Running and packaging in JBoss
*To run these examples you must edit build.xml and set the jboss.dir to where JBoss is. The server configuration used in this example is 'all', so you must start JBoss with 'run -c all'. *
You can change the server configuration used by modifying the jboss.server.config property in build.xml. If you use the 'default' server configuration, you will get error messages on startup. They are not "harmful", more info about these can be found here
There are several ways to package classes to be run with AOP in JBoss, and this page takes you through a few of the options available to you.
All the examples shown here use loadtime transformations, so you will need to modify your jboss/server/yourconfig/conf/jboss-service.xml as outlined in RunningWithJBossApplicationServer
A simple application is that comes in a web-application and a full J2EE app flavour is used to illustrate how it can be pacaged in different ways to acheive the same thing.
The source class/package structure is
org | - jboss | - injbossaop | - ejb (Only used in EAR version) | | | - ExampleSession | - ExampleSessionBean | - ExampleSessionHome | -lib | | | - ExampleValue | - SimpleInterceptor | -web | - BasicExampleServlet (Used for WAR version) - EarExampleServlet (USed for EAR version)
Both examples use the same jboss-aop.xml file
<?xml version="1.0" encoding="UTF-8"?> <aop> <bind pointcut="all(org.jboss.injbossaop.lib.ExampleValue)"> <interceptor class="org.jboss.injbossaop.lib.SimpleInterceptor"></interceptor> </bind> <typedef name="MyServlets" expr="class($instanceof{javax.servlet.http.HttpServlet}) AND class(org.jboss.injbossaop.web.*)"></typedef> <bind pointcut="all($typedef{MyServlets})"> <interceptor class="org.jboss.injbossaop.lib.SimpleInterceptor"></interceptor> </bind> <bind pointcut="all($typedef{MyServlets})"> <interceptor class="org.jboss.injbossaop.lib.SimpleInterceptor"></interceptor> </bind> <typedef name="MySessionBeans" expr="class($instanceof{javax.ejb.SessionBean}) AND class(org.jboss.injbossaop.ejb.*)" ></typedef> <bind pointcut="all($typedef{MySessionBeans})"> <interceptor class="org.jboss.injbossaop.lib.SimpleInterceptor"></interceptor> </bind> </aop>
War functionality
http://localhost:8080/aopexample/index.jsp
gets ExampleValue from session, calls getMessage() on it, and displays the value.
You can fill in a value in the textbox and press submit. The call goes to
BasicExampleServlet.service() creates a new ExampleValue with the passed in string and sets that in the session forwards to index.jsp for display
index.jsp then gets ExampleValue from session, calls getMessage() on it, and displays the value.
The output in the JBoss logs for all the WAR examples will be something like:
-For initial display of index.jsp page
21:34:14,929 INFO [STDOUT] **** ExampleValue empty Constructor 21:34:14,939 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue_getMessage_53534 07034680111516_OptimizedMethodInvocation type: Method Invocation method: getMessage Class containing method: org.jboss.injbossaop.lib.ExampleValue 21:34:14,939 INFO [STDOUT] **** ExampleValue.getMessage() 21:34:14,939 INFO [STDOUT] >>> Leaving SimpleInterceptor
-Having filled in a value and pressed submit, you should get
21:34:33,525 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.web.BasicExampleServlet_service_8 586428322187484014_OptimizedMethodInvocation type: Method Invocation method: service Class containing method: org.jboss.injbossaop.web.BasicExampleServlet 21:34:33,525 INFO [STDOUT] **** BasicExampleServlet.service() 21:34:33,535 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue1OptimizedConstru ctorInvocation type: Constructor Invocation constructor: public org.jboss.injbossaop.lib.ExampleValue(java.lang.Stri ng) 21:34:33,535 INFO [STDOUT] **** ExampleValue String Constructor 21:34:33,535 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:34:33,625 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue_getMessage_53534 07034680111516_OptimizedMethodInvocation type: Method Invocation method: getMessage Class containing method: org.jboss.injbossaop.lib.ExampleValue 21:34:33,625 INFO [STDOUT] **** ExampleValue.getMessage() 21:34:33,625 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:34:33,625 INFO [STDOUT] >>> Leaving SimpleInterceptor
Ear functionality
http://localhost:8080/aopexample/index.jsp
gets ExampleValue from session, calls getMessage() on it, and displays the value.
You can fill in a value in the textbox and press submit. This works similar to the war example apart from that the servlet used is EarExampleServlet which calls through to the ExampleSession SLSB, which creates the message. The call goes to
EarExampleServlet.service() Looks up ExampleSessionHome, calls create() and calls ExampleSession.getValue() with the passed in String ExampleSession.getValue() creates a new ExampleValue with the passed in string and returns that EarExampleServlet.service() sets the ExampleValue in the session and forwards to index.jsp for display
index.jsp then gets ExampleValue from session, calls getMessage() on it, and displays the value.
The output in the JBoss logs for all the EAR examples will be something like:
-For initial display of index.jsp page
21:26:26,305 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.web.EarExampleServlet_service_858 6428322187484014_OptimizedMethodInvocation type: Method Invocation method: service Class containing method: org.jboss.injbossaop.web.EarExampleServlet 21:26:00,447 INFO [STDOUT] **** ExampleValue.getMessage() 21:26:00,447 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:08:19,332 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue$ExampleValue_mes sage_632994_OptimizedSetFieldInvocation type: Field Write Invocation field: java.lang.String org.jboss.injbossaop.lib.ExampleValue.message 21:08:19,332 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:08:19,332 INFO [STDOUT] **** ExampleValue empty Constructor 21:08:19,332 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue_getMessage_53534 07034680111516_OptimizedMethodInvocation type: Method Invocation method: getMessage Class containing method: org.jboss.injbossaop.lib.ExampleValue 21:08:19,332 INFO [STDOUT] **** ExampleValue.getMessage() 21:08:19,332 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue$ExampleValue_mes sage_32604882_OptimizedGetFieldInvocation type: Field Write Invocation field: java.lang.String org.jboss.injbossaop.lib.ExampleValue.message 21:08:19,332 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:08:19,332 INFO [STDOUT] >>> Leaving SimpleInterceptor
-Having filled in a value and pressed submit, you should get (a bit longer this time)
21:26:36,730 INFO [STDOUT] **** EarExampleServlet.service() 21:26:36,950 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.ejb.ExampleSessionBean_getValue_8 555731906870343793_OptimizedMethodInvocation type: Method Invocation method: getValue Class containing method: org.jboss.injbossaop.ejb.ExampleSessionBean 21:26:36,950 INFO [STDOUT] *** ExampleSessionBean.getValue() 21:26:36,960 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue1OptimizedConstru ctorInvocation type: Constructor Invocation constructor: public org.jboss.injbossaop.lib.ExampleValue(java.lang.Stri ng) 21:26:36,960 INFO [STDOUT] **** ExampleValue String Constructor 21:26:36,960 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:26:36,960 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:26:36,960 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue1OptimizedConstru ctorInvocation type: Constructor Invocation constructor: public org.jboss.injbossaop.lib.ExampleValue(java.lang.Stri ng) 21:26:36,960 INFO [STDOUT] **** ExampleValue String Constructor 21:26:36,960 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:26:37,050 INFO [STDOUT] <<< Entering SimpleInterceptor: invocation class: org.jboss.injbossaop.lib.ExampleValue_getMessage_53534 07034680111516_OptimizedMethodInvocation type: Method Invocation method: getMessage Class containing method: org.jboss.injbossaop.lib.ExampleValue 21:26:37,050 INFO [STDOUT] **** ExampleValue.getMessage() 21:26:37,050 INFO [STDOUT] >>> Leaving SimpleInterceptor 21:26:37,060 INFO [STDOUT] >>> Leaving SimpleInterceptor
Now for the interesting bit - how is it all packaged?
Before running the examples, open the local.properties file and set jboss.dir to
point to your JBoss distribution.
WAR examples
We'll start off looking at a few ways you can package a war file.
Standard WAR with stand-alone jboss-aop.xml file
If you run
$ant deploy-basic-lt-war
two files get deployed: jboss-aop.xml and aopexample.war
aopexample.war is a bog-standard war file. It contains
index.jsp WEB-INF/web.xml WEB-INF/lib/aopexamplelib.jar
aopexamplelib.jar contains:
org/jboss/injbossaop/lib/ExampleValue.class org/jboss/injbossaop/lib/SimpleInterceptor.class org/jboss/injbossaop/web/BasicExampleServlet.class org/jboss/injbossaop/web/EarExampleServlet.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSession.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionBean.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionHome.class (Never called in this example)
The magic comes from deploying the jboss-aop.xml file BEFORE the war is deployed
WAR and .aop lib file contained in a SAR
If you run
$ ant deploy-basic-lt-war-in-sar
Only one file gets deployed: aopexample.sar.
aopexample.sar contains:
aopexample.war aopexamplelib.aop META-INF/jboss-service.xml
aopexample.war contains
index.jsp WEB-INF/web.xml
aopexamplelib.aop contains more or less the same as aopexamplelib, but contains a META-INF/jboss.aop file:
org/jboss/injbossaop/lib/ExampleValue.class org/jboss/injbossaop/lib/SimpleInterceptor.class org/jboss/injbossaop/web/BasicExampleServlet.class org/jboss/injbossaop/web/EarExampleServlet.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSession.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionBean.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionHome.class (Never called in this example) META-INF/jboss-aop.xml
WAR and .aop lib file contained in a SAR
If you run
$ ant deploy-basic-lt-war-in-jar
Only one file gets deployed: aopexample.jar.
aopexample.jar contains:
aopexample.war aopexamplelib.aop
aopexample.war contains
index.jsp WEB-INF/web.xml
aopexamplelib.aop contains more or less the same as aopexamplelib, but contains a META-INF/jboss.aop file:
org/jboss/injbossaop/lib/ExampleValue.class org/jboss/injbossaop/lib/SimpleInterceptor.class org/jboss/injbossaop/web/BasicExampleServlet.class org/jboss/injbossaop/web/EarExampleServlet.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSession.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionBean.class (Never called in this example) org/jboss/injbossaop/ejb/ExampleSessionHome.class (Never called in this example) META-INF/jboss-aop.xml
EAR examples
Now let's take a look at a few ways to package ear files.
Standard EAR with standalone jboss-aop.xml file
If you run
$ ant deploy-ear
two files get deployed: jboss-aop.xml and aopexample.ear.
aopexample.ear contains:
aopexample.war aopexampleejb.jar aopexamplelib.jar META-INF/application.xml
aopexample.war contains
index.jsp WEB-INF/web.xml
aopexampeejb.jar contains:
org/jboss/injbossaop/ejb/ExampleSession.class org/jboss/injbossaop/ejb/ExampleSessionBean.class org/jboss/injbossaop/ejb/ExampleSessionHome.class META-INF/ejb-jar.xml
and, finally aopexamplelib.jar contains:
org/jboss/injbossaop/lib/ExampleValue.class org/jboss/injbossaop/lib/SimpleInterceptor.class org/jboss/injbossaop/web/BasicExampleServlet.class (Never called in this example) org/jboss/injbossaop/web/EarExampleServlet.class
There's nothing special about the classes in the ear - the magic comes from deploying the jboss-aop.xml file BEFORE the ear is deployed
EAR containing .aop file
If you run
$ ant deploy-ear-aop
One file gets deployed: aopexample.ear.
aopexample.ear contains:
aopexample.war aopexampleejb.jar aopexamplelib.aop META-INF/application.xml
aopexample.war contains:
index.jsp WEB-INF/web.xml
aopexampeejb.jar contains:
org/jboss/injbossaop/ejb/ExampleSession.class org/jboss/injbossaop/ejb/ExampleSessionBean.class org/jboss/injbossaop/ejb/ExampleSessionHome.class META-INF/ejb-jar.xml
and, finally aopexamplelib.aop contains:
org/jboss/injbossaop/lib/ExampleValue.class org/jboss/injbossaop/lib/SimpleInterceptor.class org/jboss/injbossaop/web/BasicExampleServlet.class (Never called in this example) org/jboss/injbossaop/web/EarExampleServlet.class META-INF/jboss-aop.xml
This is pretty similar to what we had in the standard ear example, apart from that the lib file has now has an .aop extension, and contains a META-INF/jboss-aop.xml file. NOTE: ALL the relevant files in the ear get transformed/intercepted. The jboss-aop.xml file resides in aopexamplelib.aop. aopexampleejb.jar contains ExampleSessionBean (i.e. it is outside of aopexamplelib.aop), but the call to ExampleSessionBean.getValue() still gets intercepted.
Comments