• Post Reply Bookmark Topic Watch Topic
  • New Topic

javax.persistence.TransactionRequiredException - @Transactional Issue (Class/Method level)  RSS feed

 
Vaibhav Gargs
Ranch Hand
Posts: 112
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I am trying to use transactional annotation in my code but getting an exception as below:

If I use the @Transactional at class level, it works fine without any exception but if I move this annotation to the method wherein I am persisting the code, it is giving me the exception.

What is the reason for this?





javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:54) ~[hibernate-entitymanager-5.1.2.FINAL.jar:5.1.2.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:362) ~[spring-orm-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at com.sun.proxy.$Proxy49.executeUpdate(Unknown Source) ~[na:na]
at com.rbs.amservices.ugc.repository.AreteResourceRepositoryImpl.create(AreteResourceRepositoryImpl.java:81) ~[classes/:na]
at com.rbs.amservices.ugc.repository.AreteResourceRepositoryImpl.findByPath(AreteResourceRepositoryImpl.java:60) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:201) ~[spring-aop-4.1.5.RELEASE.jar:4.1.5.RELEASE]
at com.sun.proxy.$Proxy37.findByPath(Unknown Source) ~[na:na]
at com.rbs.amservices.ugc.service.AreteResourceService.findResource(AreteResourceService.java:25) ~[classes/:na]
at com.rbs.amservices.ugc.web.AreteResourceController.findResource(AreteResourceController.java:73) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.1.5.RELEASE.jar:4.1.5.RELEASE]


Thanks,
Vaibhav
 
Atul More
Ranch Hand
Posts: 67
1
Java jQuery Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
HI,

You can not mark @Transactional annotaion in DAO class where you create EntityManager.
You are already mentioned the DAO class with @Reposirtory.
Mark the method @Transactional from where you called the DAO method.
 
Dave Tolls
Ranch Foreman
Posts: 2996
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
at com.rbs.amservices.ugc.repository.AreteResourceRepositoryImpl.create(AreteResourceRepositoryImpl.java:81) ~[classes/:na]
at com.rbs.amservices.ugc.repository.AreteResourceRepositoryImpl.findByPath(AreteResourceRepositoryImpl.java:60) ~[classes/:na]


Since create() is being called by another method in the same class, standard AOP won't work, essentially meaning that the code represented by the Transactional annotation is not run...that requires the method to be called from "outside" the class.
So in this case, as the exception shows, you don't actually have a Transaction.

If you were to call the create() method from somewhere else (external to the object) then it would work.
 
Vaibhav Gargs
Ranch Hand
Posts: 112
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Atul & Dave.

Can you please explain the reason behind this?
 
Dave Tolls
Ranch Foreman
Posts: 2996
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aspect Oriented Programming (AOP) generally intercepts calls to methods on an object.  This is normally done "externally" to the object, so any calls within the object are not intercepted (there are ways in which to achieve this, but they depend on what AOP framework you are using).

So:

would work.

In your case, though, you are already inside the object (in the findByPath method) when create is called, so the intercept simply doesn't happen.

The answer on this SO thread covers Spring's proxy-based AOP.
 
Vaibhav Gargs
Ranch Hand
Posts: 112
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Dave.

But, in my case, I am calling create method from findByPath() method. And, create() method is annotated with @Transactional. So, shouldn't it intercept the create method?

Shouldn't it create a proxy such as:

findByPath(){

--- Begin Transaction

create();

--- End Transaction


}
 
Dave Tolls
Ranch Foreman
Posts: 2996
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No.
As the SO thread says, Spring uses a Proxy for its AOP, so the interception can only happen from outside.
Once you are inside the class then no interception can take place.


That;s essentially what's happening.
As you can see, the call to findByPath just goes into the real object, and once there it is not possible to intercept the internal call to create.

Now, I'm not sure if Spring AOP has any mechanism to allow for that.  It never used to.
AspectJ I think had some jiggery pokery it could do to achieve it, but I'm not sure.
 
Vaibhav Gargs
Ranch Hand
Posts: 112
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Dave!! I understood the concept now.

The issue is resolved if I put the annotation over class or findByPath method.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!