#AspectJ aspects not being weaved in application that uses Spring - spring

I have added the line <context:load-time-weaver/>
to my application-context.xml,
and have created a META-INF\aop.xml file with the following:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-verbose">
<!-- only weave classes in our application-specific packages -->
<include within="com.xxx.aspectj.*"/>
</weaver>
<aspects>
<aspect name="com.xxx.aspectj.StandardAspect"/>
</aspects>
</aspectj>
With the aspect including a catch-all to simply see if it is even working:
#After("call (public * *(..))")
public void interceptEverything() {
System.out.println("Hello");
}
But nothing seems to happen, any ideas?

Removing the include within tag solved my problem.
I realized that I have misinterpreted the include within tag, I thought it had meant only weave aspects in the package listed, but it meant only weave aspects into classes in the package listed.

Related

IBM JDK throwing error 0 class {0} is already woven and has not been built in reweavable mode [Xlint:nonReweavableTypeEncountered]

We have few aspects, Aspect classes are defined with #Aspect and declared the same aspect in METAINFO/aop.xml:
aop.xml
<aspectj>
<weaver options="-Xset:weaveJavaxPackages=true">
<include within = "Test"/>
</weaver>
<aspects>
<aspect name = "Test"/>
</aspects>
</aspectj>
Below error is thrown only in IBM JDK environment with WebSphere.
Exception:
Error at Test.java::0 class {0} is already woven and has not been
built in reweavable mode [Xlint:nonReweavableTypeEncountered]
The same code works with Tomcat + Oracle JDK stack combination.
As per AspectJ Configuration.
Aspect does not require to add it to the Weaver tag, which was causing error to thrown in SystemOut.log of WAS.
<aspectj>
<weaver options="-Xset:weaveJavaxPackages=true">
// add only actual classes to be woven.
</weaver>
<aspects>
<aspect name = "Test"/>
</aspects>
</aspectj>
An aop.xml file contains two key sections: "aspects" defines one or more aspects to the weaver and controls which aspects are to be used in the weaving process; "weaver" defines weaver options and which types should be woven.
https://www.eclipse.org/aspectj/doc/next/devguide/ltw-configuration.html

Spring load time weaving

After 12 hours of trying I don't seem to be able to get Spring load time weaving working on Tomcat.
Spring 4.2.1
Hibernate 4.3.11
Tomcat 8.09
I am trying to get an #Entity autowired.
The weaver output always says:
not weaving 'mypackage.MyEntity'
unless I also use a #Configuration annotation on it. It will then weave but I get back A SPRIGNCGLIB proxy where all the properties are null.
If I remove the #Configuration annotation (I don't think it should be there anyway) then I don't get any weaving and #Autowired property is always null.
This is my configuration:
applicationContext-beans.xml
<context:component-scan base-package="my.package" />
<context:spring-configured />
<context:load-time-weaver />
classes/META-INF/aop.xml
<aspectj>
<weaver options="-Xreweavable">
<include within="my.package.*"/>
</weaver>
<aspects>
<aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect"/>
</aspects>
MyEntity.java
package my.package;
#Entity
#Table(name = "user")
#Configurable
public class User {
private Encrypter encrypter; // THE CLASS I WANT INJECTED
#Autowired
public void setEncrypter(Encrypter encrypter) {
this.encrypter = encrypter;
}
}
context.xml
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
The Tomcat lib folder has (I am not sure it needs both of these):
spring-instrument-4.2.1.RELEASE.jar
spring-tomcat-weaver-2.5.6.SEC03.jar
The apps WEB-INF/lib folder has:
aspectjweaver-1.8.6.jar
spring-aop-4.2.1.RELEASE.jar
spring-aspects-4.2.1.RELEASE.jar
I have tried starting Tomcat with
-javaagent:D:/my/path/to/server/apache-tomcat-8.0.9/lib/spring-instrument-4.2.1.RELEASE.jar
but it didn't help and according to the Spring LTW documentation the context.xml fragment is the preferred way to do this.
Does anyone have any ideas?

Spring Aspects: specify which packages to weave

