I have Spring used in a legacy project and would like to use "Scheduled" runs in a class that is not created as a bean, but as a usual "new" class. So annotations such as #Scheduled are not active.
How can I then enable scheduling by calling all relevant Spring methods explicitly?
Basically you can't do that, because Spring can use its "magic" (in this case figure out the scheduling rules and invoke the method periodically) only on classes which are managed by spring.
If you have to create the class manually - you can't place a #Scheduled annotation on it.
So Your options are:
Create a spring bean (I understand, you already have spring, hence the question) that will create your legacy class, or maybe will access it via some legacy global registry - it really depends on your project:
#Component
public class MySpringBean {
#Scheduled (...)
public void scheduledStuff() {
MyLegacyClass c = MyLegacyGlobalContext.getMyLegacyClass();
c.callMyLegacyMethod();
}
}
Implement the scheduling entirely outside the spring:
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Callable() {
public Object call() throws Exception {
MyLegacyClass c = MyLegacyGlobalContext.getMyLegacyClass();
c.callMyLegacyMethod();
}
},
30,
TimeUnit.MINUTES);
Related
I have recently noticed that Spring successfully intercepts intra class function calls in a #Configuration class but not in a regular bean.
A call like this
#Repository
public class CustomerDAO {
#Transactional(value=TxType.REQUIRED)
public void saveCustomer() {
// some DB stuff here...
saveCustomer2();
}
#Transactional(value=TxType.REQUIRES_NEW)
public void saveCustomer2() {
// more DB stuff here
}
}
fails to start a new transaction because while the code of saveCustomer() executes in the CustomerDAO proxy, the code of saveCustomer2() gets executed in the unwrapped CustomerDAO class, as I can see by looking at 'this' in the debugger, and so Spring has no chance to intercept the call to saveCustomer2.
However, in the following example, when transactionManager() calls createDataSource() it is correctly intercepted and calls createDataSource() of the proxy, not of the unwrapped class, as evidenced by looking at 'this' in the debugger.
#Configuration
public class PersistenceJPAConfig {
#Bean
public DriverManagerDataSource createDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//dataSource.set ... DB stuff here
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager( ){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(createDataSource());
return transactionManager;
}
}
So my question is, why can Spring correctly intercept the intra class function calls in the second example, but not in the first. Is it using different types of dynamic proxies?
Edit:
From the answers here and other sources I now understand the following:
#Transactional is implemented using Spring AOP, where the proxy pattern is carried out by wrapping/composition of the user class. The AOP proxy is generic enough so that many Aspects can be chained together, and may be a CGLib proxy or a Java Dynamic Proxy.
In the #Configuration class, Spring also uses CGLib to create an enhanced class which inherits from the user #Configuration class, and overrides the user's #Bean functions with ones that do some extra work before calling the user's/super function such as check if this is the first invocation of the function or not. Is this class a proxy? It depends on the definition. You may say that it is a proxy which uses inheritance from the real object instead of wrapping it using composition.
To sum up, from the answers given here I understand these are two entirely different mechanisms. Why these design choices were made is another, open question.
Is it using different types of dynamic proxies?
Almost exactly
Let's figure out what's the difference between #Configuration classes and AOP proxies answering the following questions:
Why self-invoked #Transactional method has no transactional semantics even though Spring is capable of intercepting self-invoked methods?
How #Configuration and AOP are related?
Why self-invoked #Transactional method has no transactional semantics?
Short answer:
This is how AOP made.
Long answer:
Declarative transaction management relies on AOP (for the majority of Spring applications on Spring AOP)
The Spring Framework’s declarative transaction management is made possible with Spring aspect-oriented programming (AOP)
It is proxy-based (§5.8.1. Understanding AOP Proxies)
Spring AOP is proxy-based.
From the same paragraph SimplePojo.java:
public class SimplePojo implements Pojo {
public void foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar();
}
public void bar() {
// some logic...
}
}
And a snippet proxying it:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
The key thing to understand here is that the client code inside the main(..) method of the Main class has a reference to the proxy.
This means that method calls on that object reference are calls on the proxy.
As a result, the proxy can delegate to all of the interceptors (advice) that are relevant to that particular method call.
However, once the call has finally reached the target object (the SimplePojo, reference in this case), any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy.
This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
(Key parts are emphasized.)
You may think that aop works as follows:
Imagine we have a Foo class which we want to proxy:
Foo.java:
public class Foo {
public int getInt() {
return 42;
}
}
There is nothing special. Just getInt method returning 42
An interceptor:
Interceptor.java:
public interface Interceptor {
Object invoke(InterceptingFoo interceptingFoo);
}
LogInterceptor.java (for demonstration):
public class LogInterceptor implements Interceptor {
#Override
public Object invoke(InterceptingFoo interceptingFoo) {
System.out.println("log. before");
try {
return interceptingFoo.getInt();
} finally {
System.out.println("log. after");
}
}
}
InvokeTargetInterceptor.java:
public class InvokeTargetInterceptor implements Interceptor {
#Override
public Object invoke(InterceptingFoo interceptingFoo) {
try {
System.out.println("Invoking target");
Object targetRetVal = interceptingFoo.method.invoke(interceptingFoo.target);
System.out.println("Target returned " + targetRetVal);
return targetRetVal;
} catch (Throwable t) {
throw new RuntimeException(t);
} finally {
System.out.println("Invoked target");
}
}
}
Finally InterceptingFoo.java:
public class InterceptingFoo extends Foo {
public Foo target;
public List<Interceptor> interceptors = new ArrayList<>();
public int index = 0;
public Method method;
#Override
public int getInt() {
try {
Interceptor interceptor = interceptors.get(index++);
return (Integer) interceptor.invoke(this);
} finally {
index--;
}
}
}
Wiring everything together:
public static void main(String[] args) throws Throwable {
Foo target = new Foo();
InterceptingFoo interceptingFoo = new InterceptingFoo();
interceptingFoo.method = Foo.class.getDeclaredMethod("getInt");
interceptingFoo.target = target;
interceptingFoo.interceptors.add(new LogInterceptor());
interceptingFoo.interceptors.add(new InvokeTargetInterceptor());
interceptingFoo.getInt();
interceptingFoo.getInt();
}
Will print:
log. before
Invoking target
Target returned 42
Invoked target
log. after
log. before
Invoking target
Target returned 42
Invoked target
log. after
Now let's take a look at ReflectiveMethodInvocation.
Here is a part of its proceed method:
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
++this.currentInterceptorIndex should look familiar now
Here is the target
And there are interceptors
the method
the index
You may try introducing several aspects into your application and see the stack growing at the proceed method when advised method is invoked
Finally everything ends up at MethodProxy.
From its invoke method javadoc:
Invoke the original method, on a different object of the same type.
And as I mentioned previously documentation:
once the call has finally reached the target object any method calls that it may make on itself are going to be invoked against the this reference, and not the proxy
I hope now, more or less, it's clear why.
How #Configuration and AOP are related?
The answer is they are not related.
So Spring here is free to do whatever it wants. Here it is not tied to the proxy AOP semantics.
It enhances such classes using ConfigurationClassEnhancer.
Take a look at:
CALLBACKS
BeanMethodInterceptor
BeanFactoryAwareMethodInterceptor
Returning to the question
If Spring can successfully intercept intra class function calls in a #Configuration class, why does it not support it in a regular bean?
I hope from technical point of view it is clear why.
Now my thoughts from non-technical side:
I think it is not done because Spring AOP is here long enough...
Since Spring Framework 5 the Spring WebFlux framework has been introduced.
Currently Spring Team is working hard towards enhancing reactive programming model
See some notable recent blog posts:
Reactive Transactions with Spring
Spring Data R2DBC 1.0 M2 and Spring Boot starter released
Going Reactive with Spring, Coroutines and Kotlin Flow
More and more features towards less-proxying approach of building Spring applications are introduced. (see this commit for example)
So I think that even though it might be possible to do what you've described it is far from Spring Team's #1 priority for now
Because AOP proxies and #Configuration class serve a different purpose, and are implemented in a significantly different ways (even though both involve using proxies).
Basically, AOP uses composition while #Configuration uses inheritance.
AOP proxies
The way these work is basically that they create proxies that do the relevant advice logic before/after delegating the call to the original (proxied) object. The container registers this proxy instead of the proxied object itself, so all dependencies are set to this proxy and all calls from one bean to another go through this proxy. However, the proxied object itself has no pointer to the proxy (it doesn't know it's proxied, only the proxy has a pointer to the target object). So any calls within that object to other methods don't go through the proxy.
(I'm only adding this here for contrast with #Configuration, since you seem to have correct understanding of this part.)
#Configuration
Now while the objects that you usually apply the AOP proxy to are a standard part of your application, the #Configuration class is different - for one, you probably never intend to create any instances of that class directly yourself. This class truly is just a way to write configuration of the bean container, has no meaning outside Spring and you know that it will be used by Spring in a special way and that it has some special semantics outside of just plain Java code - e.g. that #Bean-annotated methods actually define Spring beans.
Because of this, Spring can do much more radical things to this class without worrying that it will break something in your code (remember, you know that you only provide this class for Spring, and you aren't going to ever create or use its instance directly).
What it actually does is it creates a proxy that's subclass of the #Configuration class. This way, it can intercept invocation of every (non-final non-private) method of the #Configuration class, even within the same object (because the methods are effectively all overriden by the proxy, and Java has all the methods virtual). The proxy does exactly this to redirect any method calls that it recognizes to be (semantically) references to Spring beans to the actual bean instances instead of invoking the superclass method.
read a bit spring source code. I try to answer it.
the point is how spring deal with the #Configurationand #bean.
in the ConfigurationClassPostProcessor which is a BeanFactoryPostProcessor, it will enhance all ConfigurationClasses and creat a Enhancer as a subClass.
this Enhancer register two CALLBACKS(BeanMethodInterceptor,BeanFactoryAwareMethodInterceptor).
you call PersistenceJPAConfig method will go through the CALLBACKS. in BeanMethodInterceptor,it will get bean from spring container.
it may be not clearly. you can see the source code in ConfigurationClassEnhancer.java BeanMethodInterceptor.ConfigurationClassPostProcessor.java enhanceConfigurationClasses
You can't call #Transactional method in same class
It's a limitation of Spring AOP (dynamic objects and cglib).
If you configure Spring to use AspectJ to handle the transactions, your code will work.
The simple and probably best alternative is to refactor your code. For example one class that handles users and one that process each user. Then default transaction handling with Spring AOP will work.
Also #Transactional should be on Service layer and not on #Repository
transactions belong on the Service layer. It's the one that knows about units of work and use cases. It's the right answer if you have several DAOs injected into a Service that need to work together in a single transaction.
So you need to rethink your transaction approach, so your methods can be reuse in a flow including several other DAO operations that are roll-able
Spring uses proxying for method invocation and when you use this... it bypasses that proxy. For #Bean annotations Spring uses reflection to find them.
I'm using Spring's #EnableAsync feature to execute methods asynchronously. For security I'm using Apache Shiro. In the code that is executed asynchronously I need to have access to the Shiro subject that was attached to the thread that triggered the async call.
Shiro supports using an existing subject in a different thread by associating the subject with the Callable that is to be executed on the different thread (see here):
Subject.associateWith(Callable)
Unfortunately I don't have direct access to the Callable as this stuff is encapsulated by Spring. I found that I would need to extend Spring's AnnotationAsyncExecutionInterceptor to associate my subject with the created Callable (that's the easy part).
By problem is now how to make Spring use my custom AnnotationAsyncExecutionInterceptor instead of the default one. The default one is created in AsyncAnnotationAdvisor and AsyncAnnotationBeanPostProcessor. I can of course extend these classes as well, but this only shifts to problem as I need the make Spring use my extended classes again.
Is there any way to achieve what I want?
I would be fine with adding a new custom async annotation as well. But I don't think this would be much of a help.
UPDATE:
Actually my finding that AnnotationAsyncExecutionInterceptor would need to be customized was wrong. By chance I stumbled across org.apache.shiro.concurrent.SubjectAwareExecutorService which does pretty exactly what I want and made me think I could simply provide a custom executor instead of customizing the interceptor. See my answer for details.
I managed to achieve what I want - shiro subject is automatically bound and unbound to tasks that are executed by spring's async support - by providing an extended version of the ThreadPoolTaskExecutor:
public class SubjectAwareTaskExecutor extends ThreadPoolTaskExecutor {
#Override
public void execute(final Runnable aTask) {
final Subject currentSubject = ThreadContext.getSubject();
if (currentSubject != null) {
super.execute(currentSubject.associateWith(aTask));
} else {
super.execute(aTask);
}
}
... // override the submit and submitListenable method accordingly
}
To make spring use this executor I had to implement an AsyncConfigurer that returns my custom executor:
#EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
#Override
public Executor getAsyncExecutor() {
final SubjectAwareTaskExecutor executor = new SubjectAwareTaskExecutor();
executor.setBeanName("async-executor");
executor.setCorePoolSize(10);
executor.setMaxPoolSize(10);
executor.initialize();
return executor;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
With this change the parent Thread's subject will automatically be available in methods that are annotated with #Async and - probably even more important - the subject will be de-attached from the thread after execution of the asynchronous method.
I have a Spring Boot Application with a bunch of background jobs. I have added the following Annotation on my main application class:
#SpringBootApplication
#EnableScheduling
public class MyApplication {
In the job class, I have following configuration:
#Component
public class MyTask {
#Scheduled(fixedDelay = 14400000)
public void doSomething()
Right now, Spring Boot is executing the jobs in a sequential manner, i.e., one job at a time. This seems most likely due to a single thread based pool.
Is there any Annotation/property that can be used to increase the thread pool size?
Till now, I have found a solution here, but it requires writing a new Configuration class.
Ideally, it should be a property in application.properties file.
I usually don't put business logic inside a #Scheduled method, instead, I call another method in other component and this method has the #Async annotation. When your scheduled job is fired, then it calls the async method in another thread and you scheduler is free to run other jobs.
Check more how to do it here: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support
I don't see a property for this in https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html and I don't see any annotation in the docs.
If you want it configurable at that level, just create your own custom properties, which you inject into the other solution you found.
Currently I am building a spring standalone program in order to learn new methods and architectures.
The last few days I tried to learn scheduler. I never used them before so I read some articles handling the different possible methods. Two of them are especially interesting: The spring nativ #Scheduler and Quartz.
From what I read, Spring is a little bit smaller then Quartz and much more basic. And quartz is not easy to use with spring (because of the autowired and components).
My problem now is, that there is one thing I do not understand:
From my understanding, both methods are creating parallel Threads in order to asynchronously run the jobs. But what if I now have a spring #Service in my main Application, that is holding a HashMap with some information. The data is updated and changed with user interaction. Parallel there are the scheduler. And a scheduler now whants to use this HashMap from the main application as well. Is this even possible?
Or do I understand something wrong? Because there is also the #Async annotation and I did not understand the difference. Because a scheduler itself is already parallel to the main corpus, isn't it?
(summing up, two questions:
can a job that is executed every five seconds, implemented with a scheduler, use a HashMap out of a service inside the main program? (in spring #Scheduler and/or in Quartz?)
Why is there a #Async annotation. Isn't a scheduler already parallel to the main process?
)
I have to make a few assumptions about which version of Spring you're using but as you're in the process of learning, I would assume that you're using spring-boot or a fairly new version, so please excuse if the annotations don't match your version of Spring. This said, to answer your two questions the best I can:
can a job that is executed every five seconds, implemented with a scheduler, use a HashMap out of a service inside the main program? (in spring #Scheduler and/or in Quartz?)
Yes, absolutely! The easiest way is to make sure that the hashmap in question is declared as static. To access the hashmap from the scheduled job, simply either autowire your service class or create a static get function for the hashmap.
Here is an example of a recent Vaadin project where I needed a scheduled message sent to a set of subscribers.
SchedulerConfig.class
#Configuration
#EnableAsync
#EnableScheduling
public class SchedulerConfig {
#Scheduled(fixedDelay=5000)
public void refreshVaadinUIs() {
Broadcaster.broadcast(
new BroadcastMessage(
BroadcastMessageType.AUTO_REFRESH_LIST
)
);
}
}
Broadcaster.class
public class Broadcaster implements Serializable {
private static final long serialVersionUID = 3540459607283346649L;
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
private static LinkedList<BroadcastListener> listeners = new LinkedList<BroadcastListener>();
public interface BroadcastListener {
void receiveBroadcast(BroadcastMessage message);
}
public static synchronized void register(BroadcastListener listener) {
listeners.add(listener);
}
public static synchronized void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static synchronized void broadcast(final BroadcastMessage message) {
for (final BroadcastListener listener: listeners)
executorService.execute(new Runnable() {
#Override
public void run() {
listener.receiveBroadcast(message);
}
});
}
}
Why is there a #Async annotation. Isn't a scheduler already parallel to the main process?
Yes, the scheduler is running in its own thread but what occurs to the scheduler on long running tasks (ie: doing a SOAP call to a remote server that takes a very long time to complete)?
The #Async annotation isn't required for scheduling but if you have a long running function being invoked by the scheduler, it becomes quite important.
This annotation is used to take a specific task and request to Spring's TaskExecutor to execute it on its own thread instead of the current thread. The #Async annotation causes the function to immediately return but execution will be later made by the TaskExecutor.
This said, without the #EnableAsync or #Async annotation, the functions you call will hold up the TaskScheduler as they will be executed on the same thread. On a long running operation, this would cause the scheduler to be held up and unable to execute any other scheduled functions until it returns.
I would suggest a read of Spring's Documentation about Task Execution and Scheduling It provides a great explanation of the TaskScheduler and TaskExecutor in Spring
My use case is the following:
I'm currently developing an application in which there is an EventModule which is responsible for firing all sorts of events. One of those events is a TimeEvent. These time events should be fired every second. It should also be possible to add support for new events when my application is up and running. For the latter requirement I'm using OSGI.
For generating the time events themselves, I found out that spring already provides such functionality for me, namely by placing #Scheduled annotations on a method that will be invoked periodally (in my case every second).
So therefore I had this code:
/**
* Generator class that periodically generates {#link TimeEvent}s.
*/
#Component
#EnableScheduling
public class TimeEventGenerator {
#Scheduled( cron = "*/1 * * * * ?" )
public void testSchedule() {
// fire a time event
}
}
This works fine and events are fired every second. However, this requires the TimeEventGenerator class to be instantiated on start up (since it is annotated with #Component). In my use case, namely the OSGI part, I should be able to create an instance of this class in the start(BundleContext) method of my BundleActivator whenever I decide to plug in the support for TimeEvents, so having the #Component annotation is not an option.
This is the part where I'm having some troubles. I learned that I can inject beans myself in a spring application context by using a BeanFactoryPostProcessor, which is exactly what I did and this resulted in the following code:
/**
* Class that allows to add spring beans to a running application context.
*/
#Component
public class RuntimeBeanFactory implements ApplicationContextAware,
BeanFactoryPostProcessor {
private ApplicationContext applicationContext;
private ConfigurableListableBeanFactory beanFactory;
#Override
#Autowired
public void setApplicationContext( ApplicationContext aApplicationContext ) throws BeansException {
applicationContext = aApplicationContext;
}
#Override
#Autowired
public void postProcessBeanFactory( ConfigurableListableBeanFactory aBeanFactory ) throws BeansException {
beanFactory = aBeanFactory;
}
public <T> T createBean( Class<T> aBeanClass, String aBeanName ) throws IOException {
BeanDefinitionRegistry registry = ( ( BeanDefinitionRegistry ) beanFactory );
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass( aBeanClass );
beanDefinition.setLazyInit( false );
beanDefinition.setAbstract( false );
beanDefinition.setAutowireCandidate( true );
if ( !registry.isBeanNameInUse( aBeanName ) ) {
registry.registerBeanDefinition( aBeanName, beanDefinition );
}
return applicationContext.getBean( aBeanClass );
}
}
The problem here is that whenever I create a TimeEventGenerator (cf. the first code snippet) with the createBean method, the testSchedule() method is never invoked, while I expected it to be the case, since the bean is managed by spring.
EDIT: I forgot to add that I have also tried the above code with two sub classes of GenericBeanDefinition, namely the ScannedGenericBeanDefinition and the AnnotatedGenericBeanDefinition, without success either.
Looking at the Spring documentation, I think you should try AnnotatedGenericBeanDefinition instead of GenericBeanDefinition. See the documents here.
EDIT
I was looking at the code for ScheduledAnnotationBeanPostProcessor and my annotations were being processed. The issue I ran into was that even though the post processor recognized the scheduled task, it only schedules the tasks with the task executor one time. By the time I registered my scheduled class, this had already happened, to it was not getting invoked. Passing a refresh event to the post processor forced it to schedule, but it also rescheduled every other task. Looking at the code (at least in Spring 3.2), what you want to do is not possible using the annotations. You could create a custom annotation processor and register the tasks with a task executor.
If you simply need to switch the TimeEventGenerator on and off then simply put it in a separate bundle and start and stop the bundle to switch it on and off.