I have created a bean of a class with default (Singleton) scope. Within the class I have a method which is scheduled to be run every hour.
public class TaskService implements InitializingBean {
#Scheduled(cron="0 0 */1 * * ?")
public void hourlyReportTask()
{
... code here ...
}
public void performAllTasks()
{
hourlyReportTask();
...
...
}
}
My application config looks something like this,
<bean id="reportService"
class="com.tasks.TaskService" />
I am assuming the Thread running the scheduled task will be using the same TaskService bean since its created in singleton scope. What shall happen if the application is currently running hourlyReportTask() and the Spring container kicks off a background scheduled thread to run hourlyReportTask() at the same time. Will it wait for the to get access of the TaskService instance?
The exact same instance is used by both your application and the scheduling service. There is no synchronization so the scheduling service may run that method while your application invokes it.
Pretty much the same way as you would have injected TaskService in something that can be accessed by multiple threads at the same time and those threads call that method concurrently.
There's no black magic behind #Scheduled: it invokes your method the same way as you would manually. If that method is not thread-safe you need to fallback on regular synchronization mechanism in Java (for instance by adding the synchronized keyword to your method declaration).
Spring Singleton, does not mean what you expect from Design Patterns Singleton. In Spring, Singleton means that a bean only has created only one instance (without meaning that another cannot be created) and that instance is used whenever Spring needs that type.
In your case your hourlyReportTask() method would execute twice.
Related
I'm using spring boot. I was new to spring and started a spring project. So I didn't know about pre defined repositories (JPA, CRUD) which can be easily implemented. In case, I wanted to save a bulk data, so I use for loop and save one by one, Its taking more time. So I tried to use #Async. But it doesn't also work, is my concept wrong?
#Async has two limitation
it must be applied to public methods only
self-invocation – calling the async method from within the same class won’t work
1) Controller
for(i=0;i < array.length();i++){
// Other codes
gaugeCategoryService.saveOrUpdate(getEditCategory);
}
2) Dao implementation
#Repository
public class GaugeCategoryDaoImpl implements GaugeCategoryDao {
// Other codings
#Async
#Override
public void saveOrUpdate(GaugeCategory GaugeCategory) {
sessionFactory.getCurrentSession().saveOrUpdate(GaugeCategory);
}
}
After removing #Async , it working normally. But with that annotation it doesn't work. Is there any alternative method for time consuming? Thanks in advance.
the #Async annotation creates a thread for every time you call that method. but you need to enable it in your class using this annotation #EnableAsync
You also need to configure the asyncExecutor Bean.
You can find more details here : https://spring.io/guides/gs/async-method/
In my opinion, there are several issues with your code:
You overwrite the saveOrUpdate() method without any need to do so. A simple call to "super()" should have been enough to make #Async work.
I guess that you somewhere (within your controller class?) declare a transactional context. That one usually applies to the current thread. By using #Async, you might leave this transaction context as (because of the async DAO execution), the main thread may already be finished when saveOrUpdate() is called. And even though I currently don't know it exactly, there is a good change that the declared transaction is only valid for the current thread.
One possble fix: create an additional component like AsyncGaugeCategoryService or so like this:
#Component
public class AsyncGaugeCategoryService {
private final GaugeCategoryDao gaugeCategoryDao;
#Autowired
public AsyncGaugeCategoryService(GaugeCategoryDao gaugeCategoryDao) {
this.gaugeCategoryDao = gaugeCategoryDao;
}
#Async
#Transactional
public void saveOrUpdate(GaugeCategory gaugeCategory) {
gaugeCategoryDao.saveOrUpdate(gaugeCategory);
}
}
Then inject the service instead of the DAO into your controller class. This way, you don't need to overwrite any methods, and you should have a valid transactional context within your async thread.
But be warned that your execution flow won't give you any hint if something goes wrong while storing into the database. You'll have to check the log files to detect any problems.
Is that possible to execute methods annotated as #After (in class annotated as #Aspec) asynchronous? For example using annotation #Async or implements Runnable or Callable. And the same question for methods annotated as #PostPersist.
The real case is sending mail after registration. I don't want to execute method from some MailService in register method because this service will have too many dependencies and will be difficult to testing. But sending mail have to be executed asynchronous because this operation is very expensive.
Should not be a problem. Just start a new thread in the method "after" method.
AOP works as follows (by default):
When you register a bean that requires some aspects to be applied to, Spring creates a proxy around that bean and when you get the bean from the application context(by ctx.getBean(MyBean.class) or by Autowire is somewhere) you receive the proxy that has the real/target bean inside.
So, for example, when you tell Spring to execute a method after some target method this happens:
the application calls the method of the proxy
If something has to be executed before the target method(like configured #Before action) it's done.
call the real/target method
If something has to be executed after the target method(like configured #After action) it's done.
The next method in the call stack is executed
So basically with #After you just "insert" a method in the call stack. You can start a new thread from there, it will return the control immediately and the next thing after the target method will be executed.
I have a method A running in the transactional scope which:
Modifies an entity A to switch from state A to state B
Passes a task to a executor service that expects an Entity to be in state B when executed
The problem is when this task is run (that thing I have no control of) before the method A commits, it doesn't see the required state changed because it does not block until the method A level transaction ends.
Task is run using a spring bean and #Transactional-annotated method like this:
#Service
public class TransactionalProcessingAdapter implements ProcessingAdapter {
#Override
#Transactional
public void execute(ProcessingAdaptedMethod processingAdapter) {
processingAdapter.execute();
}
}
What am I doing wrong? Thanks!
The thing is that Spring transactions are thread bounded - eg a transaction is visible inside its initial threads only. ThreadLocal is used to implement that property.
You might want to implement your own TransactionSynchronizationManager in Spring and inject it. Use something like InheritableThreadLocal instead of ThreadLocal.
I have two Spring based async thread pools and methods in the same Spring bean. The doWork() uses the default Spring thread pool and holdAndReprocess() uses its own Spring thread pool.
I currently have my class setup like below where doWork processes some work and then if a failure occurs it parks the thread in the holdAndReprocess() "queue" thread pool and then waits and reprocesses the thread by calling the doWork(). With my current setup, the call to holdAndReprocess() and then the call back to doWork() is synchronous. Any ideas on how to wire this such that all communication between the doWork() and holdAndReprocess is asynchronous?
I'm using xml backed configuration and not pure annotation driven Spring beans.
public class AsyncSampleImpl implements AsyncSample {
#Async
public void doWork(){
holdAndReprocess();
}
#Async("queue")
#Transactional(propagation = Propagation.REQUIRED)
public void holdAndReprocess(){
//sleeps thread for static amount of time and then reprocesses
doWork();
}
}
Read https://stackoverflow.com/a/4500353/516167
As you're calling your #Async method from another method in the same object, you're probably bypassing the async proxy code and just calling your plain method, ie within the same thread.
Split this bean into two beans and invoke holdAndReprocess() from separate bean.
This rules apply also to #Transactional annotations.
Read about this: https://stackoverflow.com/a/5109419/516167
From Spring Reference Documentation Section 11.5.6, “Using #Transactional”
In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with #Transactional!
Draft
public class AsyncSampleImpl implements AsyncSample {
public void doWork(){
reprocessor.holdAndReprocess();
}
public void holdAndReprocess(){
//sleeps thread for static amount of time and then reprocesses
worker.doWork();
}
}
I wondering if I should exspect any problems when I autowire threads with prototype scope.
The thread:
...
#Service
#Scope("prototype")
public class MyThread extends Thread {
...
}
The thread starting class:
...
public class ThreadStarter {
#Autowired
private MyThread myThread;
public void startThread(){
myThread.start();
}
}
The starting class will be called from a webservice implementation.
Are there any pitfalls I should take into consideration?
Well it reallty depends on what the thread class instance does.
Think of Servlet doGet and/or doPost methods. If you're being stateless and don't keep values in wider scopes (such as session or context) you're fine with not troubling yourself about which instance of your servlet will be called when. However if you are being statefull (get/put objects to the session scope for example) then you need to synchronize that servlet instance's access to said scope (synchronized(session)) or serialize the way requests are being treated by the servlet threads.
I think here you're pretty much in the same situation. You want to make your thread instance to be prototype scoped (and thus have a new instance created each time an injection is needed) if you are infact stateful and share data between your threads, and you can leave it to the default scope of singleton if that thread's run() method is stateless as far as data outside it is concerned.
Nope, autowiring only affects which bean is choosed to fulfill a dependency- as long as you are not meddling with the ApplicationContext (i.e. adding/modifying beans concurrently), no weird stuff should happen.
In your example ThreadStarter will be injected a new instance of MyThread everytime it is instantiated- which I hope is what you want.