Spring scheduler is not starting [duplicate] - java

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

Related

Spring XML equivalent of #EnableAsync

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.

Class bean in application context for Cacheable annotation

I'm using Spring 4.1.4 and Ehcache 2.9 and caching using the #Cacheable annotation.
I've noticed that every public class that has a method with this annotation must be referenced in
applicationContext.xml
as follows
<bean class="com.example.web.Test"/>
this forces me to add every public class that i want to cache into the applicationContext.
Is there a way to overcome this?
Thanks
Of course #Cacheable works only for spring beans.
There are many ways to instantiate a spring bean, explicite xml configuration <bean class="..."/> is only one. An other way is to enable the component scan and annotate the class with #Component or #Service (or some other) annotations.

Understanding spring #Configuration class

Following the question Understanding Spring #Autowired usage I wanted to create a complete knowledge base for the other option of spring wiring, the #Configuration class.
Let's assume I have a spring XML file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<import resource="another-application-context.xml"/>
<bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
<constructor-arg value="${some.interesting.property}" />
</bean>
<bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
<constructor-arg ref="someBean"/>
<constructor-arg ref="beanFromSomewhereElse"/>
</bean>
</beans>
How can I use #Configuration instead? Does it have any affect on the code itself?
Migrating XML to #Configuration
It is possible to migrate the xml to a #Configuration in a few steps:
Create a #Configuration annotated class:
#Configuration
public class MyApplicationContext {
}
For each <bean> tag create a method annotated with #Bean:
#Configuration
public class MyApplicationContext {
#Bean(name = "someBean")
public SomeClass getSomeClass() {
return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
}
#Bean(name = "anotherBean")
public AnotherClass getAnotherClass() {
return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
}
}
In order to import beanFromSomewhereElse we need to import it's definition. It can be defined in an XML and the we'll use #ImportResource:
#ImportResource("another-application-context.xml")
#Configuration
public class MyApplicationContext {
...
}
If the bean is defined in another #Configuration class we can use the #Import annotation:
#Import(OtherConfiguration.class)
#Configuration
public class MyApplicationContext {
...
}
After we imported other XMLs or #Configuration classes, we can use the beans they declare in our context by declaring a private member to the #Configuration class as follows:
#Autowired
#Qualifier(value = "beanFromSomewhereElse")
private final StrangeBean beanFromSomewhereElse;
Or use it directly as parameter in the method which defines the bean that depends on this beanFromSomewhereElse using #Qualifier as follows:
#Bean(name = "anotherBean")
public AnotherClass getAnotherClass(#Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
}
Importing properties is very similar to importing bean from another xml or #Configuration class. Instead of using #Qualifier we'll use #Value with properties as follows:
#Autowired
#Value("${some.interesting.property}")
private final String someInterestingProperty;
This can be used with SpEL expressions as well.
In order to allow spring to treat such classes as beans containers we need to mark this in our main xml by putting this tag in the context:
<context:annotation-config/>
You can now import #Configuration classes exactly the same as you would create a simple bean:
<bean class="some.package.MyApplicationContext"/>
There are ways to avoid spring XMLs altogether but they are not in the scope of this answer. You can find out one of these options in my blog post on which I'm basing my answer.
The advantages and disadvantages of using this method
Basically I find this method of declaring beans much more comfortable than using XMLs due to a few advantages I see:
Typos - #Configuration classes are compiled and typos just won't allow compilations
Fail fast (compile time) - If you forget to inject a bean you'll fail on compile time and not on run-time as with XMLs
Easier to navigate in IDE - between constructors of beans to understand the dependency tree.
Possible to easily debug configuration startup
The disadvantages are not many as I see them but there are a few which I could think of:
Abuse - Code is easier to abuse than XMLs
With XMLs you can define dependencies based on classes that are not available during compile time but are provided during run-time. With #Configuration classes you must have the classes available at compile time. Usually that's not an issue, but there are cases it may be.
Bottom line: It is perfectly fine to combine XMLs, #Configuration and annotations in your application context. Spring doesn't care about the method a bean was declared with.

Registering beans from a Configuration-annotated class

I have a class annotated with #Configuration (let's call it StubConfiguration) which has a single method that is annotated with #Bean. This method returns a BeanFactoryPostProcessor implementation which is responsible for registering some beans. However, Spring is unable to resolve the beans this factory registers at runtime.
My assumption is that StubConfiguration is picked up by Spring's component scanning, the BeanFactoryPostProcessor is registered and then its postProcessBeanFactory() method is invoked, subsequently registering the beans I need.
Am I thinking about this incorrectly? How can I go about registering the beans that I need with my ApplicationContext using this post processing?
If you're also using an XML app context to declare beans, you can tell Spring to do a component scan and treat #Stub as a Spring component annotation.
<context:component-scan base-package="your.base.package">
<context:include-filter type="annotation" expression="your.stub.package.Stub"/>
</context:component-scan>
If you're only using an annotation config app context, check out this answer for a way to do it without XML.
What about making your #Stub annotation extend the #Component annotation? Like the #Service or #Repository.
You will have your beans scanned with the regular Spring context scanning, you can keep your custom annotation and you won't need to register manually your beans.
Example from #Service:
{#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Service {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* #return the suggested component name, if any
*/
String value() default "";
}}

How to add Spring Beans automatically to a TaskExecutor

I'm looking for a way to have spring beans registering themselves to a job processor bean who in turn will execute the registered beans on a schedule.
I'm hoping that the bean would just have to implement an interface and by some spring mechanism get registered to the job processor bean. Or alternatively inject the job processor bean into the beans and then somehow the job processor bean can keep track of where it's been injected.
Any suggestions appreciated, it might be that spring is not the tool for this sort of thing?
Use a spring context something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--Scans the classpath for annotated
components #Component, #Repository,
#Service, and #Controller -->
<context:component-scan base-package="org.foo.bar"/>
<!--Activates #Required, #Autowired,
#PostConstruct, #PreDestroy
and #Resource-->
<context:annotation-config/>
</beans>
And define a pojo like this:
#Component
public class FooBar {}
And inject like this:
#Component
public class Baz {
#Autowired private FooBar fooBar;
}
Spring has a powerful abstraction layer for Task Execution and Scheduling.
In Spring 3, there are also some annotations that you can use to mark bean methods as scheduled (see Annotation Support for Scheduling and Asynchronous Execution)
You can let a method execute in a fixed interval:
#Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
Or you can add a CRON-style expression:
#Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
Here's the XML code you'll need to add (or something similar):
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Used together with
<context:component-scan base-package="org.foo.bar"/>
<context:annotation-config/>
as described by PaulMcKenzie, that should get you where you want to go.

Categories

Resources