que mvc example espaƱol java spring spring-mvc executorservice spring-websocket

java - mvc - Problema de Spring Async al actualizar de 4.2.0.RC3 a 4.2.0.RELEASE



spring mvc wikipedia (3)

Agregar el bean en la configuración de contexto de la aplicación Spring.

@Configuration @EnableAsync public class AppContext extends WebMvcConfigurationSupport { @Bean public Executor taskExecutor() { return new SimpleAsyncTaskExecutor(); } }

Le sugiero que se refiera a linuxism.tistory.com/2076

Si declara sus ejecutores en XML, puede crear una clase y denominarlo TaskExecutor. Luego, cuando Spring trate de encontrar el bean TaskExecutor, encontrará este.

@Component public class TaskExecutor extends SimpleAsyncTaskExecutor { }

Tengo una aplicación web que utiliza los artefactos spring (4.2.x) spring-webmvc, spring-messaging, spring-websocket

Tengo las siguientes anotaciones @ Enable * en mi clase java spring config

@EnableWebMvc @EnableWebSocketMessageBroker @EnableAsync @EnableMBeanExport

WebSocket se utiliza para transmitir mensajes a los clientes del navegador. Y hay pocos métodos asíncronos anotados con @Async

La aplicación funcionaba bien con la versión de primavera 4.2.0.RC3. Pero cuando lo cambié a la versión 4.2.0.RELEASE de GA, obtengo la siguiente excepción al inicio. Si elimino @EnableAsync, funciona bien, pero necesito la funcionalidad asíncrona.

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.core.task.TaskExecutor] is defined: expected single matching bean but found 4: clientOutboundChannelExecutor,messageBrokerTaskScheduler,clientInboundChannelExecutor,brokerChannelExecutor org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:366) org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332) org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor.setBeanFactory(AsyncAnnotationBeanPostProcessor.java:128) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1597) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1565) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201) org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:228) org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:682) org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:522) org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667) org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:539) org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493) org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)


Para aquellos que, como yo, que todavía están usando la configuración XML pasada de moda ...

Esto estaba funcionando para mí antes de la primavera 4.2:

<task:annotation-driven /> <task:executor id="executorA" pool-size="50" /> <task:executor id="executorB" pool-size="100" /> @Async("executorA") public void executeA() {} @Async("executorB") public void executeB() {}

Como señala Artem, Spring 4.2 se está confundiendo acerca de qué grupo usar para los métodos asíncronos sin calificador, incluso cuando no tiene dichos métodos en su aplicación.

Para arreglarlo, utilicé esto:

<task:annotation-driven executor="defaultExecutor"/> <task:executor id="defaultExecutor" pool-size="1" queue-capacity="0"/> <task:executor id="executorA" pool-size="50" /> <task:executor id="executorB" pool-size="100" /> @Async("executorA") public void executeA() {} @Async("executorB") public void executeB() {}

Tenga en cuenta que si agrega métodos @Async sin calificador, esos métodos utilizarán el grupo de subprocesos defaultExectuor:

@Async public void myDefaultExecute() {}

Y, por supuesto, las llamadas executeA () utilizarán un grupo de subprocesos executorA y las llamadas executeB () utilizarán un grupo de subprocesos executorB.

Espero que ayude.


Uno de sus @Configuration debe implementar AsyncConfigurer para especificar el TaskExecutor particular para los métodos de @Async .

De lo contrario, se confunde cuál elegir en el contexto de applicationContext .

Incluso si funcionó con RC3 , no importa que sea correcto, por lo tanto, el error se ha corregido para GA .

ACTUALIZAR

El código fuente en el AsyncAnnotationBeanPostProcessor ve así:

Executor executorToUse = this.executor; if (executorToUse == null) { try { // Search for TaskExecutor bean... not plain Executor since that would // match with ScheduledExecutorService as well, which is unusable for // our purposes here. TaskExecutor is more clearly designed for it. executorToUse = beanFactory.getBean(TaskExecutor.class); } catch (NoUniqueBeanDefinitionException ex) { try { executorToUse = beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, TaskExecutor.class); } catch (NoSuchBeanDefinitionException ex2) { throw new IllegalStateException("More than one TaskExecutor bean exists within the context, " + "and none is named ''taskExecutor''. Mark one of them as primary or name it " + "''taskExecutor'' (possibly as an alias); or specify the AsyncConfigurer interface " + "and implement getAsyncExecutor() accordingly.", ex); } } catch (NoSuchBeanDefinitionException ex) { logger.debug("Could not find default TaskExecutor bean", ex); // Giving up -> falling back to default executor within the advisor... } }

Entonces, supongo que antes de pasar de RC3 a GA ha tenido un bean taskExecutor al respecto.

Como vemos por StackTrace, ya existe un bean ...