2011-05-25 16 views
0

根據以下彈簧文檔link我可以使用@Async註釋使方法調用異步。我可以從我擁有的java src文件在Grails中使用此工具嗎?我可以在Grails中使用@Async註釋

[更新] 這是我的java(netty)套接字處理程序類,它接收套接字數據包。
公共類的DefaultHandler擴展SimpleChannelUpstreamHandler {

private static final Logger LOG = LoggerFactory.getLogger(DefaultHandler.class); 

private AggregateSocketData aggregateSocketData; 

@Override 
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
     throws Exception { 
    LOG.trace("In messageRecieved method with event: {}",e); 
    IEvent event = Events.dataInEvent(e.getMessage()); 
    System.out.println(Thread.currentThread().getName()); 
    aggregateSocketData.receiveSocketData(event); 
} 


@Override 
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) 
     throws Exception { 
    LOG.error("Exception occurred in Default Handler: " ,e.getCause()); 
} 

public AggregateSocketData getAggregateSocketData() { 
    return aggregateSocketData; 
} 

public void setAggregateSocketData(AggregateSocketData aggregateSocketData) { 
    this.aggregateSocketData = aggregateSocketData; 
} 

}

我已在grails-的conf豆 - resources.xml中

<bean id="defaultECM1240Handler" class="com.appcapture.buildingmgr.netty.DefaultHandler" 
     scope="prototype"> 
     <property name="aggregateSocketData" ref="binaryDataAggregatorService"></property> 
</bean> 

,這是我的Grails服務類,其方法我用@Async註解

class BinaryDataAggregatorService implements AggregateSocketData {

def rawDataService 
static transactional = true 

@Async 
void receiveSocketData(IEvent event) { 
    println Thread.currentThread().name 
    log.debug("Going to decode netty packet in receiveSocketData"); 
    Map decodedPacket = decodePacket((INettyPacket)event.getSource()) 
    def rawData = saveRawData (decodedPacket); 
    log.debug ("Saved raw data, id: ${rawData?.id}") 
    rawDataService.saveHTTPData(decodedPacket); 
} 

}

[更新2]下面是該方法調用堆棧跟蹤。 這是堆棧。 BinaryDataAggregatorService.receiveSocketData(INettyPacket)線:20 BinaryDataAggregatorService $$ FastClassByCGLIB $$ 82489f62.invoke(INT,對象,對象[])行:不可用
MethodProxy.invoke(對象,對象[])線:149
Cglib2AopProxy $ CglibMethodInvocation.invokeJoinpoint()線:688
Cglib2AopProxy $ CglibMethodInvocation(ReflectiveMethodInvocation).proceed()線:150
TransactionInterceptor.invoke(的MethodInvocation)線:110
Cglib2AopProxy $ CglibMethodInvocation(ReflectiveMethodInvocation).proceed()線:172
Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Object,Method,Object [],MethodProx y)的行:621 BinaryDataAggregatorService $$ EnhancerByCGLIB $$ 1c96985c.receiveSocketData(INettyPacket)行:不可用
DefaultHandler.handlePacket(INettyPacket)線:50

[更新3] Grails的堆棧跟蹤上設置任務:註釋驅動元素。

011-05-26 17:38:03,109 [main] ERROR context.GrailsContextLoader - Error executing bootstraps: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy12 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultECM1240Handler' defined in URL [file:./grails-app/conf/spring/resources.xml]: Cannot resolve reference to bean 'binaryDataAggregatorService' while setting bean property 'aggregateSocketData'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'binaryDataAggregatorService': Invocation of init method failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy12]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy12 

謝謝
亞伯拉罕

回答

2

如果它是一個Spring bean - 是的,你可以。對於你有@Service註釋,並有一個<context:component-scan base-package="com.foo.bar" />

但要使它更容易,你可以使用放置在grails-app/services Groovy類 - 這將是一個Spring bean自動

爲了使@Async工作,你需要在xml配置中使用<task:annotation-driven/>

+0

我添加了註釋到服務類,但在調試我無法看到另一個線程已經建立。我需要提供其他一些配置嗎? – Abe 2011-05-25 08:11:19

+0

不是我所知道的。嘗試打印當前線程ID以查看它們是否相同。而且 - 你如何獲得java類的實例? – Bozho 2011-05-25 08:37:57

+0

我沒有將註釋添加到Java類,而是將其添加到grails服務方法。既然它是默認的spring bean,我認爲它會起作用。當我印刷它時,我得到了相同的線名。 – Abe 2011-05-25 09:56:11

1

我在嘗試做同樣的事情時發現了這一點。我還沒有嘗試過,但也許它會工作。

https://gist.github.com/tux2323/2758723

ETA:

我修改我的Resources.groovy文件,以配合我發現這裏(http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html):

 xmlns task:"http://www.springframework.org/schema/task" 
     task.'annotation-driven'('executor':'myExecutor') 
     task.'executor'('id':'myExecutor', 'pool-size':'5') 

我在@Async註釋代碼仍然是使用相同的線程,據我所知。

0

我跟隨Jason H的步驟回答,它確實幫助我解決了爲我的服務設置@Async的問題。

xmlns task:"http://www.springframework.org/schema/task" 
task.'annotation-driven'('executor':'myUploadExecutor', 'proxy-target-class':true, 'mode':'proxy') 
task.'executor'('id':'myUploadExecutor', 'pool-size':'5') 

我已經在我的resources.groovy添加此代碼,那麼你就可以開始在代碼中使用@Async(不要忘記導入org.springframework.scheduling.annotation.Async你類),無 ( 'proxy-target-class':true,'mode':'proxy')你會得到一個錯誤java.lang.ClassCastException:com.sun.proxy。$ Proxy在拋出你的「服務名稱」時拋出。

在我的情況我使用@Async運行在不同的線程添加到數據庫中的東西,如果你使用@ gorm.AuditStamp爲您的域名,Spring安全上下文沒有綁定到新的線程,你會得到createdBy和updatedBy空值 。

爲了解決這個問題,我在我的BootStrap.groovy上添加了: SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)

欲瞭解更多信息,看看這個網站: http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads

相關問題