JBoss standalone AOP
This document give a try to JBoss standalone AOP solution, which has been released as a DR 1 (developper release) in may 2003.
Case studyThe experiment is done thru a very simple J2SE application. The application makes use of major concepts which are at the heart of any J2EE architecture: ClassLoader, URLClassLoader and hierarchy. ClassLoader hierarchy
Java class loading mechanism follow a hierarchy of class loader. Class are loaded thru the class path of each
ClassLoader (java.lang.ClassLoader and subclasses). Class are loaded (when available)
by the highest ClassLoader in the hierarchy.
Boot CL | Extension CL | System CL (main) and Custom CL can be plugged at any level and between each other
Boot CL | Extension CL | System CL (main - app server classes) / | | | | URLClassLoader_my_war (deployed standalone war) | URLClassLoader_my_ear (deployed ear, jar put in the ear except ejb-jars) | URLClassLoader_my_ejb-jar (ejb-jar in my_ear. Use Manifest entries to point the ear wide jars in the parent CL) | URLCLassLoader_my_war (war in my_ear, servlet classes of WEB-INF/classes and jar of WEB-INF/lib) Sample applicationIn order to easily test this fundamental behavior of any J2EE app server, the following sample application has been developped : Boot CL / | / Extension CL / | | System CL (classpath contains JBoss AOP jars, POJO.class and META-INF/jboss-aop.xml for POJO) | | | | | URLClassLoader_1 (search path contains POJO2.class and NO META-INF/jboss-aop.xml) | | | URLClassLoader_2 (search path conteains POJO2.class and META-INF/jboss-aop.xml for POJO2) | URLClassLoader_2 (search path contains JBoss AOP jars, POJO.class, POJO2.class and META-INF/jboss-aop.xml for POJO*) deployed in System CL <?xml version="1.0" encoding="UTF-8"?> <aop> <interceptor-pointcut class="POJO"> <interceptors> <interceptor class="TracingInterceptor"/> </interceptors> </interceptor-pointcut> </aop> deployed in URLClassLoader_2 <?xml version="1.0" encoding="UTF-8"?> <aop> <interceptor-pointcut class="POJO2"> <interceptors> <interceptor class="TracingInterceptor"/> </interceptors> </interceptor-pointcut> </aop> deployed in URLClassLoader_3 <?xml version="1.0" encoding="UTF-8"?> <aop> <interceptor-pointcut class="POJO*"> <interceptors> <interceptor class="TracingInterceptor"/> </interceptors> </interceptor-pointcut> </aop> Expected behaviorBased on what we can read in the doc, ant our knowledge on ClassLoader hierarchy we expect the following:
Note the URLClassLoader_3 is more for demonstration purpose. Off course, the sample application should run correctly without AOP before going further. Results
Below is the stdout and stderr of the simple application running twice: without AOP and with AOP.
You can run this by your own - read here ************************************** BUILDING (JAVA_HOME is C:\java\j2sdk1.4.0_02) ************************************** ************************************** TEST WITHOUT AOP ************************************** ** test POJO loaded by SystemCL class.hashcode = 5383406 POJO say Hello World! ** test POJO loaded by SystemCL thru URLClassLoader_1 with no AOP xml child of SystemCL class.hashcode = 5383406 POJO say Hello World! ** test POJO2 loaded by URLClassLoader_1 with no AOP xml child of SystemCL class.hashcode = 12338265 POJO2 say hello ! ** test POJO loaded by SystemCL thru URLClassLoader_2 with AOP xml child of SystemCL class.hashcode = 5383406 POJO say Hello World! ** test POJO2 loaded by URLClassLoader_2 with AOP xml child of SystemCL class.hashcode = 8947545 POJO2 say hello ! ** test POJO loaded by URLClassLoader_3 with AOP xml child of BootstrapCL class.hashcode = 16130931 POJO say Hello World! ** test POJO2 loaded by URLClassLoader_3 with AOP xml child of BootstrapCL class.hashcode = 15939189 POJO2 say hello ! ************************************** TEST WITH AOP (requires JAVA 1.4) ************************************** xml deploy AOP = /C:/cvs_02/jboss-aop/docs/oreilly-aop/example1/aop_system/META-INF/jboss-aop.xml ** test POJO loaded by SystemCL class.hashcode = 15700311 Entering method: helloWorld POJO say Hello World! Leaving method: helloWorld ** test POJO loaded by SystemCL thru URLClassLoader_1 with no AOP xml child of SystemCL class.hashcode = 15700311 Entering method: helloWorld POJO say Hello World! Leaving method: helloWorld ** test POJO2 loaded by URLClassLoader_1 with no AOP xml child of SystemCL javassist.NotFoundException: POJO2 at javassist.ClassPoolTail.openClassfile(ClassPoolTail.java:294) at javassist.ClassPoolTail.checkClassName(ClassPoolTail.java:177) at javassist.ClassPool.checkClassName(ClassPool.java:679) at javassist.ClassPool.checkClassName(ClassPool.java:679) at javassist.ClassPool.get0(ClassPool.java:542) at org.jboss.aop.AOPClassPool.getLocally(AOPClassPool.java:73) at org.jboss.aop.AspectManager.translate(AspectManager.java:348) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.jboss.aop.standalone.SystemClassLoader.loadClass(SystemClassLoader.java:173) at java.lang.ClassLoader.loadClass(ClassLoader.java:299) at java.lang.ClassLoader.loadClass(ClassLoader.java:262) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:322) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:207) at StandaloneTest.testInheritWithoutAOP(StandaloneTest.java:63) at StandaloneTest.main(StandaloneTest.java:104) class.hashcode = 6616781 POJO2 say hello ! ** test POJO loaded by SystemCL thru URLClassLoader_2 with AOP xml child of SystemCL class.hashcode = 15700311 Entering method: helloWorld POJO say Hello World! Leaving method: helloWorld ** test POJO2 loaded by URLClassLoader_2 with AOP xml child of SystemCL javassist.NotFoundException: POJO2 at javassist.ClassPoolTail.openClassfile(ClassPoolTail.java:294) at javassist.ClassPoolTail.checkClassName(ClassPoolTail.java:177) at javassist.ClassPool.checkClassName(ClassPool.java:679) at javassist.ClassPool.checkClassName(ClassPool.java:679) at javassist.ClassPool.get0(ClassPool.java:542) at org.jboss.aop.AOPClassPool.getLocally(AOPClassPool.java:73) at org.jboss.aop.AspectManager.translate(AspectManager.java:348) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.jboss.aop.standalone.SystemClassLoader.loadClass(SystemClassLoader.java:173) at java.lang.ClassLoader.loadClass(ClassLoader.java:299) at java.lang.ClassLoader.loadClass(ClassLoader.java:262) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:322) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:207) at StandaloneTest.testInheritWithAOP(StandaloneTest.java:73) at StandaloneTest.main(StandaloneTest.java:110) class.hashcode = 8215850 POJO2 say hello ! ** test POJO loaded by URLClassLoader_3 with AOP xml child of BootstrapCL class.hashcode = 9558209 POJO say Hello World! ** test POJO2 loaded by URLClassLoader_3 with AOP xml child of BootstrapCL class.hashcode = 6183504 POJO2 say hello ! Conclusion
Everithing is OK for the SystemCL: POJO is instrumented.
URLClassLoader not supported
JBoss standalone AOP does not bring AOP in java.lang.URLClassLoader.
JBoss standalone AOP even print stack traces saying the class is not found by its instrumentation layer, even if the class is found by the application itself. ClassLoader hierarchy not supportedAs soon as you try to use JBoss AOP in a java.lang.ClassLoader hierarchy which goes beyond than the hello world, it won't work. No way. Final word
If you really need a global cross application and cross application server AOP solution,
forget about JBoss AOP
. The JBoss standalone AOP is just good to build light demo to help
user get in the JBoss stuff.
|