I have a Java, Spring Data application with a PostgreSQL DB and I have a code similar to this in my service layer:
public void method1() {
PersonDto dto = method2();
method3(dto);
}
#Transactional
public PersonDto method2() {
Person p1 = personRepository.saveAndFlush(new Person());
return createPersonDto(p1);
}
#Transactional
public void method3(PersonDto p1) {
Person p2 = personRepository.findById(p1.getId());
if (p2 == null) {
System.out.println("Not in the DB");
} else {
System.out.println("In the DB");
}
}
Sometimes this code prints "Not in the DB", when I was expecting that it would always print "In the DB". My questions are:
This saveAndFlush is even necessary? Since I'm not reusing that Entity in the same transaction, I guess it would have the same effect as a save, right?
How to guarantee that the changes in method2 will be committed before method 3 calls it? So it will always print "In the DB"?
The fact that I'm converting my Entity to a DTO is what is messing this up? Maybe if I was passing the Entity itself it would work properly?
I'm thinking about #Transactional only in method1, or replacing #Transactional in method3 with #Transactional(isolation = Isolation.READ_UNCOMMITTED).
Any advice?
I can see a couple of reason why you're getting the results you describe.
One possibility is that #Transactional doesn't necessarily mean "execute this method in a totally separate transaction." The default propagation is REQUIRED, which will use an existing transaction if one is already active. So if method2() is called in a stack where a transaction was opened earlier, it won't create a new one (and thus the new entity won't be committed) until that original transaction is committed. If this is what's happening, one solution would be to change the propagation to REQUIRES_NEW:
#Transactional(propagation = REQUIRES_NEW)
Another possibility, which seems more likely, is that these methods are all in the same class. To understand why that fails, you have to understand how Spring implements handling of #Transactional (and most other behavioral annotations): using proxies. That means that only method calls that come through the proxy get the transactional behavior. That's the typical scenario when one object calls a reference it has to another; the reference is actually to the proxy, which intercepts the call and wraps the behavior (in this case, transactionality) around it. However, when calling methods within the same instance, there is no proxy in play (Spring doesn't/can't replace this with a reference to the proxy), and thus no transactional behavior.
There are a few ways to work around that, but first I would consider how to restructure my classes and methods to avoid it. If that's not reasonable, things like AspectJ, TransactionTemplate, and maybe some other ideas are discussed in this SO Q&A.
Addendum:
This question and its answers also talks about options to work around the proxying problem.
Related
I want to know what actually happens when you annotate a method with #Transactional?
Of course, I know that Spring will wrap that method in a Transaction.
But, I have the following doubts:
I heard that Spring creates a proxy class? Can someone explain this in more depth. What actually resides in that proxy class? What happens to the actual class? And how can I see Spring's created proxied class
I also read in Spring docs that:
Note: Since this mechanism is based on proxies, 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!
Source: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
Why only external method calls will be under Transaction and not the self-invocation methods?
This is a big topic. The Spring reference doc devotes multiple chapters to it. I recommend reading the ones on Aspect-Oriented Programming and Transactions, as Spring's declarative transaction support uses AOP at its foundation.
But at a very high level, Spring creates proxies for classes that declare #Transactional on the class itself or on members. The proxy is mostly invisible at runtime. It provides a way for Spring to inject behaviors before, after, or around method calls into the object being proxied. Transaction management is just one example of the behaviors that can be hooked in. Security checks are another. And you can provide your own, too, for things like logging. So when you annotate a method with #Transactional, Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism.
Transactions in EJB work similarly, by the way.
As you observed, through, the proxy mechanism only works when calls come in from some external object. When you make an internal call within the object, you're really making a call through the this reference, which bypasses the proxy. There are ways of working around that problem, however. I explain one approach in this forum post in which I use a BeanFactoryPostProcessor to inject an instance of the proxy into "self-referencing" classes at runtime. I save this reference to a member variable called me. Then if I need to make internal calls that require a change in the transaction status of the thread, I direct the call through the proxy (e.g. me.someMethod().) The forum post explains in more detail.
Note that the BeanFactoryPostProcessor code would be a little different now, as it was written back in the Spring 1.x timeframe. But hopefully it gives you an idea. I have an updated version that I could probably make available.
When Spring loads your bean definitions, and has been configured to look for #Transactional annotations, it will create these proxy objects around your actual bean. These proxy objects are instances of classes that are auto-generated at runtime. The default behaviour of these proxy objects when a method is invoked is just to invoke the same method on the "target" bean (i.e. your bean).
However, the proxies can also be supplied with interceptors, and when present these interceptors will be invoked by the proxy before it invokes your target bean's method. For target beans annotated with #Transactional, Spring will create a TransactionInterceptor, and pass it to the generated proxy object. So when you call the method from client code, you're calling the method on the proxy object, which first invokes the TransactionInterceptor (which begins a transaction), which in turn invokes the method on your target bean. When the invocation finishes, the TransactionInterceptor commits/rolls back the transaction. It's transparent to the client code.
As for the "external method" thing, if your bean invokes one of its own methods, then it will not be doing so via the proxy. Remember, Spring wraps your bean in the proxy, your bean has no knowledge of it. Only calls from "outside" your bean go through the proxy.
Does that help?
As a visual person, I like to weigh in with a sequence diagram of the proxy pattern. If you don't know how to read the arrows, I read the first one like this: Client executes Proxy.method().
The client calls a method on the target from his perspective, and is silently intercepted by the proxy
If a before aspect is defined, the proxy will execute it
Then, the actual method (target) is executed
After-returning and after-throwing are optional aspects that are
executed after the method returns and/or if the method throws an
exception
After that, the proxy executes the after aspect (if defined)
Finally the proxy returns to the calling client
(I was allowed to post the photo on condition that I mentioned its origins. Author: Noel Vaes, website: https://www.noelvaes.eu)
The simplest answer is:
On whichever method you declare #Transactional the boundary of transaction starts and boundary ends when method completes.
If you are using JPA call then all commits are with in this transaction boundary.
Lets say you are saving entity1, entity2 and entity3. Now while saving entity3 an exception occur, then as enitiy1 and entity2 comes in same transaction so entity1 and entity2 will be rollback with entity3.
Transaction :
entity1.save
entity2.save
entity3.save
Any exception will result in rollback of all JPA transactions with DB.Internally JPA transaction are used by Spring.
All existing answers are correct, but I feel cannot give this complex topic justice.
For a comprehensive, practical explanation you might want to have a look at this Spring #Transactional In-Depth guide, which tries its best to cover transaction management in ~4000 simple words, with a lot of code examples.
It may be late but I came across something which explains your concern related to proxy (only 'external' method calls coming in through the proxy will be intercepted) nicely.
For example, you have a class that looks like this
#Component("mySubordinate")
public class CoreBusinessSubordinate {
public void doSomethingBig() {
System.out.println("I did something small");
}
public void doSomethingSmall(int x){
System.out.println("I also do something small but with an int");
}
}
and you have an aspect, that looks like this:
#Component
#Aspect
public class CrossCuttingConcern {
#Before("execution(* com.intertech.CoreBusinessSubordinate.*(..))")
public void doCrossCutStuff(){
System.out.println("Doing the cross cutting concern now");
}
}
When you execute it like this:
#Service
public class CoreBusinessKickOff {
#Autowired
CoreBusinessSubordinate subordinate;
// getter/setters
public void kickOff() {
System.out.println("I do something big");
subordinate.doSomethingBig();
subordinate.doSomethingSmall(4);
}
}
Results of calling kickOff above given code above.
I do something big
Doing the cross cutting concern now
I did something small
Doing the cross cutting concern now
I also do something small but with an int
but when you change your code to
#Component("mySubordinate")
public class CoreBusinessSubordinate {
public void doSomethingBig() {
System.out.println("I did something small");
doSomethingSmall(4);
}
public void doSomethingSmall(int x){
System.out.println("I also do something small but with an int");
}
}
public void kickOff() {
System.out.println("I do something big");
subordinate.doSomethingBig();
//subordinate.doSomethingSmall(4);
}
You see, the method internally calls another method so it won't be intercepted and the output would look like this:
I do something big
Doing the cross cutting concern now
I did something small
I also do something small but with an int
You can by-pass this by doing that
public void doSomethingBig() {
System.out.println("I did something small");
//doSomethingSmall(4);
((CoreBusinessSubordinate) AopContext.currentProxy()).doSomethingSmall(4);
}
Code snippets taken from:
https://www.intertech.com/Blog/secrets-of-the-spring-aop-proxy/
The page doesn't exist anymore.
I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.
I'm trying to test a service class (responsible for calling the repository layer and do some operations if needed), basically, this is the class I'm trying to test
class CarServiceImpl{
public Car findById(String id){
//call repository layer to find a car
}
public void deleteById(String id){
Car car = this.findById(id);
if(car != null){
//Call repository layer to update the car
}else{
Throw NotFOundException();
}
}
}
As you can see I call the findById method on the deleteById method, so my questions are.
is it really code smell to call a method on the same class? I don think I should create a separate class to find a car by id.
how can I mock the call to "findById" on the "deleteById" method, if I use Mockito.when(carServiceImpl.findById("car1")).thenReturn(carModel);
it stills call the method so i'll need to mock the call to respository for finding by id too, even when i already tested the method findById.
This isn't necessarily a smell and you can partially mock Car like so:
String carId = "...";
Car car = ...;
CarServiceImpl car = mock(CarServiceImpl.class);
when(car.findById(carId)).thenReturn(car);
when(car.deleteById(carId)).thenCallRealMethod();
But if you can allow deleteById() to execute the 'real method' then your test must already have a repository in which case letting findById() be a 'real call' is simple and improves the quality of your test coverage at ~no additional cost. The fact that you have already tested findById() doesn't mean that you shouldn't test it again, indirectly, as part of deleteById().
I would suggest that you do either or both of the following:
Unit test Car by giving it a mocked repository and using mocked expectations and verifications to test all of its methods
Functional/Acceptance test Car by giving it a real repository and using real invocations on the underlying store to assert actual results for each of its methods
On a separate note, I'm guessing the idea of injecting a repository into a domain object is a deliberate use of the "active record" pattern where your entities know how to CRUD themselves. This could be considered a code smell; it breaches the SRP and could be held to be a poor separation of concerns because the domain object knows about two things: its own state and how to persist itself.
You want your test setup and test code to be as "minimalistic" as possible. In that sense, the other answer is correct in saying: if you can test deleteById() without a special setup then go for that.
And would it turn out that findById() is by itself a "huge" thing that requires a lot of test setup - then I would rather step back and consider putting the content of this method into a distinct class - some kind of CarIdentityService.
Meaning: very often when we start making test code more complex - the better answer is to step back and change the design of our production code. In your case, you might want to push the whole findById() code into a distinct class - and now you can simply mock that finder object within your CarService class.
And just for the record: CarIdentityService could be a local or inner class of CarService. But introducing it might allow you to streamline you implementation and avoid getting into the spy business.
What happens when I call one transactional method from another transactional method, now my second transactional method completed, and it came back in 1st transactional method, and unfortunately it fail, so will it roll back everything, means will it roll back 2nd transactional method changes..?? Note: both method are in same class
#Transactional
public void method1(){
//do something
call method2();
//do something
...
...
failed here
}
#Transactional
public void method2(){
//do something
save()
}
So in above example will it rollback whatever I saved in 2nd transactional method?
It depends on the txType. By default it is REQUIRED. So the first method starts the transaction and the same transaction is used for the call to method2.
Also be careful that a method call inside the same object does not trigger the transaction processing. As typically the transaction handling is handled as proxy that only works when calling an injected other bean. In your example you would not notice a difference though.
A case where this would matter is if method1 is not #Transactional and method2 is. In this case there would be no transaction at all.
If both methods are in the same class, the #Transactional annotation won't even be considered when calling from another method of the same class. It doesn't matter what you put there, or even if you leave it out. There still will be a transaction started by method1(), but then you're stuck in that transaction.
If the second method were in a separate class, you could use Propagation.REQUIRES_NEW to have it run in its own transaction, meaning that even if method1() later on failed, any changes in method2() would still have made.
The default transaction propagation of REQUIRED starts a new transaction if none exist, or joins an existing transaction. Again, in the separate class situation it results in the rollback of any changes made in method2() when method1() fails.
Spring boot provides concept of propagation with #Transactions. Propagation level decides that inner transaction should be part of same outer transaction or it should be different isolated one. By default propagation level is REQUIRED which means inner transaction will be part of same outer transaction, so if inner transaction fails whole transaction will get rollback.
Now its important to know that Rollback works for only Runtime exceptions by default. For checked Exceptions you have to specify that explicitly #Transcations(rollbackFor = Exception.class)
So to answer for your question is YES! It does rollback changes made by inner transaction.
this is a typical question:
You should call method2() by self injected object or use this notation, because another ways will call method2 and avoid call proxy object method, which contain all transactional logic.
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct
Nested Transaction behaviour depends on #Transactional parameters. For example - Use PROPAGATION_REQUIRES_NEW for create new transaction for nested methods with #Transactional. See more info in official doc
What happens depends on the chosen transaction propagation. Default is: "REQUIRED" which means that if no transaction exists it will be started.
So in your code method2 will join existing transaction created for method1.
As for your case with both methods in the same class, be careful as this will not work as you expect because of the way Spring proxy objects work.
It depends on your transaction propagation config.
Related official doc is here
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation
Just note the graph, propagation define a transaction's "transaction context".
I'm using a Interface with #Transaction, and I have a method that performs a loop and check some information, but this loop takes long time to finish it, and i added a parameter in the database. And inside of the loop, is checked the parameter, and if is equal true, the loop will stop.
My problem is at the moment that check the parameter, it not get the parameter updated, it keep with the old value of the parameter.
is there a way to keep the transaction on interface and disable for specific method?
Try to split in two your method and you put "Requires new" on that check the parameters, in order to create a new transaction and suspend the current transaction if one exists.
#Transactional(propagation = Propagation.REQUIRES_NEW)
I hope I've given you all the answers about your question.
The first thing is undestand why you are using #Transaction on interfaces, beacause the correct way is to annote concrete classes (and methods of concrete classes) with the #Transactional annotation.
From spring references documentation:
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
Then can you share your code with us?