Spring Async for batch insertion - java

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.

Related

If Spring can successfully intercept intra class function calls in a #Configuration class, why does it not support it in a regular bean?

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.

Where to place Spring #Async in a stack of methods calls

I am using Spring Boot 1.5.x, and in details, I am using the #Async annotation. My problem is that I have the following method in a repository.
#Repository
class Repository {
#Async
CompletableFuture<String> findSomething() {
/* Some code that returns something */
}
}
And then, I have the following method in a service, which calls the above repository.
#Service
class Service {
private Repository repository;
// ...
#Async
CompletableFuture<String> findSomething() {
return repository.findSomething()
}
}
My question is: should I place the #Async annotation also in the service.findSomething() method? Or should I place the annotation only in the service method?
I mean, Spring should schedule the execution of a method marked with #Async annotation in a dedicated thread. Is it correct?
Thanks in advance.
Annotating a method with #Async will cause the caller to return immediately and the actual execution will occur in a separate thread as part of a task submitted to the default SimpleAsyncTaskExecutor (if you haven't configured another one). Please see the relevant spring documentation.
That being said, for your goal there's no added benefit in nesting the #Async. If your goal is to make Repository.findSomething asynchronous and to be able to call it from different places, not only Service.findSomething, you should annotate only this method.
Also, Service.findSomething is asynchronous itself, even if not annotated with #Async, in the scenario you depicted. The method is not blocking by calling CompletableFuture.get() and it will return immediately, although it will not be executed in a separate thread.

Should I put #Transactional annotation for submethods also in spring?

I have a main DB handler method, which calls other methods, which are also working with BD things.
I put #Transactional annotation for the main method, because I want to roll back everything, if something goes wrong.
My question is: should I put this annotation also for the submethods, or it will know that the submethods were called from a method which is transactional.
For example, in the deleting method an exception occurs, how can I make sure that the writing part will be also rollbacked:
#Transactional
public void maintDbTings() {
writing();
deleting();
}
#Transactional //do I need this?
public void writing() {
//no exceptions
}
#Transactional //do I need this?
public void deleting() {
//exception occurs
}
Spring begins a transaction when it encounters a method annotated with #Transactional. The transaction’s scope
covers the execution of that method, the execution of any methods that method invokes, and
so on, until the method returns. Any managed resources that are covered by the configured
PlatformTransactionManager and that you use during the transaction scope participate in the
transaction. For example, if you use the org.springframework.jdbc.datasource.DataSourceTransactionManager, a Connection retrieved from the linked DataSource
participates in the transaction automatically.
The transaction terminates one of two ways: Either the method completes execution directly and the transaction manager commits the transaction, or the method throws an exception and the transaction manager rolls the transaction back.
I hope it is clear now.
In plain english, when you have this:
#Transactional
public void maintDbTings() {
writing();
}
#Transactional //do I need this?
public void writing() {
//no exceptions
}
And call mainDbTings, the #Transactional on the writing has no effect. Meaning that the transaction that was started for mainDbThings will still be present/open in writing. So in this case you can easily drop it.
On the other hand since writing is public someone might call it expecting it to be transactional, since it is a service class most probably. In this case making writing to be #Transactional is mandatory and you can't drop it.
So it's up your needs really.
You can use propagation properties like REQUIRED, REQUIRES_NEW, NESTED according to your requirement as described in the below link:
http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

How can I query SQL just after transaction open?

Just like in the title. I need to query a specific function on database which will define a few values assigned to the transaction. If it's possible I want to make it a global configuration connected with a specific profile(There are few requests that I do not want to load that function).
Project is build on Java SE 1.7, Spring Boot 1.1.7 and it connects with PostgreSQL database.
Requests are build on 3 layers, SomeClassController(Controller), SomeClassService(Service), SomeClassDB(Repository). On SomeClassDB it connects with database using JdbcTemplate from Spring and performs a CRUD operations. Before any of those operations I want to query a function. And as i mentioned it, I don't want a method that will do the job - I need something like global configuration on TransactionManager?
Maybe I should use TransactionSynchronization with beforeCommit method? But I don't know how to use it globally.
EDIT1: What I can but i don't want to ;):
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
#Service
public class SessionService {
Boolean flag;
public SessionService(){
flag=false;
}
#Value("${appVersion}") String appVersion;
#Value("${appArtifactId}") String appArtifactId;
public void addSession(){
if(!flag){
jdbcTemplate.execute("SELECT add_ses('"+appArtifactId+"','"+appVersion+")");
flag=true;
}
}
public void deleteSession(){
jdbcTemplate.execute("SELECT del_ses()");
}
}
And now I can just call those two methods on start and end of 2nd layer class with #Autowired this class. But I really don't want to do it in that way. Someone, someday will forget about it propagating that 2nd layer SomeClassService class and I want to avoid it.
I hope that will get you closer to my problem.
This could be typical use case of aspects. Have you tried to write an aspect for this? Aspect can be configured to execute some code before and after call of a method in specific package or method decorated by specific annotation. Spring has very nice support for aspects.
Another way is to create a proxy (using java.lang.reflect.Proxy) object which will call your initialization code and then delegate to proxied object.

Spring #Transactional multiple threads

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.

Categories

Resources