Martin Melka
Martin Melka

Reputation: 7789

Grails - running a TCP thread on background

I want to have an app that listens to TCP socket connections and can react to them. In order for that I need to start a background thread on start - I can do that in BootStrap.groovy.

For the background threading I downloaded the executor plugin.

The code looks like this:

class BootStrap {

def myService

def init = { servletContext ->
    log.info("Bootstrapping")
    development {
        log.info("Doing myService async ")
        myService.doSomething()
    }
}

class MyService {
    def doSomething() {
        runAsync {
            println "Running!"
        }
    }
}
}

This code is a copy-paste from an another thread here at SO.

I am getting this error:

| Error 2014-06-06 22:30:37,317 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: Cannot invoke method doSomething() on null object
Message: Cannot invoke method doSomething() on null object
    Line | Method
->>   14 | doCall                       in BootStrap$_closure1_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

It seems that the myService object is not populated. Do I need to edit some configs or something?


Edit: tried to use executorService, but that didn't help either.

| Error 2014-06-07 00:06:36,099 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: Cannot invoke method doSomething() on null object
Message: Cannot invoke method doSomething() on null object
    Line | Method
->>   14 | doCall                       in BootStrap$_closure1_closure2

Upvotes: 1

Views: 612

Answers (5)

Lalit Agarwal
Lalit Agarwal

Reputation: 2354

Well, I think you should have a look at this plugin: http://grails.org/plugin/routing

The plugin is based on apache camel http://camel.apache.org/ . It has lot of options and components which you could use. I have used it a lot for HL7 integration where we send and receive responses on TCP socket. The simplest example of a TCP would be:

import org.apache.camel.builder.RouteBuilder

class MyMessageRoute extends RouteBuilder {  

    from('mina2:tcp://localhost:9090').to('stream:out') 
 }
}

So, whatever comes on localhost 9090 will be printed to your console. Your host and port will start as soon as your application is up and even when you run integration tests, the port will be listening. To run this you will need to have the routing plugin installed and also have below dependencies in you BuildConfig.groovy

dependencies {
    // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

    runtime "org.apache.mina:mina-core:2.0.7"
    runtime "org.apache.mina:mina-integration-spring:1.1.7"        
    runtime "org.apache.camel:camel-mina2:2.13.0"
    compile('org.apache.poi:poi-ooxml:3.8') {
    }
}

You could even use netty instead on mina2. For more info on their integration with apache camel look at below docs.

Netty component: http://camel.apache.org/netty.html

Mina2 Component: http://camel.apache.org/mina2.html

All camel components: http://camel.apache.org/components.html

Hope this helps!!

Upvotes: 2

Anand Kushwaha
Anand Kushwaha

Reputation: 457

You should move your doSomethoing() method to a separate service as suggested by @Fabrizio D'Ammassa, and if you don't want to move your code to separate service than you can achieve this goal as follow :

class BootStrap {


def init = { servletContext ->
    log.info("Bootstrapping")
    development {
        log.info("Doing myService async ")
        doSomething()
    }
}


    def doSomething() {
        runAsync {
            println "Running!"
        }
    }

}

Upvotes: 2

Fabrizio D'Ammassa
Fabrizio D'Ammassa

Reputation: 4769

You should move the service class to the proper folder in Grails project.

Bootstrap.groovy

class BootStrap {

   def myService

   def init = { servletContext ->
      log.info("Bootstrapping")
      development {
         log.info("Doing myService async ")
         myService.doSomething()
      }
   }

}

MyService.groovy

class MyService {
    def doSomething() {
        runAsync {
            println "Running!"
        }
    }
}

Upvotes: 2

schneidermatic
schneidermatic

Reputation: 43

I've created a short SocketServer example (called 'gsocket') here: https://github.com/m-schneider/gsocket In the case where it's not a prerequisite that you define your service class in 'BootStrap.groovy' it should fit your needs - hopefully ;) A Socket Server client (client.groovy) is also in the main folder for rapid testing.

Hope that helps.

Upvotes: 2

Abdennour TOUMI
Abdennour TOUMI

Reputation: 93173

no , myService object is populated.

class MyService {
    def executorService

    def doSomething() {

        executorService.submit({
                println "Running!"
            } as Callable)

    }
}

Use this instead of runsync ,if you have executor plugin .

And if Dependency Injection of MyService did not work , clean your app :

grails stop-app
grails clean-all
grails refresh-dependencies
grails run-app

Upvotes: 1

Related Questions