Spring XML equivalent of #EnableAsync - java

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.

Related

Spring scheduler is not starting [duplicate]

I have a problem with Spring's annotation based task scheduler - I can't get it working, I don't see any problem here...
application-context.xml
<task:scheduler id="taskScheduler" />
<task:executor id="taskExecutor" pool-size="1" />
<task:annotation-driven executor="taskExecutor" scheduler="taskScheduler" />
bean
#Service
public final class SchedulingTest {
private static final Logger logger = Logger.getLogger(SchedulingTest.class);
#Scheduled(fixedRate = 1000)
public void test() {
logger.debug(">>> Scheduled test service <<<");
}
}
Spring #Configuration (non-xml configuration) for annotation-driven tasks
Just add #EnableScheduling on your WebMvcConfig class
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#EnableWebMvc
#EnableAsync
#EnableScheduling
public class WebMvcConfig implements WebMvcConfigurer {
/** Annotations config Stuff ... **/
}
If you want to use task:annotation-driven approach and your #Scheduled annotation is not working, then you most probably missed context:component-scan in your context xml.
Without this line, spring cannot guess where to search for your annotations.
<context:component-scan base-package="..." />
This is happening because by default Spring lazy initializes the beans.
Disable lazy initialization for the bean by placing this annotation
#Lazy(false)
on top of your #Component.
For me the solution that worked in Spring 5 was that I had to add #Component to the class having #Scheduled annotated methods.
After configuring the Schedulers, add #EnableScheduling in your main class.
I finally found a solution.
application-context.xml
<bean id="schedulingTest" class="...SchedulingTest" />
<task:scheduled-tasks>
<task:scheduled ref="schedulingTest" method="test" cron="* * * * * ?"/>
</task:scheduled-tasks>
and the test() method without the annotation. This runs the method every second and works perfectly.
if you have dispatcher-servlet.xml move your configuration there. it worked for me and i have left a comment in this article:
https://stackoverflow.com/a/11632536/546130
The solution for me was to add in the applicationContext.xml:
<task:annotation-driven/>
with the following schemaLocation:
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
You should also check lazy-init to be false for that bean or use default-lazy-init="false" in beans.
That solved my problem.
I had to update my dispatcher-servlet.xml with
<beans xmlns="http://www.springframework.org/schema/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.3.xsd"></beans>
Bean definition below:
<bean id="scheduledTasks" class="com.vish.services.scheduler.ScheduledTasks"></bean>
We had the following reason:
Service needed an interface (due to Transaction annotation) - IDE added this tx annotation also to interface. But #Scheduled was in implementing service class - and Spring ignored it since it thought that only annotations exist on the interface. So be careful to only have annotations on implementing classes!
Just add #EnableScheduling at any spring boot configuration class annotated with #Configuration and for the method that run the schedule job add #Scheduled annotation.
Maybe it will be useful for someone. I ran into similar issue when I had a bean that did a long processing job in PostConstruct method. Thus, Spring Boot application didn't start (because PostConstruct method was in progress) and that's why my scheduled jobs didn't run (they start running after application startup).
If you are using Grails with Spring Scheduler you will need to add to the top of your class.
static lazyInit = false
Source

#Async with JavaMelody #MonitoredWithSpring not working

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.

JobParameters from Spring Batch

