Siegfried Goeschl bio photo

Siegfried Goeschl

Email Github

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