How to combine #Scheduled with Profiles - java

I've got a class that Spring finds via component scan and that has a method annotated with #Scheduled:
#Component
public class Foo {
...
#Scheduled(fixedDelay = 60000)
public void update() {
...
The value 60000 is ok for production, but in my tests I want it to be 1000.
How can I achieve that? E.g., can I combine #Scheduled with profiles somehow?

Make delay as property:
#Component
public class Foo {
...
#Scheduled(fixedDelay = ${delay})
public void update() {
You may keep 2 property files. For example dev.properties and prod.properties
Spring will load one of it.
<context:property-placeholder
location="classpath:${spring.profiles.active}.properties" />

Create two beans, one for production and one for testing and annotate both with #Profile accordingly like below
#Bean
#Scheduled(fixedDelay = 1000)
#Profile("test")
public void update() {
}
#Bean
#Scheduled(fixedDelay = 60000)
#Profile("dev")
public void update() {
}
In your unit test class you can switch between them by activating the relevant profile like below
#RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "classpath:/app-config.xml"
#ContextConfiguration("/app-config.xml")
#ActiveProfiles("dev") //or switch to #ActiveProfiles("test") when testing
public class TransferServiceTest {
#Autowired
private TransferService transferService;
#Test
public void testTransferService() {
// test the transferService
}
}
If #ActiveProfiles("dev") is activated only the dev #scheduled bean will be created otherwise test if the test profile is activated.

I solved this issue like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans ... xmlns:task="http://www.springframework.org/schema/task"
... xsi:schemaLocation="... http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd ...>
<!-- Everything for "default" profile, including the bean with "#Scheduled(fixedDelay = 60000)" on UpdaterTracker.update() and the "taskScheduler" bean -->
...
<!-- Activate this profile in Arquillian tests -->
<beans profile="arquillian">
<!-- Update more frequently -->
<bean id="updaterTracker" class="com.foo.UpdaterTracker"/>
<task:scheduled-tasks scheduler="taskScheduler">
<task:scheduled ref="updaterTracker" method="update" fixed-delay="1000"/>
</task:scheduled-tasks>
</beans>
</beans>
The first part defines the beans as usual, including an instance of the UpdaterTracker-bean that performs update() every 60 seconds. The last part is only activated in case "arquillian" profile is active, defining another instance of the UpdaterTracker-bean and a scheduled task that executes update() every second.
The solution is not perfect, because it produces 2 instances of UpdaterTracker and 3 scheduled tasks. It could be optimized by directly referencing the first UpdaterTracker instance in so that we get 1 instance and 2 scheduled tasks.
However, this works for me and the solution has advantages: It does not require additional beans to be coded and can cope with multiple profiles.

Related

Spring scheduled tasks: from XML to annotation

In our Spring web-application, we are moving from XML based configuration to Annotation based configuration.
I'm stuck with a scheduled task defined with this XML
<task:scheduled-tasks scheduler="cacheScheduler">
<task:scheduled ref="currencyExchangeRateTask" method="cacheCurrencyExchangeRates" cron="0 0 8,20 * * *" />
</task:scheduled-tasks>
There are multiple schedulers in our web-application. And this task needs to be executed on the scheduler with id cacheScheduler.
I have now the following annotation in place
#Scheduled(cron = "0 0 8,20 * * *")
public void cacheCurrencyExchangeRates() {
...
}
This is executing on the default scheduler.
How can this be fixed without XML configuration?
You can't do it through #Scheduled directly. It doesn't provide any annotation members to specify a bean reference name.
Instead, you have to use SchedulingConfigurer. Define a #Configuration class. Annotate it with #EnableScheduling and #ComponentScan for the packages with component types that have #Scheduled annotated methods. Then have the class implement SchedulingConfigurer.
The ScheduledTaskRegistrar provided through its configureTasks method lets you set a task scheduler.
For example:
#Configuration
#ComponentScan("com.example.tasks")
#EnableScheduling
class Tasks implements SchedulingConfigurer {
#Bean
public TaskScheduler cacheScheduler() {
return new ThreadPoolTaskScheduler();
}
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(cacheScheduler());
}
}
All the #Scheduled methods discovered through this #Configuration class will now be using the TaskScheduler defined within.
If you need different #Scheduled methods to use different TaskScheduler instances, you'll need different #Configuration classes, similarly to needing different <task:scheduled-tasks .../> elements.

Spring & JUnit: Spring instantiates two instances of test class, only injects dependencies for one, runs the other one

What I'm trying to do: Run a single JUnit test (one JUnit test class with a single test method). Test class has one dependency that I expect Spring to handle (inject) prior to running the test.
What I see: Test class is instantiated twice, dependency is satisfied (injected) for one of the instances but not the other. Test is run using the instance for which dependencies are not injected.
My guess: I'm speculating that the test class is instantiated twice because Spring is using the first instance to analyze dependencies (probably using reflection to look for annotations, which I'm not using).
But: I cannot for my life figure out why the test class instance for which the dependency is not created/injected is used to run the test.
test.xml
<beans ...>
<bean id="test" class="com.example.MyTestClass">
<property name="primaryDependency" ref="pridep"/>
</bean>
<bean id="pridep" class="com.example.MyPrimaryDependency">
<property name="dataSource" ref="ds"/>
</bean>
<bean id="ds" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"/>
</beans>
MyTestClass.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:test.xml"})
public class MyTestClass {
private IPrimaryDependency mDep = null;
public MyTestClass() {
}
public void setPrimaryDependency(IPrimaryDependency dep) {
mDep = dep;
}
#Before
public void createImageData() {
}
#Test
public void testImageSearch() {
assertNotNull("mDep is null", mDep);
}
}
MyPrimaryDependency.java
public class MyPrimaryDependency extends RequiresADataSource implements IPrimaryDependency {
public MyPrimaryDependency() {
}
}
Existing related question: Spring dependency injection null when running a test case, but I'm not able to discern what's going on from that answer.
Sorry for the rookie question-- I've been scouring documentation (and bothering colleagues) for several days and am baffled by this.
Thanks!
Add #Autowired
#Autowired
private IPrimaryDependency mDep;
Explanation:
JUnit creates brand new instances of test classes for each test.
Spring JUnit runner only extends this behaviour by "preparing" created objects which basically means setting up application context and injecting annotation driven dependencies.
In your case the test class is instantiated twice: From test.xml (the property is injected there) and by JUnit runner to run the first test method.
However when created by JUnit, Spring has no idea that it needs to inject something because there are no annotations in the class thus the property ends up being null.
See source code of SpringJUnit4ClassRunner and DependencyInjectionTestExecutionListener for implementation details.
Your test class is
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:test.xml"})
public class MyTestClass {
You run this class with JUnit. Because of #RunWith, JUnit uses an instance of SpringJUnit4ClassRunner to instantiate the class and run its tests.
Because of #ContextConfiguration, the ClassRunner will generate an ApplicationContext by loading your test.xml file.
That test.xml file has a <bean> definition for your test class
<bean id="test" class="com.example.MyTestClass">
<property name="primaryDependency" ref="pridep"/>
</bean>
So Spring will also generate an instance and set the appropriate property.
Basically, what I'm getting at is that your test class shouldn't be a bean in the Spring context. Create a different test class and inject the bean that has an injection target and inject that into your test class.

How do I unit-test Maven multi-module Spring app?

I'm having problems trying to unit test a maven multi-module project with Spring.
I've 4 modules:
application-core
application-data
application-service
application-web
This is my test, its in the application-core module:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/config/application-context.xml")
public class TicketTest {
#Mock
ITicketDAO ticketDAO;
#Autowired
#InjectMocks
ITicketCore ticketCore;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testRegisterTicket_Ticket_NotUsed_isValid() {
Long ticketNumber = 0L;
when(ticketDAO.getTicket(anyLong())).thenReturn(null);
final boolean isValidTicket = ticketCore.validateTicket(ticketNumber);
assertTrue(isValidTicket);
}
}
And here is the implementation:
#Component
#Scope("prototype")
public class TicketCore implements ITicketCore{
private ITicketDAO ticketDao;
#Autowired
public TicketCore(ITicketDAO ticketDao) {
this.ticketDao = ticketDao;
}
#Override
public boolean validateTicket(Long ticketNumber) {
ITicket ticket = ticketDao.getTicket(ticketNumber);
return ticket != null;
}
}
Interface:
public interface ITicketDAO {
ITicket getTicket(Long ticketNumber);
}
Implementation of ITicketDAO its on the application-data module:
#Service
public class TicketDAO implements ITicketDAO {
#Override
public ITicket getTicket(Long ticketNumber) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}
I'm having problems testing this code because the context doesn't find the implementation of ITicketDAO. It's seems obvious, because when the test are running, JUnit doesn't care about putting in the classpath the "others modules".
Spring throws BeanCreationException for obvious reasons.
Am I right?
So I would like to test my project without Spring getting in the tests' way.
What could I do to get my tests run w/o any problem???
I've created dummy classes in the test folder/packages, and it works, but...
I would eventually have ALL the external implementations in my application-core module's test folder.
There is a better way?
Thanks in advance.
UPDATE:
application-data
application-service
application-web
all of them depends on application-core. Spring successfully inject TicketCore(application-core). What I want is to give Spring "something" (a dummy class) to inject in ITicketDAO just to run the test.
<beans>
<context:component-scan base-package="ve.gov.imat.transimat" />
<context:annotation-config />
<aop:config proxy-target-class="true" />
</beans>
Pretend that each Maven module is a completely separate project. Put tests specifically of each module's code inside it, and add integration tests in the module where all of the dependencies necessary to run them have been included.
You haven't provided any information on the dependencies between your modules, but it appears that the problem you're running into is that you need some implementation of an interface for testing purposes, but your production bean is defined in another module. This is what mocking frameworks like EasyMock and Mockito are for; they allow you to write simple placeholder implementations so that you can test TicketCore specifically, and it's a good idea to use them even when the real implementation is available so that you can be sure you're just testing one component at a time.
In TicketTest, you're correctly defining your Mockito mock for ITicketDAO, but your TicketCore is still trying to autoacquire the bean from Spring, even though you haven't registered it. Either manually register your bean into the test context, or place the definition for the mock in an #Configuration in src/test.
If I've understood you well your problem is your context file references a class you don't have available in your test classpath.
In principle tests shouldn't need the implementation of any collaborator to work, only the one of the sut.
One solution is to create an application-test-context.xml file under your test/resources folder to be used in your test instead of the production one. Within this file you can create the mocks of your collaborators
<!-- Mock service for splitting jobs -->
<bean factory-bean="mockControl" factory-method="createMock"
primary="true">
<constructor-arg value="net.compart.docpilot.model.service.JobSplitService" />
</bean>

JUnit: Can I keep the common parts of the spring context?

I have some unit tests with Spring. All the tests load a spring configuration file, and then add some more.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:beans.xml" }, inheritLocations = true)
public abstract class TestBase {
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:extraBeansOne.xml" }, inheritLocations = true)
public class TestOne extends TestBase {
#Test
public void testA() {
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:extraBeansTwo.xml" }, inheritLocations = true)
public class TestTwo extends TestBase {
#Test
public void testB() {
}
}
There's also a suite with the two tests:
#RunWith(Suite.class)
#Suite.SuiteClasses({ TestOne.class, TestTwo.class })
public class TestSuite {
}
In the common spring configuration file, I have a bean:
<beans ...>
<bean id="testBean" class="com.example.TestBean" />
<bean>
The problem is that, when I run the suite, the testBean gets loaded twice, once for each test class. Since it is defined in a common configuration file, is there any way to prevent it from loading multiple times?
No there is not really a chance to reuse them.
The Spring Junit Runner reuses the spring contexts over different tests, but only if there files are the same.
9.3.2.1 Context management and caching
...
Test classes provide an array containing the resource locations of XML configuration metadata - typically in the classpath - that is used to configure the application. These locations are the same as or similar to the list of configuration locations specified in web.xml or other deployment configuration files.
If this is very important for you and you are willing to spend time on it, then you can try to implement something that bases on the fact that application context can have a parent (like the two contexts in web applications, one defined for ContextLoaderListener the other defined for DispatcherServlet)) Then it is may possible to use/reuse the parent context in different test method dependend child contexts.
#See Spring Reference: Chapter 9.3.5.2 Context management and caching

Spring #Async Not Working

An #Async method in a #Service-annotated class is not being called asynchronously - it's blocking the thread.
I've got <task: annotation-driven /> in my config, and the call to the method is coming from outside of the class so the proxy should be being hit. When I step through the code, the proxy is indeed hit, but it doesn't seem to go anywhere near any classes related to running in a task executor.
I've put breakpoints in AsyncExecutionInterceptor and they never get hit. I've debugged into AsyncAnnotationBeanPostProcessor and can see advice getting applied.
The service is defined as an interface (with the method annotated #Async there for good measure) with the implementation's method annotated #Async too. Neither are marked #Transactional.
Any ideas what may have gone wrong?
-=UPDATE=-
Curiously, it works only when I have my task XML elements in my app-servlet.xml file, and not in my app-services.xml file, and if I do my component scanning over services from there too. Normally I have one XML file with only controllers in it (and restrict the component-scan accordingly), and another with services in it (again with a component-scan restricted such that it doesn't re-scan the controllers loaded in the other file).
app-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"
>
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="7"/>
<!-- Enable controller annotations -->
<context:component-scan base-package="com.package.store">
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> -->
</context:component-scan>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
app-services.xml (doesn't work when specified here)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<!-- Set up Spring to scan through various packages to find annotated classes -->
<context:component-scan base-package="com.package.store">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<task:annotation-driven executor="han" />
<task:executor id="han" pool-size="6"/>
...
Am I missing something glaringly obvious in my configuration, or is there some subtle interplay between config elements going on?
For me the solution was to add #EnableAsync on my #Configuration annotated class:
#Configuration
#ComponentScan("bla.package")
#EnableAsync
public class BlaConfiguration {
}
Now the class in package bla.package which has #Async annotated methods can really have them called asynchronously.
With the help of this excellent answer by Ryan Stewart, I was able to figure this out (at least for my specific problem).
In short, the context loaded by the ContextLoaderListener (generally from applicationContext.xml) is the parent of the context loaded by the DispatcherServlet (generally from *-servlet.xml). If you have the bean with the #Async method declared/component-scanned in both contexts, the version from the child context (DispatcherServlet) will override the one in the parent context (ContextLoaderListener). I verified this by excluding that component from component scanning in the *-servlet.xml -- it now works as expected.
Jiří Vypědřík's answer solved my problem. Specifically,
Check if your method annotated with #Async is public.
Another useful information from Spring tutorials https://spring.io/guides/gs/async-method/:
Creating a local instance of the FacebookLookupService class does NOT
allow the findPage method to run asynchronously. It must be created inside
a #Configuration class or picked up by #ComponentScan.
What this means is that if you had a static method Foo.bar(), calling it in that manner wouldn't execute it in async, even if it was annotated with #Async. You'll have to annotate Foo with #Component, and in the calling class get an #Autowired instance of Foo.
Ie, if you have a annotated method bar in class Foo:
#Component
class Foo {
#Async
public static void bar(){ /* ... */ }
#Async
public void bar2(){ /* ... */ }
}
An in your caller class:
class Test {
#Autowired Foo foo;
public test(){
Foo.bar(); // Not async
foo.bar(); // Not async
foo.bar2(); // Async
}
}
Edit: Seems like calling it statically also doesn't execute it in async.
Hope this helps.
Try adding proxy-target-class="true" to all <*:annotation-driven/> elements that support this attribute.
Check if your method annotated with #Async is public.
In my case the #Async method was defined in same class as the sync method that used it, and that apparently caused all jobs to hang on current thread.
Bad
#Component
#EnableAsync
public class TranslationGapiReader {
#Async
public CompletableFuture<GapiFile> readFile(String fileId) {
try { Thread.sleep(2000); } catch (Exception exc) { throw new RuntimeException("ololo", exc); }
return CompletableFuture.completedFuture(null);
}
public Stream<GapiFile> readFiles(Iterable<String> fileIds) {
List<CompletableFuture<GapiFile>> futures = new ArrayList<>();
for (String fileId: fileIds) {
futures.add(readFile(fileId));
}
return Stream.empty();
}
}
Good
#Component
#EnableAsync
public class AsyncGapiFileReader {
#Async
public CompletableFuture<TranslationGapiReader.GapiFile> readFile(String fileId) {
try { Thread.sleep(2000); } catch (Exception exc) { throw new RuntimeException("ololo", exc); }
return CompletableFuture.completedFuture(null);
}
}
#Component
#EnableAsync
public class TranslationGapiReader {
#Autowired
AsyncGapiFileReader asyncGapiFileReader;
public Stream<GapiFile> readFiles(Iterable<String> fileIds) {
List<CompletableFuture<GapiFile>> futures = new ArrayList<>();
for (String fileId: fileIds) {
futures.add(asyncGapiFileReader.readFile(fileId));
}
return Stream.empty();
}
}
I'm not Spring guru enough to understand why does it only work when the #Async method is in a different class, but that's what fixes the issue from my observations.
Firstly make your .xml config looks like:
<task:scheduler id="myScheduler" pool-size="10" />
<task:executor id="myExecutor" pool-size="10" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" proxy-target-class="true" />
(Yes, scheduler count and executor thread pool size is configurable)
Or just use default:
<!-- enable task annotation to support #Async, #Scheduled, ... -->
<task:annotation-driven />
Secondly make sure #Async methods are public.
#Async can not be used in conjunction with lifecycle callbacks such as #PostConstruct. To asynchonously initialize Spring beans you currently have to use a separate initializing Spring bean that invokes the #Async annotated method on the target then.
public class SampleBeanImpl implements SampleBean {
#Async
void doSomething() { … }
}
public class SampleBeanInititalizer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
#PostConstruct
public void initialize() {
bean.doSomething();
}
}
source
I realized following the tutorial async-method tutorial code that my issue source was: the bean with the annotated #Async method was not being created wrapped in a proxy.
I started digging and realized that there was a message saying
Bean 'NameOfTheBean' is not eligible for getting processed by all
BeanPostProcessors (for example: not eligible for auto-proxying)
You can see here responses about this issue and its basically that BeanPostProcessors are required by every Bean, so every bean injected here and its dependencies will be excluded to be processed later by other BeanPostProcessors, because it corrupted the life cycle of beans. So identify which is the BeanPostProcessor that is causing this and dont use or create beans inside of it.
In my case i had this configuration
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Autowired
private Wss4jSecurityInterceptor securityInterceptor;
#Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(securityInterceptor);
interceptors.add(payloadLoggingInterceptor);
}
}
WsConfigurerAdapter is actually a BeanPostProcessor and you realize it because there is always a pattern: #Configuration that extends classes and override some of it functions to install or tweak beans involved in some non functional features, like web service or security.
In the aforementioned example you have to override the addInterceptors and added interceptors beans, so if you are using some annotation like #Async inside DefaultPayloadLoggingInterceptor it wont work. What is the solution? Get ride of WsConfigurerAdapter to start.
After digging a bit i realized a class named PayloadRootAnnotationMethodEndpointMapping at the end was which had all valid interceptors, so i did it manually insted of overriding a function.
#EnableWs
#Configuration
public class WebServiceConfig {
#Autowired
private Wss4jSecurityInterceptor securityInterceptor;
#Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
#Autowired
public void setupInterceptors(PayloadRootAnnotationMethodEndpointMapping endpointMapping) {
EndpointInterceptor[] interceptors = {
securityInterceptor,
payloadLoggingInterceptor
};
endpointMapping.setInterceptors(interceptors);
}
}
So this will be run after all BeanPostProcessor have done their job. The setupInterceptors function will run when that party is over and install the interceptors beans. This use case may be extrapolated to cases like Security.
Conclusions:
If you are using a #Configuration extending from some class that runs some given functions automatically and you override them, you are probably inside of a BeanPostProcessor, so dont inject beans there and try to use AOP behaviour, because it wont work, and you will see Spring tells it to you with the beforementioned message in the console. In those cases dont use beans but objects (using the new clause).
If you need to use beans digg about which class is carrying the beans you want to setup at the end, #Autowired it and add those beans like i did before.
I hope this may save some time for you.
You need 3 lines of code for Async to work
in applicationContext.xml
At class level #EnableAsync
#Async at method level
#Service
#EnableAsync
public myClass {
#Async
public void myMethod(){
}
write a independent Spring configuration for asynchronous bean.
for example:
#Configuration
#ComponentScan(basePackages="xxxxxxxxxxxxxxxxxxxxx")
#EnableAsync
public class AsyncConfig {
/**
* used by asynchronous event listener.
* #return
*/
#Bean(name = "asynchronousListenerExecutor")
public Executor createAsynchronousListenerExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100);
executor.initialize();
return executor;
}
}
I overcome this problem with this situation.
Try below:
1. In config create bean for ThreadPoolTaskExecutor
#Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
2. In service method where #Async is used add
#Async("threadPoolTaskExecutor")
public void asyncMethod(){
//do something
}
This should get #Async working.

Categories