functional interface call within #Transactional method - java

I have read this #Transactional method called from another method doesn't obtain a transaction and learned that we can't call a #Transactional method from another method in the same class. I'm wondering if the following code works. I know that we can't put #Transactional on doSomething and have doSomethingTransactionally to call it directly, so I created a utility method that has #Transactional annotation in another class which takes in a function and execute it. The goal is to keep all the logic in the same class. If the following code does not work, is there a way to achieve this goal?
#Component
class A {
#Autowired
B b;
public String doSomethingTransactionally() {
return b.transactionalHelper(this::doSomething);
}
public String doSomething() {
// a bunch of db operations
}
}
#Component
class B {
#Transactional
public T transactionalHelper(Supplier<T> supplier) {
return supplier.get();
}
}

Related

Does spring self injection lead to memory leakage?

In Spring, beans are encapsulated by a proxy object and when called from outer object the proxy object's method is also called. By using this trick transaction management is performed in proxy object's methods.
But when you are calling a method in the same bean and if you want the called method to be run in another transaction with the caller method it is not possible. Since the method calls in the same bean does not pass through the proxy object which performs transaction operations.
In order to solve this, self-injection of the bean inside itself is proposed.
like this
#Service
public class MyService{
#Autowired
public MyService myService;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1(){
method2();// runs in the same transaction with method1
myService.method2();// runs in separate transaction from method1
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void method2(){
}
}
I want to ask whether self-injection leads to memory leakage.
Outer bean MyService includes injected myService and myService should include attribute of type MyService, which should include attribute of type MyService ....
The service is not copied, it is only a reference. But I'd be wary of such a design: it creates a circular reference and the object graph is impossible to create at once. You first need to create the incomplete service, then set its field. Furthermore, it is kind of confusing and surprising to find such a dependency to self
I'd propose a different solution:
#Component
public class WithTransaction {
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNew(final Runnable runnable) {
runnable.run();
}
}
#Service
public class MyService{
private final WithTransaction withTransaction;
#Autowired
public MyService(final WithTransaction withTransaction) {
this.withTransaction = withTransaction;
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1(){
method2();// runs in the same transaction with method1
withTransaction.requiresNew(this::method2); // runs in separate transaction from method1
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void method2(){
}
}
And if you can avoid it: don't call any public methods from your service on the service itself. Split the service into smaller components so that each "public" call must go through the proxy.

What happens when #Transactional(readonly=true) method calls #Transactional(readonly=false) method and vice versa?

I wonder, what happens when #Transactional(readonly=true) method calls #Transactional(readonly=false) method? Talking about the situation with propagation = Propagation.REQUIRED (within the outer transaction scope).
public class ServiceA {
ServiceB serviceB;
#Transactional(readonly = true)
public void readOnly() {
// some reading from repo
serviceB.write()
}
}
public class ServiceB {
#Transactional
public void write() {
// some write to repo
}
}
The same question for the opposite situation, what happens if #Transactional(readonly=false) method calls #Transactional(readonly=true) method? I suppose that for the last case it would just consider #Transactional(readonly=false) from the outer scope.
Calling readOnly=false from readOnly=true doesn't work since the previous transaction continues.
This is because the previous transactional is being continued.
If you want this to work, you must have it start a new transaction. Sample:
public class ServiceB {
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void write() {
// some write to repo ..
}
}
In this case, it will work because a new transactional will be started.

Spring #Transactional method and class

I understand that #Transactional annotation in class affect all the method and #Transactional annotation in method only affect this method and override the class annotation.
But, this code makes sense?(no more methods in class)
#Service
#Transactional
public class Service extends AbstractCrudService<A,Repository> {
#Transactional(readOnly=true)
public Optional<A> getByApplicant(B b) {
return repository.findByB(b);
}
Is the same if put #Transactional annotation only in method?
#Service
public class Service extends AbstractCrudService<A,Repository> {
#Transactional(readOnly=true)
public Optional<A> getByApplicant(B b) {
return repository.findByB(b);
}
Both examples work the same way
#Transactional on the class set on all methodos with #Transactional, but if you put #Transactional o method, this replace the class annotation
The #Transactional annotation on the class level will be applied to every method in the class.
However, when a method is annotated with #Transactional (like, getByApplicant(B b)) this will take precedence over the transactional settings defined at the class level.
More about it:
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/transaction.html

Applying multiple permutations of mocks to dependencies for better unit testing in Spring

Let's say I have a class (OrchestratingClass) that has a method orchestrate() that calls a number of smaller methods of other classes (classA's do1() method, classB's do2() method). I would like to test the behavior of orchestrate() by mocking the responses of do1() and do2() with various permutations. I'm running my test with something like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public OrchestratingClassTest {
#Inject
private OrchestratingClass oc;
#Test
public void test1() {
// I would like to mock classA's do1() method to send back "1"
// I would like to mock classB's do2() method to send back "2"
}
#Test
public void test2() {
// I would like to mock classA's do1() method to send back "100"
// I would like to mock classB's do2() method to send back "200"
}
static class SimpleConfig {
#Bean
public InterfaceA interfaceA() {
return new ClassA();
}
#Bean
public InterfaceB interfaceB() {
return new ClassB();
}
#Bean
public OrchestratingClass orchestratingClass() {
return new OrchestratingClass();
}
}
}
And the orchestratingClass itself is quite basic, but I've added some sample code to aid in visualization:
#Named
public OrchestratingClass {
#Inject
private InterfaceA interfaceA;
#Inject
private InterfaceB interfaceB;
public String orchestrate() {
return interfaceA.do1() + " " + interfaceB.do2();
}
}
Now I'm aware I could tweak my SimpleConfig class to have the mocked out versions of classA and classB, but then I'm locked into 1 particular mock and can't "re-mock" things when I move onto test2(). I'm convinced that playing around with the java config files for 1 single test class would not work if we're trying to inject different "flavors" of beans "per-test". Does anyone have any recommendation on what I can do to make sure I'm really testing this thoroughly without being invasive (ex: adding superfluous "setters" for the specific classes in the orchestratingClass to side-step the bean injection pain)? Essentially, I'm looking to "tamper" the applicationContext on a per-test basis for specific beans of interest (along with the necessary housekeeping that's required) by applying a variety of mocks.
Here's a simple example using Mockito:
public class OrchestratingClassTest {
#Mock
private ClassA mockA;
#Mock
private ClassB mockB;
#InjectMocks
private OrchestratingClass oc;
#Before
public void prepare() {
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldConcatenate() {
when(mockA.do1()).thenReturn("1");
when(mockB.do2()).thenReturn("2");
assertEquals("1 2", oc.orchestrate());
}
}
The magic happens in the call to MockitoAnnotations.initMocks(this), which will create mock instances for the fields annotated with #Mock, then create a real instance of Orchestrating class and inject its fields, thanks to #InjectMocks.
Note that, even without this magic, you could make your class easily testable by just adding a constructor taking ClassA and ClassB as arguments to OrchestratingClass, and annotate that constructor with #Autowired instead of annotating the fields. So, in short, use constructor injection rather than field injection.

What is the difference between defining #Transactional on class vs method

Case1
#Transactional
public class UserServiceImpl implements UserService {
...................
public void method1(){
try{
method2();
}catch(Exception e){
}
}
public void method2(){
}
}
Case2
public class UserServiceImpl implements UserService {
...................
public void method1(){
try{
method2();
}catch(Exception e){
}
}
#Transactional
public void method2(){
}
}
In case1 if any exception occurs it rollback is working, but in case 2 it's not working. Is there any performance issues if I follow the case1?
In case 1 #Transactional is applied to every public individual method. Private and Protected methods are Ignored by Spring.
Spring applies the class-level annotation to all public methods of
this class that we did not annotate with #Transactional. However, if
we put the annotation on a private or protected method, Spring will
ignore it without an error.
In case 2 #Transactional is only applied to method2(), not on method1()
Case 1:
- Invoking method1() -> a transaction is started. When method1() calls method2() no new transaction is started, because there is already one
Case 2:
- Invoking method1() -> no transaction is started. When method1() calls method2() NO new transaction is started. This is because #Transactional does not work when calling a method from within the same class. It would work if you would call method2() from another class.
From the spring reference manual:
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.
#Transactionalon a class applies to each method on the service. It is a shortcut. Typically, you can set #Transactional(readOnly = true) on a service class, if you know that all methods will access the repository layer. You can then override the behavior with #Transactional on methods performing changes in your model. Performance issues between 1) and 2) are not known.
Suppose you have the following class:
#Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}
The #Transactional annotation on the class level will be applied to every method in the class.
However, when a method is annotated with #Transactional (like, updateFoo(Foo foo)) this will take precedence over the transactional settings defined at the class level.
More info:
Transaction management in Spring
Quoting from here
The Spring team's recommendation is that you only annotate concrete classes with the #Transactional annotation, as opposed to annotating interfaces.
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!

Categories