I have problem with asynchronus execution of my code.
Method startConversion() should be called asynchronusly. call goes trought AOP proxy.
Everything separated works fine. Problem occurs when I put together #Async and #MonitoredWithSpring annotations
javamelody is defined in webxml in first xml - OK
Spring async support is defiend in xml - OK
Code works well without #MonitoredWithSpring. But i need this bean to be monitored.
Sample code:
#MonitoredWithSpring //L1 - if this line removed #async will work
public interface IOfficeConversionService {
void startConversion ();
}
Implementing class
#Service
public class COfficeConversionSevice implements IOfficeConversionService {
#Override
#Transactional
#Async ("officeFileConversionExecutor")
public void startConversion () {
//ASYNC work
}
}
With L1 present, code will call method startConversion() synchronusly.
Without L1 everything works fine, and method startConversion() is called asynchronusly in new thread
In stacktrace don't even create async pointcut.
#Async annotation is never processed by its postProcessor. #Transactional works, and transaction is created. No error in initialization
Spring configuration
<context:annotation-config />
<aop:aspectj-autoproxy />
<task:executor id="mailexecutor" pool-size="25-100" queue-capacity="1000" rejection-policy="ABORT" />
<task:executor id="pnpexecutor" pool-size="5" />
<task:executor id="officeFileConversionExecutor" pool-size="5" />
<task:scheduler id="systemScheduler" pool-size="5" />
<task:annotation-driven executor="mailexecutor" scheduler="systemScheduler"/>
Can you help me? Some suggestion ?
I am out of ideas.
Related
Is there a way to turn on Spring's Async configuration from XML? All the examples I saw are using programmatic context declaration and use #EnableAsync
Is there an XML equivalent for this. In some places I saw <context:annotation-config /> being used, but this doesn't mention anything about async .
I am using Spring 4.
Did you try using this
<task:annotation-driven />
Yes, you can use something like this
<beans>
<task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>
<task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/>
<bean id="asyncBean" class="com.foo.MyAsyncBean"/>
<bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>
</beans>
According to the Spring documentation, this is equivalent to using #EnableAsync
In the annotation based approach you have to have #EnableAsync on the Configuration class. Something like as shown below:
#Configuration
#EnableAsync
#ComponentScan(basePackages ="com.spring.sample.demoAsync")
public class SpringAsyncConfig {
}
Then you create a component class to have a function that is called Asynchronously. Something like as shown below:
#Component
public class AsyncClass {
#Async
public Future<String> asyncMethod() {
System.out.println("Executing Thread Async:" +Thread.currentThread().getName());
return new AsyncResult<String>(Thread.currentThread().getName());
}
}
To have the xml equivalent of this approach, you can create a bean in the applicationContext.xml file as shown below:
<bean id="AsyncClass" class="com.spring.sample.demoAsync.AsyncClass"/>
To call the function asyncMethod() in your flow, you can refer AsyncClass bean from any other bean or service. Below is something that I tried to stitch the flow:
<bean id="callingBean" class="comspring.sample.demoAsync.CallingBeanClass">
<property name="AsyncClassBean" ref="AsyncClass"/>
</bean>
It's not necessary to follow this step but is an alternative approach.
In my applicationContext.xml file, I also imported the task schema by using:
xmlns:task="http://www.springframework.org/schema/task
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"
and then mentioning the executor as a task in the same file:
<task:executor id="myexecutor" pool-size="5" />
Now my AsyncClass looks like this without #component annotation.
public class AsyncClass {
#Async("myexecutor")
public Future<String> asyncMethod() {
System.out.println("Executing Thread Async:" +Thread.currentThread().getName());
return new AsyncResult<String>(Thread.currentThread().getName());
}
}
and then finally invoking the asyncMethod() asynchronously from the CallingBeanClass.
I am working on a Spring-MVC application in which I want to use #Async at-least for the methods which are fire-and-forget. When I try to use #Async and I have used #EnableAsync annotation too for class, the actions inside the method are not performed. When I add task executor in servlet-context.xml, then I get an error bean is getting currently created. I am new to Async, can anyone tell me how I can use it.
I am not using Eager loading btw.
Error log :
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'groupNotesService': Bean with name 'groupNotesService' has been injected into other beans [mattachService] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
Code :
GroupNotesServiceImpl :
#Service
#Transactional
#EnableAsync
public class GroupNotesServiceImpl implements GroupNotesService {
#Override
#Async
public void editGroupNote(GroupNotes mnotes, int msectionId) {
//Code to be executed, which is not getting executed
}
}
Servlet-context.xml :
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="20"/>
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<resources mapping="/resources/" location="/resources/" />
If I remove any of the mvc lines above, I get a servlet.init() threw load exception error.
Also, Is it possible to use Async where I am returning int? I checked out the Future tag, but I don't know what modifications are required.
Here is the method that returns int.
#Override
public int saveGroupNoteAndReturnId(GroupNotes mnotes, int msectionid) {
// saves note and returns its id.
}
MattachService bean :
<beans:bean id="mattachDAO"
class="com.journaldev.spring.dao.GroupAttachmentsDAOImpl">
<beans:property name="sessionFactory"
ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
<beans:bean id="mattachService"
class="com.journaldev.spring.service.GroupAttachmentsServiceImpl">
<beans:property name="groupAttachmentsDAO" ref="mattachDAO" />
</beans:bean>
Edit
I checked out that there is a problem to run #Transactional and #Async both in one class. Jira SPR-7147. The workaround suggested there was to introduce a normal facade, and I really don't know what that means.
#EnableAsync should be in configuration, not the service itself. Since you seem to use xml configuration, check this https://stackoverflow.com/a/20127051/562721. It recommends to declare org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor to take care of #Async annotations
I'm trying to call a method in Spring-powered bean asynchronously using #Async. I defined an executor in XML:
<task:executor id="emailTasksExecutor" pool-size="1" />
and here is my method:
#Override
#Async("emailTasksExecutor")
public void sendEmail()
{
...
}
And the method does not get called at all when I use qualifier (emailTasksExecutor). However, if I remove it, everything works ok. But in this case the default executor is used and I need to change this behaviour.
I thought the problem is that my class does not implement any interfaces, and something went wrong with proxies. But extracting the interface did not help.
So, the problem was my maven-aspectj-plugin. I found the solution here. All I need to do is to add mode="aspectj" to the task:annotation-driven.
I have a class MessageProcessor being called by another method in another class (i.e. Caller).
public class Caller {
#Scheduled(filxedDelay=10)
public void poll(){
//do stuff
messageProcessor.process(msg);
}
}
public class MessageProcessor{
#Async(value="abcExecutor")
public void process(String msg){
//do stuff here.
}
}
Spring file looks like:
<task:executor id="abcExecutor" pool-size="9" rejection-policy-"CALLER_RUNS"/>
I want to add another #Async executor:
#Async(value="defExecutor")
public void remove(String msg){
//do stuff here.
}
#Scheduled(filxedDelay=10)
public void kill(){
//do stuff
messageProcessor.remove(msg);
}
By adding another executor in spring file:
<task:executor id="defExecutor" pool-size="9" rejection-policy="CALLER_RUNS"/>
But how to add multiple executors in <task:annotation-driven executor="abcExecutor" scheduler="scheduler" mode="proxy" proxy-target-class="true"/>
How can I make these multiple executors run with annotation?
PS: Obviously, I don't want to have the same pool being used for both the
#Async methods
The #Async("defExecutor") is sufficient to designate the method to be handled by the 2nd executor. The xml declaration specifies only the default executor, which will be used whenever no value is specified in #Async.
See the explanation of Chris Beams in this issue:
So, is it a right XML ?
<task:executor id="abcExecutor" pool-size="9" rejection-policy-"CALLER_RUNS"/>
<task:executor id="defExecutor" pool-size="9" rejection-policy="CALLER_RUNS"/>
<task:annotation-driven executor="abcExecutor" scheduler="scheduler" mode="proxy" proxy-target-class="true"/>
My problem is that I have a function implemented on my website which searches for Particular Tweet when I press the button. I want it to make it automatic such that, that function is called again and again after every two minutes, regardless some one uses the website or not.. How to do this in java?? Spring Solution is better
You could use Spring scheduling (see documentation here)
From the doc:
XML config
<context:component-scan base-package="some.package" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Java bean
#Component
public class SomeBean {
#Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
}