In JBOSS 7 and WildFly application server it is no longer possible to simply drop a JAR into a shared library folder - you have to need a module for that.
1. Adding A JBoss Module
First we need to add a module to inject “jamon-2.79.jar”
- “jamon-2.79.jar” needs to be shared across all deployed applications since it contains all the counters
wildfly-8.2.0> tree modules/jamon/
modules/jamon/
`-- core
`-- main
|-- jamon-2.79.jar
|-- jamon-2.79-properties.jar
`-- module.xml
JAMon can be configured using a jamonapi.properties found on the class path so I created a jamon-2.79-properties.jar only containing the properties file. More information about jamonapi.properties can be found at JAMon.
2. The JBoss Module XML File
Here we need to tell JBoss that we need the the “javaee.api” classes otherwise we have various ‘‘ClassDefNotFoundExceptions’’
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="jamon.core">
<resources>
<resource-root path="jamon-2.79.jar"/>
<resource-root path="jamon-2.79-properties.jar"/>
</resources>
<dependencies>
<module name="javaee.api"/>
</dependencies>
</module>
3. Share the JBoss Module Globally
Now we tell JBoss that the module is shared across all deployed applications - this is done in the various “$JBOSS_HOME/standalone/configuration” files, e.g. standalone.xml
<subsystem xmlns="urn:jboss:domain:ee:1.2">
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
<global-modules>
<module name="jamon.core" slot="main"/>
</global-modules>
</subsystem>
4. Deploy the JAMon WebApp
Copy the WAR file into the JBoss deployment folder
wildfly-8.2.0> tree standalone/deployments/
standalone/deployments/
|-- README.txt
|-- jamon.war
5. Start JBoss
After starting JBoss it shall pick up the newly deployed web
[org.jboss.as.server.deployment] (MSC service thread 1-10) JBAS015876: Starting deployment of "jamon.war" (runtime-name: "jamon.war")
[org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017534: Registered web context: /jamon
[org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "jamon.war" (runtime-name : "jamon.war")
6. Access The JAMon Admin Page
Use the following link http://localhost:8080/jamon/jamonadmin.jsp
7. JAMon Libraries for EJB Server Side
We need to define additional libraries as ‘‘provided’’ since the libraries are actually supplied using the JBoss module (if we bundle our own JAR we would get no metrics)
<dependency>
<groupId>com.jamonapi</groupId>
<artifactId>jamon</artifactId>
<version>2.79</version>
<scope>provided</scope>
</dependency>
8. Writing an Interceptor
JAMon comes with a ready to use com.jamonapi.aop.JAMonEJBInterceptor which does not work - no idea why.
As work-around I implemented a custom AroundAdvice called PerformanceMonitoringInterceptor
package org.jboss.as.quickstarts.ejb.remote.infra;
import com.jamonapi.aop.JAMonEJBInterceptor;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class PerformanceMonitoringInterceptor extends JAMonEJBInterceptor {
@AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
return super.intercept(context);
}
}
9. Using the PerformanceMonitoringInterceptor
9.1 Using EJB Annotations
package org.jboss.as.quickstarts.ejb.remote.stateless;
import org.jboss.as.quickstarts.ejb.remote.infra.PerformanceMonitoringInterceptor;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
@Stateless
@Remote(RemoteCalculator.class)
@Interceptors({PerformanceMonitoringInterceptor.class})
public class CalculatorBean implements RemoteCalculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
9.2 Using Global Interceptors
Adding a META-INF/ejb-jar.xml allows to globally instrument the EJBs without using annotations
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
version = "3.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
<interceptors>
<interceptor>
<interceptor-class>org.jboss.as.quickstarts.ejb.remote.infra.PerformanceMonitoringInterceptor</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>org.jboss.as.quickstarts.ejb.remote.infra.PerformanceMonitoringInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
10. Run the EJB Client
When you deploy the server code and run the EJB Client you will be able to see the invocations using http://localhost:8080/jamon/jamonadmin.jsp