I have a Spring / Hibernate application. Custom type created by Hibernate needs Spring context, so I use Spring Aspects to provide it.
#Configurable(preConstruction = true)
public class EncryptedStringUserType implements EnhancedUserType {
...
#EnableSpringConfigured
#EnableLoadTimeWeaving
public class RootConfiguration {
...
After adding Spring Security, I got number of messages in stderr like this:
[AppClassLoader#14dad5dc] error can't determine implemented interfaces of missing type org.springframework.security.ldap.authentication.LdapAuthenticationProvider
when weaving type org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer
when weaving classes
when weaving
[Xlint:cantFindType]
Is it possible to specify packages of classes that should be weaved and avoid trying to weaving other ones?
SOLUTION
Put META-INF/aop.xml to resources root and exclude unnecessary packages:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<exclude within="org.springframework.security.config.annotation.authentication.configurers.ldap.*"/>
<exclude within="org.springframework.security.config.annotation.web.configurers.openid.*"/>
</weaver>
</aspectj>
You can limit the scope of weaving by adding a <include within="your.package.here.*"/> tag to the META-INF/aop.xml file in your classpath. Here's a full example of META-INF/aop.xml taken from the Spring documentation:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="foo.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="foo.ProfilingAspect"/>
</aspects>
</aspectj>

AspectJ not seeing META-INF/aop.xml

I am trying to get Load Time Weaving working with my Tomcat 7 webapp, in order to weave a class from an external jar file (located in WEB-INF/lib).
I have done the following:
Started Tomcat with the following parameters: -javaagent:/path/aspectjweaver-1.7.0.jar -classpath /path/aspectjrt-1.7.0.jar:etc
Placed aop.xml into WAR_ROOT/META-INF/, WEB-INF/lib/META_INF, WEB-INF/lib and WEB-INF/
aop.xml:
<aspectj>
<aspects>
<aspect name="ca.gc.agr.agrishare.web.jsf.chartlet.AgriShareGanttRendererAspect"/>
</aspects>
<weaver options="-verbose -debug -XnoInline">
<include within="org.jfree..*"/>
<dump within="org.jfree..*" />
</weaver>
</aspectj>
No matter where I place the file, my target class is not woven, and I keep seeing errors like this:
[WebappClassLoader#495b317b] error can't determine implemented interfaces of missing type javax.validation.ValidatorFactory
when weaving type org.hibernate.cfg.beanvalidation.TypeSafeActivator
when weaving classes
when weaving
[Xlint:cantFindType]
The fact that it is trying to weave a class outside of the package I specified, and considering that server startup time quadrupled, I think that it is trying to weave all classes.
What am I missing?
Figured it out.
WAR_ROOT/META-INF/ is the webapp metadata, looked up by servletContext.getResource("/META-INF/bla").
WAR_ROOT/WEB-INF/classes/META-INF is java classes metadata, looked up by getContextClassLoader().getResource("/META-INF/bla").
I created META-INF/aop.xml in my Config project (which is on the classpath), and everything is working properly now.

Ignoring Aspectj during junit tests

Here is situation:
We have class with defined aspect to it's methodA;
We have JUnit test for this methodA;
When I run JUnit test it activates Aspect as well. Any thoughts how to ignore Aspects during unit tests?
I have separated tests for my Aspects and it works fine. So in my unit test I want to test only methodA without any attached aspects.
I use spring 3.0 and its aspectj support.
Thanks in advance.
Regards,
Max
You can disable the compile-time weaving that I assume your IDE is doing and use load-time weaving in your separated AspectJ tests.
To enable load-time weaving you have to provide a javaagent as an JVM parameter.
An example:
-javaagent:lib/spring-dependencies/spring-agent.jar
Other changes when you move from compile-time to load-time weaving
You must also provide an aop.xml file in the META-INF folder on the claspath.
For my trace example, it looks like this:
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in this package -->
<include within="aspects.trace.demo.*" />
</weaver>
<aspects>
<!-- use only this aspect for weaving -->
<aspect name="aspects.trace.TraceAspect" />
</aspects>
</aspectj>
In this configuration you can see that the TraceAspect class will be weaved with all the classes in the demo package.
Spring configuration with load-time weaving
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="traceAspect" class="aspects.trace.TraceAspect"
factory-method="aspectOf"/>
<context:load-time-weaver />
</beans>
The configuration file is almost the same as the compile-time configuration file, except it also contains a load-time weaver element.
I hope this helps!

Resources