Grails - 在背景上运行TCP线程

时间:2014-06-06 20:39:48

标签: hibernate grails

我希望有一个应用程序可以侦听TCP套接字连接,并且可以对它们作出反应。为此,我需要在启动时启动后台线程 - 我可以在BootStrap.groovy中执行此操作。

对于背景线程,我下载了executor plugin

代码如下所示:

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!"
        }
    }
}
}

此代码是来自another thread的复制粘贴,位于SO。

我收到此错误:

| 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

似乎未填充myService对象。我需要编辑一些配置吗?


编辑:尝试使用executorService,但这也无济于事。

| 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

5 个答案:

答案 0 :(得分:2)

我在这里创建了一个简短的SocketServer示例(称为'gsocket'): https://github.com/m-schneider/gsocket 如果您不是在'BootStrap.groovy'中定义服务类的先决条件,它应该符合您的需求 - 希望;) 套接字服务器客户端(client.groovy)也在主文件夹中进行快速测试。

希望有所帮助。

答案 1 :(得分:2)

您应该将服务类移动到Grails项目中的正确文件夹。

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!"
        }
    }
}

答案 2 :(得分:2)

你应该按照@Fabrizio D' Ammassa的建议将你的doSomethoing()方法转移到一个单独的服务,如果你不想将你的代码移动到单独的服务,那么你可以实现这个目标,如下所示:

class BootStrap {


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


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

}

答案 3 :(得分:2)

好吧,我想你应该看看这个插件:http://grails.org/plugin/routing

该插件基于apache camel http://camel.apache.org/。它有很多可以使用的选项和组件。我在HL7集成中使用了很多,我们在TCP套接字上发送和接收响应。最简单的TCP示例是:

import org.apache.camel.builder.RouteBuilder

class MyMessageRoute extends RouteBuilder {  

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

因此,无论是什么,localhost 9090都会打印到您的控制台。您的主机和端口将在应用程序启动后立即启动,即使您运行集成测试,端口也将正在侦听。要运行它,您需要安装路由插件,并在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') {
    }
}

您甚至可以在netty上使用mina2。有关它们与apache camel集成的更多信息,请查看以下文档。

Netty组件:http://camel.apache.org/netty.html

Mina2组件:http://camel.apache.org/mina2.html

所有骆驼组件:http://camel.apache.org/components.html

希望这会有所帮助!!

答案 4 :(得分:1)

不,填充myService对象。

class MyService {
    def executorService

    def doSomething() {

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

    }
}

如果您有执行程序插件,请使用此代替runsync

如果MyService的依赖注入不起作用,请清理您的应用:

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