38

The project I am working on has a similar structure for the DAOs to the one bellow:

/** 
* Base DAO class
*/
@Transactional    
public class JPABase {

  @PersistenceContext
  private EntityManager entityManager;

  public void persist(Object entity) {
    entityManager.persist(entity);
  }
 //some more methods in here
}

and

/** 
* Generic DAO class implementation
*/
@Transactional 
public abstract class GenericDao extends JpaBase {
   //some methods in here
}

and

/** 
* Specialized DAO class
*/
@Repository
@Transactional
public class PersonDao extends GenericDao {
  //some methods in here
}

Until now, the project used compile time weaving, but the configuration has changed to use <context:load-time-weaver/> with -javaagent:/opt/tomcat7-1/lib/spring-instrument.jar.

Since this change has been applied, the JpaBase's and GenericDao's @Transactional annotations are not weaved anymore. Each time a service class calls the persist method on a PersonDao object, no transaction is started.

Noteworthy:

  • this used to work in the past, when using compile time weaving.
  • all the methods that are defined in the PersonDao are weaved correctly, but the ones inherited (e.g. persist(Object entity)) are NOT weaved.

Compile time weaving and load time weaving are supposed to do the same thing, just at different moments in time. Why has the weaving behaviour changed?

Jay Shankar Gupta
  • 5,918
  • 1
  • 10
  • 27
Anca N
  • 381
  • 3
  • 5
  • IIRC you need to specify packages for LTW, maybe you're missing one? – Marvin Jul 01 '15 at 14:58
  • 2
    The whole project is included in the `within` attribute of the `` element, in the `aop.xml` file. – Anca N Jul 01 '15 at 15:23
  • 1
    Have you tried the tips and tricks from http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/ ? – Andrei Mărcuţ Jul 01 '15 at 21:56
  • 1
    First, @Transactional only should be in JPABase subclass. Secontly, try to put spring-instrument-tomcat.jar inside /lib path on your Apache Tomcat directory and config your context.xml on /conf with the class loader to weaver (org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader) – Dani Jul 10 '15 at 17:55
  • We finally switched to compile time weaving. Everything is working fine now :) – Anca N Oct 02 '15 at 07:18
  • Did you enable load-time weaving for AspectJ? Reading the docs, it seems like you either need to have a `META-INF/aop.xml` file present _on the classpath_ (in the war, instead of the jar?) or otherwise activate it via the code. See the [Spring docs for enabling load-time weaving](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/EnableLoadTimeWeaving.html) for more info. – Marco Oct 21 '15 at 11:16
  • @anca-n Could you post your solution as answer? – ksokol Nov 10 '15 at 07:53
  • 2
    @ksokol my understanding is, that they went back to compile time weaving instead of load time (so no solution)... – Betlista Jan 14 '16 at 06:56
  • Indeed we went back to compile time weaving and everything works fine now. – Anca N Apr 13 '16 at 13:17
  • Maybe scanning of the JARs for @Servlet and other web annotatios loads the class without weaving. Try disabling the scan for your library. Also check http://tomcat.apache.org/tomcat-7.0-doc/config/loader.html#Standard_Implementation – Ales Dolecek Jun 08 '17 at 04:32

2 Answers2

1

Tomcat default classlLoader is WebappClassLoader, but you need `TomcatInstrumentableClassLoader.

There are two solutions:

  1. Modify WebappLoader.class

Change WebappLoader.java

private String loaderClass =  "org.apache.catalina.loader.WebappClassLoader";

Replace:

private String loaderClass = "org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader";  

Compile it and replaced the class file(catalina.jar), then it works.

Here is required dependency jars: catalina.jar,tomcat-coyote.jar,tomcat-util.jar(/bin),tomcat-juli.jar

  1. Modify context.xml:


<?xml version="1.0" encoding="UTF-8"?>  
<Context>  
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>  
</Context>

Vikrant Kashyap
  • 6,398
  • 3
  • 32
  • 52
-1

You probably missing the public constructor chaining inside these classes, @Transactional will work only if classes are having public constructors and public methods.

ajay tomar
  • 384
  • 1
  • 16
  • the visibility of constructors doesn't matter. And the public methods only apply to proxy based AOP not when using Weaving. – M. Deinum Oct 01 '18 at 06:57