Andre Broers’ personal blog

December 20, 2007

Counter MBean to measure EJB calls

Filed under: ejb, glassfish, j2ee, java, jmx, mbean — broersa @ 7:14 pm

In this example I create a Counter MBean which I will install in the Glassfish server. This bean has three methods getCounter, incrementCounter and resetCounter. After this I create an EJB which will increment the counter each time sayHello is called. We can then monitor the counter with the jconsole app. After reading a lot of different implementations I think this is in my opinion the best way to implement this. The problem I have with this implementation is that I can call the increment function from jconsole with which I can influence the counter.

Let’s start with the MBean:

/home/broersa/work/HelloApp/MyCounterMBean/src/com/bekijkhet/MyCounterMBean.java


package com.bekijkhet;

public interface MyCounterMBean {
  public int getCounter();
  public void incrementCounter();
  public void resetCounter();
}

/home/broersa/work/HelloApp/MyCounterMBean/src/com/bekijkhet/MyCounter.java


package com.bekijkhet;

public class MyCounter implements MyCounterMBean {
  public int counter = 0;

  public int getCounter() {
    return counter;
  }

  public void incrementCounter() {
    counter++;
  }

  public void resetCounter() {
    counter = 0;
  }
}

/home/broersa/work/HelloApp/MyCounterMBean/build.xml


<project name="MyCounterMBean" default="compile" basedir=".">
    <description>
        simple example build file
    </description>
  <!-- set global properties for this build -->
  <property name="src" location="src"/>
  <property name="build" location="build"/>

  <target name="init">
    <!-- Create the time stamp -->
    <tstamp/>
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build}"/>
  </target>

  <target name="compile" depends="init"
        description="compile the source " >
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src}" destdir="${build}"/>
  </target>

  <target name="clean"
        description="clean up" >
    <!-- Delete the ${build} and ${dist} directory trees -->
    <delete dir="${build}"/>
  </target>
</project>

type:asant compileto compile the MBean.cd build

cp -r com /home/broersa/glassfish/domains/domain1/applications/mbeans

asadmin create-mbean com.bekijkhet.MyCounter

to deploy the managed bean.

Now it is time to create the statefull EJB which increments the counter in the MBean.

/home/broersa/work/HelloApp/MyCounterEJB/src/com/bekijkhet/MyCounterEJB.java


package com.bekijkhet;
public interface MyCounterEJB {
  public String sayHello();
}

/home/broersa/work/HelloApp/MyCounterEJB/src/com/bekijkhet/MyCounterEJB.java


package com.bekijkhet;
import javax.ejb.Stateless;
import javax.ejb.EJB;
import javax.ejb.Remote;
import java.util.Properties;
import java.net.URL;
import javax.naming.*;
import javax.management.*;
import java.lang.management.*;

@Stateless
@Remote(MyCounterEJB.class)
public class MyCounterEJBBean implements MyCounterEJB {

  private MyCounterMBean mbean = null;

  public MyCounterEJBBean() {

    try {
      // Get the platform MBeanServer
      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
      ObjectName name = new ObjectName("user:impl-class-name=com.bekijkhet.MyCounter,name=com.bekijkhet.MyCounter,server=server");

      mbean = (MyCounterMBean) MBeanServerInvocationHandler.newProxyInstance(mbs, name, MyCounterMBean.class, false);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  public String sayHello() {
    mbean.incrementCounter();
    return "Hello From Glassfish!!!! ";
  }
}

/home/broersa/work/HelloApp/MyCounterEJB/build.xml


<project name="MyCounterEJB" default="dist" basedir=".">
    <description>
        simple example build file
    </description>
  <!-- set global properties for this build -->
  <property name="src" location="src"/>
  <property name="build" location="build"/>
  <property name="dist"  location="dist"/>

  <target name="init">
    <!-- Create the time stamp -->
    <tstamp/>
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build}"/>
  </target>

  <target name="compile" depends="init"
        description="compile the source " >
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="/home/broersa/work/HelloApp/MyCounterMBean/src" destdir="${build}"/>
    <javac srcdir="${src}" destdir="${build}"/>
  </target>

  <target name="dist" depends="compile"
        description="generate the distribution" >
    <!-- Create the distribution directory -->
    <mkdir dir="${dist}"/>

    <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
    <jar jarfile="${dist}/MyCounterEJB.jar" basedir="${build}"/>
  </target>

