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 “javasimon-core-4.0.1.jar” & “javasimon-javaee-4.0.1.jar” into a JBoss class ladder

  • “javasimon-core” needs to be shared across the deployed applications since it contains all the counters
  • “javasimon-javaee” is required for the EJB interceptor
jboss-eap-6.3> tree modules/javasimon/

modules/javasimon/
`-- core
    `-- main
        |-- javasimon-core-4.0.1.jar
        |-- javasimon-javaee-4.0.1.jar
        `-- module.xml

2. The JBoss Module XML File

Here we need to tell JBoss the we need the the “javax.api” classed otherwise we have various ‘‘ClassDefNotFoundExceptions’’

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="javasimon.core">
    <resources>
        <resource-root path="javasimon-core-4.0.1.jar"/>
        <resource-root path="javasimon-javaee-4.0.1.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="javasimon.core" slot="main"/>
    </global-modules>            
</subsystem>

4. Deploy the JavaSimon WebApp

Copy the WAR file into the JBoss deployment folder

boss-eap-6.3> tree standalone/deployments/

standalone/deployments/
|-- README.txt
|-- javasimon-console-webapp-4.0.1.war
`-- javasimon-console-webapp-4.0.1.war.deployed

5. Start JBoss

After starting JBoss it shall pick up the newly deployed web

[org.jboss.as.server.deployment.scanner] (MSC service thread 1-8) JBAS015012: Started FileSystemDeploymentService for directory /Applications/Java/jboss-eap-6.3/standalone/deployments
[org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015876: Starting deployment of "javasimon-console-webapp-4.0.1.war" (runtime-name: "javasimon-console-webapp-4.0.1.war")
[org.jboss.web] (ServerService Thread Pool -- 50) JBAS018210: Register web context: /javasimon-console
[org.jboss.as.server] (ServerService Thread Pool -- 26) JBAS018559: Deployed "javasimon-console-webapp-4.0.1.war" (runtime-name : "javasimon-console-webapp-4.0.1.war")

6. Access The JavaSimon Web Console

Use the following link [http://localhost:8080/javasimon-console/index.html http://localhost:8080/javasimon-console/index.html]

7. JavaSimon Libraries for EJBs

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)

<dependencies>
    <dependency>
        <groupId>org.javasimon</groupId>
        <artifactId>javasimon-core</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>         
    <dependency>
        <groupId>org.javasimon</groupId>
        <artifactId>javasimon-javaee</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

8. Writing an Interceptor

JavaSimon comes with a ready to use org.javasimon.javaee.SimonInterceptor 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 org.javasimon.javaee.SimonInterceptor;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

/**
 * EJB3 AroundInvoke to wire SimonInterceptor. For some reason
 * the original SimonInterceptor does not work.  
 */
public class PerformanceMonitoringInterceptor extends SimonInterceptor {

    @AroundInvoke
    public Object intercept(InvocationContext context) throws Exception {
        return monitor(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/javasimon-console/index.html http://localhost:8080/javasimon-console/index.html]