The steps for observing the Salary Changes made in an ADF BC application – JClient, JSF or WebService style does not matter – are pretty straightforward. Building on the implementation of the EmpListener in the article Using ADF BC Event Listeners to monitor data changes application wide through RSS Feeds and Monitor Pages, we simply add an MBean that is associated with the EmpListener and that exposes the most recent Salary Change Event information through the MBean Server. JMX Clients – either JConsole, other tools or a client we program ourselves – can connect to the MBean Server and read the details exposed by the MBean.
The steps:
- Define the SalChangeMonitorMBean interface
- Implement the SalChangeMonitor class that implements that interface
- Instantiate SalChangeMonitor upon instantiation of the EmpListener and inject the EmpListener in the MBean.
- Run the ADF BC application with some Java arguments on the commandline: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1111 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
- Make some changes to salary values – either in the ADF BC Tester, the Web Application, the JClient application or though a WebService. Or whatever. The MBean inside the application will report its findings in any case.
Define the SalChangeMonitorMBean interface
package nl.amis.adfbc;
import java.util.List;
public abstract interface SalChangeMonitorMBean {
public List<String> getMostRecentChange();
}
Implement the SalChangeMonitor class
package nl.amis.adfbc;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class SalChangeMonitor implements SalChangeMonitorMBean{
private EmpListener empListener;
public SalChangeMonitor() {
}
public SalChangeMonitor(EmpListener empListener) {
this.empListener=empListener;
}
public List<String> getMostRecentChange() {
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
List<String> changes = new ArrayList(25);
for (SalaryChangeEvent event: empListener.getEvents()) {
changes.add(dateFormat.format(event.getTimestamp())+" "+event.getEmployeeName()+" ("+event.getJob()+") from "+event.getOldSalary()+" to "+event.getNewSalary());
}
return changes;
}
}
Instantiate SalChangeMonitor with injection of the ADF BC EmpListener
Here are the critical components in the EmpListener class:
package nl.amis.adfbc;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
…
public class EmpListener implements RowSetListener {
…
public static EmpListener getEmpListener() {
if (el == null) {
el= new EmpListener();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
SalChangeMonitorMBean salChangeMonitorMBean = new SalChangeMonitor(el);
try
{
mbs.registerMBean(salChangeMonitorMBean , new ObjectName("HrmMonitor:type=salChangeMonitor"));
System.out.println("Registered MBean");
}
catch(Exception e)
{
e.printStackTrace();
}
}
return el;
}
…
}
With these elements in place, run the application based on the ADF BC Application Module – either Web Application, Stand Alone Java Client, WebService or EJB, … – and run using these parameters on the commandline: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1111 .
Read the MBean at run-time
To monitor what is happening inside the application:
Start JConsole – from the command line, just type jconsole.
On the Remote tab, connect to the host running the ADF BC application – for example localhost – and enter the same port number used in the com.sun.management.jmxremote.port argument when starting the ADF BC application.
Go to the MBeans tab. Open the HrmMonitor tree and click in the salChangeMonitor node – this is the name of the MBean. The MBean exposes a single attribute, called MostRecentChange. This attribute is a List<String> of messages describing Salary Change Events.
This is the most straightforward way of reporting on Salary Change events. Note that we can monitor these changes from anywhere, outside of the application and with minimal intrusion in the application. We only had to register the RowSetListener on the EmpView ViewObject and hook it up with an MBean. The application itself is modified in just a single location: the overridden create() method in the EmpViewImpl class, where the listener is registered.
Lucas, is there a way that multiple ejb instances can increment a counter in one mbean without exposing the increment method to the jconsole? What I need is a reference to the mbean object instance in the ejb, not the interface. I don’t know if this question is on topic. But maybe you know a sollution?
Thanx.