  <target name="clean"
        description="clean up" >
    <!-- Delete the ${build} and ${dist} directory trees -->
    <delete dir="${build}"/>
    <delete dir="${dist}"/>
  </target>
</project>

In this build.xml I included a second javac rule that includes the MBean classes in this ejb.Now we build and deploy the ejb:

asant dist

asadmin deploy dist/MyCounterEJB.jar

Now it is time to create the client that calls the ejb sayhello method that increments our counter in the mbean.


package com.bekijkhet.helloclient;
import javax.naming.*;
import com.bekijkhet.MyCounterEJB;
public class HelloClient {
  public static void main(String[] args) {
    try {
      InitialContext ctx = new InitialContext();
      MyCounterEJB m = (MyCounterEJB)ctx.lookup("com.bekijkhet.MyCounterEJB");
     System.out.println(m.sayHello());
    }
    catch (Exception e) {
      System.out.println(e);
      e.printStackTrace();
    }
  }
}

compile the code:javac -cp $GLASSFISH_HOME/lib/appserv-rt.jar:$GLASSFISH_HOME/lib/javaee.jar:$HOME/work/HelloApp/MyCounterEJB/dist/MyCounterEJB.jar:. -d . HelloClient.java

open a jconsole to monitor our Mbean. connect to localhost:8686 (which is the default portnumber) and connect with admin pwd: adminadmin

jconsole

See the counter which has the value 0.

Now we run our client:

java -cp $GLASSFISH_HOME/lib/appserv-rt.jar:$GLASSFISH_HOME/lib/javaee.jar:$HOME/work/HelloApp/MyCounterEJB/dist/MyCounterEJB.jar:. com.bekijkhet.helloclient.HelloClient

And the counter is incremented by one:

jconsole1

December 6, 2007

JMX Managed Bean with multiple agents

Filed under: java, jmx, mbean — broersa @ 12:31 pm

In this example I created a counter that gets updated from multiple instances. All examples I found on internet are using a single agent instance. The crux is to create a static MBean object that is available to all instances of the agent class. Let’s get to the code:

/home/broersa/work/mbean/mypack/MyCounterMBean.java


package mypack;
public interface MyCounterMBean {
   public int getCounter();
   public void sayCounter();
}

/home/broersa/work/mbean/mypack/MyCounter.java


package mypack;

public class MyCounter implements MyCounterMBean {
   private int counter = 0;

   public MyCounter() {
      counter = 0;
   }

   public int getCounter() {
      return counter;
   }

   public void incCounter() {
     counter++;
   }

   public void sayCounter() {
      System.out.println(counter);
   }
}

/home/broersa/work/mbean/mypack/SimpleAgent.java


package mypack;

import javax.management.*;
import java.lang.management.*;

public class SimpleAgent {
   private static MyCounter counterBean = new MyCounter();
   private MBeanServer mbs = null;

   public SimpleAgent() {

      // Get the platform MBeanServer
       mbs = ManagementFactory.getPlatformMBeanServer();

      // Unique identification of MBeans
      // replaced by static var.     Hello helloBean = new Hello();
      ObjectName myCounterName = null;

      try {
         // Uniquely identify the MBeans and register them with the platform MBeanServer
         myCounterName = new ObjectName("SimpleAgent:name=MyCounter");
         mbs.registerMBean(counterBean, myCounterName);
      } catch (InstanceAlreadyExistsException e) {
         System.out.println("Instance Already Exists");
      } catch(Exception e) {
         e.printStackTrace();
      }
      counterBean.incCounter();
   }

   // Utility method: so that the application continues to run
   private static void waitForEnterPressed() {
      try {
         System.out.println("Press  to continue...");
         System.in.read();
      } catch (Exception e) {
         e.printStackTrace();
      }
    }

   public static void main(String argv[]) {
      SimpleAgent agent1 = new SimpleAgent();
      SimpleAgent agent2 = new SimpleAgent();
      System.out.println("SimpleAgent is running...");
      SimpleAgent.waitForEnterPressed();
   }
}

goto the directory mbean and compile the code:

javac -d . mypack/MyCounter.java

javac -d . mypack/SimpleAgent.java

run the code:

java -Dcom.sun.management.jmxremote mypack.SimpleAgent

Instance Already Exists
SimpleAgent is running…
Press  to continue…

When we connect to the MBeanServer using the jconsole utility we see the counter has the value 2:

JConsole sample

Blog at WordPress.com.