Update an object Within new Transactional Scope - java

I have a problem related to Transactional boundaries and I am not able to figure out what is going wrong.
#Transactional( propagation = Propagation.REQUIRED )
Class A {
void methodA() {
try {
new B().callMethodB(obj)
} catch(Exception e) {
updateSomeProperty(obj1)
}
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
void updateSomeProperty(Object obj1) {
obj1.setProperty(1);
obj1.save();
}
}
Class B {
public void callMethodB(Object obj) throws Exception {
throws new Exception();
}
}
The problem is that my object is not updating when the error is thrown . I also tried firing SQL code from within the method updateSomeProperty but that also did not work.
Basically I want to update the object's property whether despite the exception is thrown.
Any ideas ??

And it should not work. Because you call updateSomeProperty(obj1) from another method of the class and try to change default Transactional behaviour (from REQUIRED to REQUIRED_NEW). But it will not work. Thats why all your changes will be rolled back when exception occurs.
By default Spring creates proxy for interface and #Transactional annotation should be used only for public method. And this method should be called from "outside". If you will call them from another method within the class then #Transactional annotation will not work.
You can also change default settings for transactions in xml (look at properties proxy-target-class and mode). But I have never changed this and don't remember how exactly it should work.
<tx:annotation-driven transaction-manager="txManager" mode="..." proxy-target-class="..."/>
EDIT:
By the way. Here is a very good article about transaction pitfalls. It helped me very much. There are also few other very interesting articles about transactions.
EDIT 2:
Hello again. I think that I find solution for your problem. At least I tested this and it works for me well.
I proposed you to change transaction mode to "AspectJ" and to use AspectJ compile time wieving for project. This will give you a possibility to call a private transactional method from another method within one class with changing transactional behaviour (for started nested transaction). In such case you can commit some changes in nested transaction while outer transaction will be rolled back. For this you need to do such steps:
1) Change transaction mode in transactional definition:
- if you use xml configuration then:
<tx:annotation-driven transaction-manager="txManager" mode="aspectj"/>
if you use java configuration then:
#EnableTransactionManagement(mode=AdviceMode.ASPECTJ, proxyTargetClass=false)
2) Add aspectj dependencies to pom:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
3) Add spring-aspects dependency to pom:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
4) Add maven plugin that enables compile time wieving:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>${compiler.version}</source>
<target>${compiler.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${compiler.version}</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>false</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!-- <goal>test-compile</goal> -->
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
5) Also I have maven compiler plugin in my pom thats why I think that it is beter for you to add it too:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>${compiler.version}</compilerVersion>
<fork>true</fork>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
*Note: I use jdk version 1.7+. And my versions of the compiler and aspectj is sush:
<compiler.version>1.7</compiler.version>
<aspectj.version>1.6.12</aspectj.version>
Also I have such versions of other libraries (but I think this is not necessary):
<org.springframework.version>3.1.0.RELEASE</org.springframework.version>
<org.hibernate.version>4.1.0.Final</org.hibernate.version>
<org.springdata.version>1.0.2.RELEASE</org.springdata.version>
You also can try to use load time wieving in spring, but it is
more hard to configure (this is my opinion) and it is not recommended to be used in production (as I read in few posts). But if you will decide to use it you can find a lot of info in web and spring reference dicumentation.
If you want to use compile time wieving without maven then I don't know how to configure this. (I tested only with maven). You can try to find such info in web but I don't recomend this because with maven it is much easier to handle dependencies (and in case of this example - to add necessary plugin).
Here is an example that I used for tests:
Some interface:
public interface TestClassInterface {
void testMethod();
}
Some test class that implements this interface:
#Transactional(propagation = Propagation.REQUIRED, rollbackFor=Exception.class)
#Component
public class TestClass implements TestClassInterface {
#Autowired
private SpringDataFooDAO fooDao;
public void testMethod() {
try {
Foo foo = fooDao.findOne(2L);
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
foo.setName("should be rolled back");
new ExceptionThrower().doSomething("default string");
} catch(Exception e) {
updateSomeProperty(1L, "Changed name");
throw new RuntimeException(e);
}
}
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
private void updateSomeProperty(long id, String newFooName) {
System.out.println(" --- ");
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
// Update property of test object.
Foo foo = fooDao.findOne(id);
foo.setName(newFooName);
}
}
Another class with method that throws exception:
public class ExceptionThrower {
public void doSomething(Object obj) throws Exception {
throw new Exception();
}
}
Note that I rethrow exception from catch block (I do this as Runtime exception because I don't need to handle it in upper classes). This is necessary for correct outer transaction rollback.

Check out the spring reference for how to use #Transactional. #Transactional when using spring proxies comes with a lot of **conditions apply, you need to understand them before applying it in your code.
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.
Consider the use of AspectJ mode (see mode attribute in table below)
if you expect self-invocations to be wrapped with transactions as
well. In this case, there will not be a proxy in the first place;
instead, the target class will be weaved (that is, its byte code will
be modified) in order to turn #Transactional into runtime behavior on
any kind of method.

Can you try specifing noRollbackFor = RuntimeException.class or any other class which you want and hopefully it will let you update the database. i.e. #Transactional(noRollbackFor = RuntimeException.class)

The above arrangement is perfect to start off a new transaction and do other stuff different from the original transaction.
The one thing which was going wrong in my case was that while in the other transaction, I was throwing an exception myself resulting in the second transaction being rolled back again..
So The thing is beware off exception in the transaction because they ensure that the database state rolls back. It is for what they are meant for.
Thanks

Create a custom exception and use it to throw, Also please use #ApplicationException(rollback=false) on as class level annotation while defining custom exception.
e.g.
#ApplicationException(rollback=false)
public CustomException extends Exception{

Related

Spring AOP this() PCD context binder doesn't work with aspect instantiation model perthis()

I'm trying to log which aspect instance is responsible for which proxied object. However, when I'm collecting proxy object context through this() PCD and using perthis() instantiation model I'm getting an error related to the variable name of proxy object that I use in the pointcut expression:
warning no match for this type name: bean [Xlint:invalidAbsoluteTypeName]
Maven dependencies that I use:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
</dependencies>
This is an aspect that I use to implement that I needed:
#Aspect("perthis(com.sj.aspects.AssociationsAspect.exampleBeans())")
#Component
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AssociationsAspect {
public AssociationsAspect(){
System.out.println("Creating aspect instance!");
}
#Pointcut("execution(* com.sj.utilities.Example.*(..))")
public void exampleBeans(){};
#Pointcut("execution(* com.sj.utilities.Example.*(..)) && this(bean)")
public void exampleOperations(Object bean){};
#Before(value = "exampleOperations(bean)", argNames = "jp,bean")
public void beforeExampleMethodsExecution(JoinPoint jp, Object bean){
System.out.println(
"JoinPoint: " + jp.getStaticPart() +
"\n\taspect: " + this +
"\n\tobject: " + bean
);
}
}
I tried to change bean as variable name to concrete type, but from documentation it will give different from binding result:
Any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
this(com.xyz.service.AccountService)
As well as it will be changing exiting error to another:
error at ::0 formal unbound in pointcut
Funny enough, if you put away ("perthis(com.sj.aspects.AssociationsAspect.exampleBeans())") then everything will work fine and Spring container will create a separate aspect instance for every proxy object in it. However that is not desirable and most likely a bug, because through #Scope() annotation I only say that there can be multiple instances of same aspect and that Spring container will need to create new instance when I told it to do, but not that it need to create them when it wants to.
The final solution to which I came was to use JoinPoint reflection API instead of collecting context through this() PCD. And it works fine, however I have preconceptions related to how #Scope() works without perthis() instantiation model and with it.
In the end I want to know, 'Is there a solution for collecting proxy object context with this() PCD and using perthis() instantiation model at the same time?'. As well as what are mistakes in the aspect that I described earlier, that give such an error.
I am assuming that you got the syntax example for perthis() from this part of the Spring manual. Unfortunately, the syntax is wrong. Inside perthis(), you need to specify a valid pointcut such as, not just a method name without even a return type. Examples for valid clauses would be:
perthis(myPointcut()), if myPointcut is specified as a separate, named pointcut
perthis(this(org.acme.MyClass))
perthis(execution(* doCommand(..))
perthis(execution(* doCommand(..)) && this(org.acme.MyClass))
See also the AspectJ documentation here and there. Unfortunately, documentation is sparse.
In your particular case, you might want:
perthis(execution(* com.sj.utilities.Example.*(..)))
Update: I created Spring pull request # 29998 in order to improve the documentation.

Intercept nested methods using native AspectJ in Spring Boot

I am trying to intercept any method in my application which is annotated with my custom developed annotation.
Initially I used the Spring AOP which works fine. But, it is not intercepting if the method call is in the same target class.
Going through the official docs, I got to know that the Spring AOP uses proxy beans for the same.
One workaround I found was to self inject the target class. But, this seems like too much fuss. Like every time I am adding my custom annotation to a method, I need to make sure that I add the #Scope annotation, set the proxyMode & self inject target class as shown here
Later I moved on to configuring and using native AspectJ.
This is my Custom annotation:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface TrackTime {
String description() default "";
}
Here is the Aspect for TrackTime annotation:
#Configuration
#Slf4j
#Aspect
public class TrackTimeServiceImpl {
#Pointcut("execution(public * *(..))")
public void methodsToBeProfiled(){
}
#Around("methodsToBeProfiled() && #annotation(x.y.z.TrackTime)")
public Object audit(ProceedingJoinPoint joinPoint) throws Exception {
//Business logic
}
}
I would like to mention here that my application is running on Jetty server.
The configuration file:
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableSpringConfigured
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class TrackTimeConfig implements LoadTimeWeavingConfigurer {
#Override
public LoadTimeWeaver getLoadTimeWeaver() {
return new InstrumentationLoadTimeWeaver();
}
}
The aop.xml file:
Path to file: /resources/META-INF/aop.xml
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="in.xxx.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="in.xxx.yyy.zzz.TrackTimeServiceImpl"/>
</aspects>
</aspectj>
Relative dependencies added in parent pom.xml have been mentioned here:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.21</version>
</dependency>
My service class:
#Component
public class SomeService {
public void a(){
b();
}
#TrackTime
public void b(){
//business logic
}
}
Now when the method a() is called from the controller, even though the b() has the #TrackTime annotation, it is not intercepted.
Also, I would like to mention that I have set the following program arguments while running the application
-javaagent:/Users/xxx/.m2/repository/org/springframework/spring-instrument/5.3.6/spring-instrument-5.3.6.jar
-javaagent:/Users/xxx/.m2/repository/org/aspectj/aspectjweaver/1.9.6/aspectjweaver-1.9.6.jar
I have gone through docs, articles, followed solutions on stackoverflow. But, for the above mentioned configuration/code, it is not working as I want.
Requesting help from the community.
Thanks in advance.
I did not try to run your example locally yet, but noticed two details at first glance in your code:
You are configuring both #EnableLoadTimeWeaving (for native AspectJ) and #EnableAspectJAutoProxy (for Spring AOP), which might be conflicting with each other. Try to remove the latter and see if it fixes the problem.
In aop.xml, you are using <include within="in.xxx.*"/>. Please note that this will only include classes directly in the in.xxx package, but not classes in sub-packages. In order to include them as well, please use the double-dot notation in.xxx..*.
Feel free to report back if it is still not working with the suggested changes. I can take a closer look then.
First of all, I would like to thank #hfontanez, #void void & #kriegaex for responding and helping me out in moving forward in solving the problem statement.
So if anyone is looking out on how to intercept nested & private methods, let's have this as a one stop in configuring native AspectJ.
Please check my POC here on github for a working example.
In my case, I added the aspectjweaver JAR in my project structure and passed the arguments through VM Options in IDE.
That all !!
Nested/Private methods will now be intercepted.
Thank you,
Karthik

Resilience4J in Springboot is not working as expecting

I'm trying to add resilience4j into my app for exponential backoff, etc.
Service
#Component
public class ResilienceService {
private static final String BACKEND_A = "backendA";
public ResilienceService() throws IOException {
testRetry();
}
#Retry(name = BACKEND_A)
public void testRetry() throws IOException {
System.out.println("Hey it's working!");
throw new IOException();
}
}
Config
resilience4j.retry.instances.backendA.maxAttempts=3
resilience4j.retry.instances.backendA.waitDuration=10s
resilience4j.retry.instances.backendA.enableExponentialBackoff=true
resilience4j.retry.instances.backendA.exponentialBackoffMultiplier=2
resilience4j.retry.instances.backendA.retryExceptions[0]=java.io.IOException
I'm trying to basically see if resilience lib will call this function 3 times. How should I think about both configuring this correctly and also testing that the retries are actually happening? I thought I could put a breakpoint on the method and see it call 3 times, but maybe I'm misunderstanding.
Aside from the comment by #M.Deinum above, you may also have caught out by resilience4j-springboot2 not depending on spring aop by default.
E.g. you might need:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
To be fair, the documentation does state:
Add the Spring Boot 2 Starter of Resilience4j to your compile dependency.
The module expects that org.springframework.boot:spring-boot-starter-actuator and org.springframework.boot:spring-boot-starter-aopare already provided at runtime

How to run a method before some special methods?

In my business, I have to execute a method (imagine an access controll-like method) before some special methods(e.g. save, update,etc) to check some prerequisites and then execute the intended method. It is obvious that the most simple way is to call that controlling method at the very beginning lines of those methods, but I'm looking for something like #Before. something clean.
Any answer/hints will be appreciated.
You can use Spring AOP + AspectJ
In simple, Spring AOP + AspectJ allow you to intercept method easily.
Common AspectJ annotations :
#Before – Run before the method execution #After – Run after the
method returned a result #AfterReturning – Run after the method
returned a result, intercept the returned result as well.
#AfterThrowing – Run after the method throws an exception #Around –
Run around the method execution, combine all three advices above.
Steps
1. First you should enable AspectJ
To enable AspectJ, you need aspectjrt.jar, aspectjweaver.jar and spring-aop.jar. See following Maven pom.xml file.
<!-- Spring AOP + AspectJ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
2. Enable AspectJ
In your context config file add
<aop:aspectj-autoproxy />
3. After that use AspectJ #Before
In below example, the method1() method will be executed before the execution of method2() method.
#Aspect
public class MyAspect {
#Before("execution(* your.package.method2(..))")
public void method1(JoinPoint joinPoint) {
System.out.println("method1() is running!");
System.out.println(" ---- " + joinPoint.getSignature().getName());
System.out.println("******");
}
}

Does Spring #Transactional attribute work on a private method?

If I have a #Transactional -annotation on a private method in a Spring bean, does the annotation have any effect?
If the #Transactional annotation is on a public method, it works and open a transaction.
public class Bean {
public void doStuff() {
doPrivateStuff();
}
#Transactional
private void doPrivateStuff() {
}
}
...
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
The answer your question is no - #Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them.
This is documented in Spring Manual chapter 10.5.6:
Method visibility and #Transactional
When using proxies, you should apply
the #Transactional annotation only
to methods with public visibility. If
you do annotate protected, private or
package-visible methods with the
#Transactional annotation, no error
is raised, but the annotated method
does not exhibit the configured
transactional settings. Consider the
use of AspectJ (see below) if you need
to annotate non-public methods.
The Question is not private or public, the question is: How is it invoked and which AOP implementation you use!
If you use (default) Spring Proxy AOP, then all AOP functionality provided by Spring (like #Transactional) will only be taken into account if the call goes through the proxy. -- This is normally the case if the annotated method is invoked from another bean.
This has two implications:
Because private methods must not be invoked from another bean (the exception is reflection), their #Transactional Annotation is not taken into account.
If the method is public, but it is invoked from the same bean, it will not be taken into account either (this statement is only correct if (default) Spring Proxy AOP is used).
#See Spring Reference: Chapter 9.6 9.6 Proxying mechanisms
IMHO you should use the aspectJ mode, instead of the Spring Proxies, that will overcome the problem. And the AspectJ Transactional Aspects are woven even into private methods (checked for Spring 3.0).
By default the #Transactional attribute works only when calling an annotated method on a reference obtained from applicationContext.
public class Bean {
public void doStuff() {
doTransactionStuff();
}
#Transactional
public void doTransactionStuff() {
}
}
This will open a transaction:
Bean bean = (Bean)appContext.getBean("bean");
bean.doTransactionStuff();
This will not:
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
Spring Reference: Using #Transactional
Note: 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!
Consider the use of AspectJ mode (see below) if you expect self-invocations to be wrapped with transactions as well. In this case, there won't be a proxy in the first place; instead, the target class will be 'weaved' (i.e. its byte code will be modified) in order to turn #Transactional into runtime behavior on any kind of method.
If you need to wrap a private method inside a transaction and don't want to use AspectJ, you can use TransactionTemplate.
#Service
public class MyService {
#Autowired
private TransactionTemplate transactionTemplate;
private void process() {
transactionTemplate.executeWithoutResult(status -> processInTransaction());
}
private void processInTransaction(){
//...
}
}
Yes, it is possible to use #Transactional on private methods, but as others have mentioned this won't work out of the box. You need to use AspectJ. It took me some time to figure out how to get it working. I will share my results.
I chose to use compile-time weaving instead of load-time weaving because I think it's an overall better option. Also, I'm using Java 8 so you may need to adjust some parameters.
First, add the dependency for aspectjrt.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.8</version>
</dependency>
Then add the AspectJ plugin to do the actual bytecode weaving in Maven (this may not be a minimal example).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Finally add this to your config class
#EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
Now you should be able to use #Transactional on private methods.
One caveat to this approach: You will need to configure your IDE to be aware of AspectJ otherwise if you run the app via Eclipse for example it may not work. Make sure you test against a direct Maven build as a sanity check.
Spring Docs explain that
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.
Consider the use of AspectJ mode (see mode attribute in table below)
if you expect self-invocations to be wrapped with transactions as
well. In this case, there will not be a proxy in the first place;
instead, the target class will be weaved (that is, its byte code will
be modified) in order to turn #Transactional into runtime behavior on
any kind of method.
Another way is user BeanSelfAware
The answer is no. Please see Spring Reference: Using #Transactional
:
The #Transactional annotation may be placed before an interface definition, a method on an interface, a class definition, or a public method on a class
Same way as #loonis suggested to use TransactionTemplate one may use this helper component (Kotlin):
#Component
class TransactionalUtils {
/**
* Execute any [block] of code (even private methods)
* as if it was effectively [Transactional]
*/
#Transactional
fun <R> executeAsTransactional(block: () -> R): R {
return block()
}
}
Usage:
#Service
class SomeService(private val transactionalUtils: TransactionalUtils) {
fun foo() {
transactionalUtils.executeAsTransactional { transactionalFoo() }
}
private fun transactionalFoo() {
println("This method is executed within transaction")
}
}
Don't know whether TransactionTemplate reuse existing transaction or not but this code definitely do.

Categories

Resources