I am trying to inject job parameters into a custom ItemReader. I have reviewed all of the StackOverflow notes on the subject (example: How to get access to job parameters from ItemReader, in Spring Batch?), and I see this is a common pain point that is mostly unresolved. I am hoping that a spring guru (#Michael Minella anyone) will see this and have some insight.
I have got as far as determining that the jobparameters are available about one out of 10 runs, even with no code or configuration changes. This is a case of a random success rather than a random failure, so it's proving hard to track down.
I dug into the spring code with the debugger, and determined that when this fails, no bean of the name jobParameters is registered in Spring at the time that the injection is taking place.
I am using Spring 4.1.4 with spring-batch 3.0.2 and spring-data-jpa 1.7.1 and spring-data-commons 1.9.1, running in java 8.
Java class
#Component("sourceSelectionReader")
#Scope("step")
public class SourceSelectionReaderImpl
implements ItemReader<MyThing> {
private Map<String,Object> jobParameters;
// ... snip ...
#Autowired
#Lazy
#Qualifier(value="#{jobParameters}")
public void setJobParameters(Map<String, Object> jobParameters) {
this.jobParameters = jobParameters;
}
}
Job launch parameters:
launch-context.xml job1 jobid(long)=1
launch-context.xml (minus the fluff):
<context:property-placeholder location="classpath:batch.properties" />
<context:component-scan base-package="com.maxis.maximo.ilm" />
<jdbc:initialize-database data-source="myDataSource" enabled="false">
<jdbc:script location="${batch.schema.script}" />
</jdbc:initialize-database>
<batch:job-repository id="jobRepository"
data-source="myDataSource"
transaction-manager="transactionManager"
isolation-level-for-create="DEFAULT"
max-varchar-length="1000"/>
<import resource="classpath:/META-INF/spring/module-context.xml" />
Module-context.xml (minus the fluff):
<description>Example job to get you started. It provides a skeleton for a typical batch application.</description>
<import resource="classpath:/META-INF/spring/hibernate-context.xml"/>
<import resource="classpath:/META-INF/spring/myapp-context.xml"/>
<context:component-scan base-package="com.me" />
<bean class="org.springframework.batch.core.scope.StepScope" />
<batch:job id="job1">
<batch:step id="step0002" >
<batch:tasklet transaction-manager="transactionManager" start-limit="100" >
<batch:chunk reader="sourceSelectionReader" writer="selectedDataWriter" commit-interval="1" />
</batch:tasklet>
</batch:step>
</batch:job>
The important steps to get Job Parameters to work is to define the StepScope bean and to make sure that your reader is a #StepScope component.
I would try the following:
First make sure that there is a step-bean defined. This is nice to setup using Java Configuration:
#Configuration
public class JobFrameworkConfig {
#Bean
public static StepScope scope() {
return new StepScope();
}
// jobRegistry, transactionManager etc...
}
Then, make sure that your bean is step-scoped by the use of the #StepScope-annotation (almost as in your example). Inject a #Value that is not #Lazy.
#Component("sourceSelectionReader")
#StepScope // required, also works with #Scope("step")
public class SourceSelectionReaderImpl implements ItemReader<MyThing> {
private final long myParam;
// Not lazy, specified param name for the jobParameters
#Autowired
public SourceSelectionReaderImpl(#Value("#{jobParameters['myParam']}") final long myParam) {
this.myParam = myParam;
}
// the rest of the reader...
}
Try add #DependsOn("jobParameters") after #Component("sourceSelectionReader")

#Bean configuration instead of context.xml

i am using following config in my spring context.xml to register patterns for Java melody configuration.
i want to move this out as a spring bean. can anyone help me with this? i am having trouble setting it up properly.
<bean id="facadeMonitoringAdvisor" class="net.bull.javamelody.MonitoringSpringAdvisor">
<property name="pointcut">
<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns" value="com.abc.service.*.*(..)" />
<property name="excludedPatterns" value="com.abc.service.*.getEntityManager(),com.abc.service.xyz.integration.gateway.*,com.abc.service.xyz.webservice.*" />
</bean>
</property>
</bean>
You should create a #Configuration class. For each bean tag in xml, create a method annotated with #Bean. In this case it would look something like this:
#Configuration
public class MonitoringContext
{
#Bean(name="facadeMonitoringAdvisor")
public MonitoringSpringAdvisor getMonitoringSpringAdvisor() {
MonitoringSpringAdvisor msa = new MonitoringSpringAdvisor();
msa.setPointcut(getJdkRegexpMethodPointcut());
return msa;
}
#Bean
public JdkRegexpMethodPointcut getJdkRegexpMethodPointcut() {
JdkRegexpMethodPointcut jrm = new JdkRegexpMethodPointcut();
jrm.setPatterns("com.abc.service.*.*(..)");
jrm.setExcludedPatterns("com.abc.service.*.getEntityManager(),com.abc.service.xyz.integration.gateway.*,com.abc.service.xyz.webservice.*");
return jrm;
}
}
Check out the Spring documentation for AOP here

#Async via proxy classes is creating an exception in Spring 3.2

I seem to have come up with a problem.
I have a class
#Component
#Scope("prototype")
public class MyClass extends BaseClass {
....
...
#Async
public void doSomething() {
....
}
....
}
and a Spring Config that contains
<context:annotation-config />
<context:component-scan base-package="com.company.project" />
<task:annotation-driven executor="taskExecutor"/>
<task:executor id="taskExecutor" pool-size="10" queue-capacity="10" />
and in some part of the code i have
BaseClass bean = springBeans.getBean(MyClass.class);
but i am getting this exception
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'myClass' must be of type [com.company.project.MyClass], but was actually of type [$Proxy19]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:361)
I can understand its a proxy class, but not sure why Spring is not allowing the Proxy to be converted.
I have the cglib 2.2 no dep on the class path, along with the Spring 3.2 core libs.
can anyone point to any clues as to fixing this ?
In short, i want a method to be Async when called.
Since you have CGLIB, you might want to change the #Scope to
#Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)

Categories

Resources