Могу ли я использовать аннотацию @Async с Grails - PullRequest
0 голосов
/ 25 мая 2011

Согласно следующему источнику документов ссылка Я могу использовать аннотацию @ Async , чтобы сделать вызов метода асинхронным. Могу ли я использовать это средство в Grails из имеющегося у меня файла Java src?

[Update] Это мой класс обработчика сокета 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;
}

}

Я сделал это bean-компонентом в grails-conf - resources.xml

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

А это мой класс обслуживания Grails, метод которого я аннотировал с помощью @ Async

Класс BinaryDataAggregatorService реализует 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, Object, Object []) строка: недоступно
MethodProxy.invoke (Object, Object []) строка: 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 [], MethodProxy) строка: 621 BinaryDataAggregatorService $$ EnhancerByCGLIB $$ 1c96985c.receiveSocketData (INettyPacket) строка: недоступно
Строка DefaultHandler.handlePacket (INettyPacket): 50

[Обновление 3] Трассировка стека грааля при постановке задачи: элемент, управляемый аннотациями.

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

Спасибо,
Авраам

Ответы [ 3 ]

2 голосов
/ 25 мая 2011

Если это фасоль - да, вы можете.Для этого вы должны аннотировать его с помощью @Service и иметь <context:component-scan base-package="com.foo.bar" />

Но для облегчения вы можете использовать класс groovy, помещенный в grails-app/services - это будет пружинный боб

Чтобы заставить @Async работать, вам нужно <task:annotation-driven/> в конфигурации xml.

1 голос
/ 14 января 2014

Я нашел это, пытаясь сделать то же самое. Я еще не пробовал, но, возможно, это сработает.

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 голосов
/ 21 июля 2016

Я следовал шагу из ответа Джейсона Н, и это действительно помогло мне решить проблему с настройкой @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 Security не привязан к новому потоку, вы получите createBy и обновлены по NULL.

Чтобы решить эту проблему, я добавил: SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) в моемBootStrap.groovy по init.

Для получения дополнительной информации посетите этот сайт: http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...