Spring Aspects: specify which packages to weave - spring

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>

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

#AspectJ aspects not being weaved in application that uses 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.

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?

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