SOLVED: See reply below.
I've been at this all day, and I've tried 3 different load-time weaving mechanisms: TomcatInstrumentableClassLoader, Spring javaagent, and AspectJ javaagent. None of them work, although the AspectJ javaagent seems to give the most positive log output.
The Tomcat class loader method simply wouldn't expose any of my classes for weaving. I got a long list of hibernate classes, but none of my domain entities would show up in the log. The Spring javaagent wasn't any better. Finally, I removed the <context:load-time-weaver /> instruction and launched with the AspectJ weaver as a java agent. Here's the full startup log (note the AspectJ block, and Join point MyEntityListener.<init>()):
(above: removed bean list and did some cleanup to shorten post length)Code:INFO: Initializing ProtocolHandler ["http-bio-8080"] [AspectJ] AspectJ Weaver Version 1.6.12 built on Tuesday Oct 18, 2011 at 17:52:06 GMT [AspectJ] register classloader org.apache.catalina.loader.WebappClassLoader@5c71949b [AspectJ] using configuration /D:/fcps/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ltw-test/WEB-INF/classes/META-INF/aop.xml [AspectJ] using configuration file:/D:/fcps/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ltw-test/WEB-INF/lib/org.springframework.aspects-3.1.0.RELEASE.jar!/META-INF/aop.xml [AspectJ] register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect [AspectJ] register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect [AspectJ] register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect [AspectJ] register aspect org.springframework.cache.aspectj.AnnotationCacheAspect [AspectJ] Join point 'method-execution(java.lang.String ltw.test.AddContentImpl.addContent(java.lang.String))' in Type 'ltw.test.AddContentImpl' (AddContentImpl.java:25) advised by before advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:60) [AspectJ] Join point 'method-execution(java.lang.String ltw.test.AddContentImpl.addContent(java.lang.String))' in Type 'ltw.test.AddContentImpl' (AddContentImpl.java:25) advised by afterThrowing advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:67) [AspectJ] Join point 'method-execution(java.lang.String ltw.test.AddContentImpl.addContent(java.lang.String))' in Type 'ltw.test.AddContentImpl' (AddContentImpl.java:25) advised by afterReturning advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:77) [AspectJ] Join point 'method-execution(java.lang.String ltw.test.AddContentImpl.addContent(java.lang.String))' in Type 'ltw.test.AddContentImpl' (AddContentImpl.java:25) advised by after advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:82) [AspectJ] Extending interface set for type 'ltw.test.MyEntityListener' (MyEntityListener.java) to include 'org.springframework.beans.factory.aspectj.ConfigurableObject' (AnnotationBeanConfigurerAspect.aj) [AspectJ] Join point 'initialization(void org.springframework.beans.factory.aspectj.ConfigurableObject.<init>())' in Type 'ltw.test.MyEntityListener' (MyEntityListener.java:15) advised by before advice from 'org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect' (AbstractDependencyInjectionAspect.aj:78) [with runtime test] [AspectJ] Join point 'initialization(void org.springframework.beans.factory.aspectj.ConfigurableObject.<init>())' in Type 'ltw.test.MyEntityListener' (MyEntityListener.java:15) advised by afterReturning advice from 'org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect' (AbstractDependencyInjectionAspect.aj:87) [with runtime test] [AspectJ] Join point 'initialization(void ltw.test.MyEntityListener.<init>())' in Type 'ltw.test.MyEntityListener' (MyEntityListener.java:15) advised by afterReturning advice from 'org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect' (AbstractDependencyInjectionAspect.aj:87) [with runtime test] [AspectJ] javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified INFO: No Spring WebApplicationInitializer types detected on classpath INFO: Initializing Spring FrameworkServlet 'spring' INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'spring': initialization started INFO o.s.w.c.s.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'spring-servlet': startup date [Wed Jan 25 20:46:14 AST 2012]; root of context hierarchy INFO o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring-servlet.xml] INFO o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [META-INF/ltw-test-context.xml] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'ltw-test' (hibernate logging) (MVC mappings)
I tried to keep things as simple as I could, to the point where I created this project from scratch in reflection of the project I first had the problem with, to get a small(ish) test project. Here's my META-INF/persistence.xml:
And my META-INF/aop.xml:Code:<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <persistence-unit name="ltw-test" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>java:comp/env/jdbc/ltw-test</non-jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> <property name="hibernate.hbm2ddl.auto" value="create"/> </properties> </persistence-unit> </persistence>
My application context XML (WEB-INF/spring-servlet.xml):Code:<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver options="-showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler"> <include within="ltw.test.*" /> </weaver> </aspectj>
My web.xml, for the fun of it:Code:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee"> <context:annotation-config /> <context:component-scan base-package="ltw.test" /> <context:spring-configured /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> </bean> <tx:annotation-driven /> </beans>
The class I want weaved:Code:<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="ltw-test" version="3.0"> <display-name>ltw-test</display-name> <welcome-file-list> <welcome-file>index.jspx</welcome-file> </welcome-file-list> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/spring/*</url-pattern> </servlet-mapping> </web-app>
Obviously there are a few more components (The entity, JNDI data source definition, the DAO, and an interface/implementation for the MVC controller) but that's the just of it. I added -javaagent:aspectjweaver.jar to my startup. The ctx field of MyEntityListener is always null. I simply can't get this to work no matter what I try. Any help would be greatly appreciated. I know this has been done with Spring Data JPA but I'd rather find out why this setup isn't working than abandon my troubleshooting to try something else (and Spring Data JPA uses Jodatime, but that's another topic..)Code:package ltw.test; import javax.persistence.PostPersist; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Configurable( value="myEntityListener" ) @Component( "myEntityListener" ) @Scope( BeanDefinition.SCOPE_PROTOTYPE ) public class MyEntityListener { @Autowired private ApplicationContext ctx; @PostPersist public void postPersist( MyEntity e ) { if ( this.ctx == null ) { throw new IllegalArgumentException( "No application context" ); } } }
Thanks,
Scott
PS: The project is about 14MB in size with the libraries, I'm more than happy to attach it if desired.


Reply With Quote
