Showing posts with label JMX. Show all posts
Showing posts with label JMX. Show all posts

Friday, April 17, 2015

Java Management Extensions - JMX

Java Management Extensions is a way to create management interface to Java applications. In brief, adding extra wrapper (MBean) to your application with a name (ObjectName) and register it on management server MBeanServer, so that it can be accessed/managed externally. JMX allows the developers to integrate the application by assigning management attributes/operations.

Instrumentation

To use JMX, we need to instrument the Java classes (or resources). The instrumented objects are called MBeans. MBeans are nothing but POJOs which adhere to JMX specifications.

MBeanServer

MBeanServer is the very core component of the JMX. MBeanServer is the JMX agent which hosts the MBeans on it and make them available for the remote applications. The MBeanServer need not to know how the MBeans are implemented and vice-versa. 

Accessing MBeans

MBeans running on MBeanServer can be accessed using Connectors, typically called as JMX Connectors, using JMX Service URL. The main intention of the connector is to provide an interface to establish communication between JMX agent and the application which is trying to access the MBean. There are various connectors available, but it always recommended use a standard RMIConnector.  

JMX Service URL

The URL is used to connect to MBean agent and locate MBeans to acess. There are two types of URLs depending on how the JMX is implemented on broker.
  • Static URL: As the name suggests, Static URL will create constant identity for MBeans irrespective of when and how broker is started, stopped etc. This uses RMI Connector.
  • Dynamic URL: Dynamic URL keeps changes for each time when the broker is started/re-started.

URL looks like

service:jmx:rmi://hostname:port/<urlpath>
The explanation goes here
  • service:jmx:rmi is constant
  • hostname:port is the name and port of the broker host where the MBean agent resides (Ideally, where the application is running)
  • urlpath is depends on where Service URL is static or dynamic
    • Static URL looks like : /jndi/rmi://hostname[:rmiPort]/jndiname
    • Dynamic URL looks like : /stub/serialnumber-with-base64encoded

Static JMX Service URL

Static URL contains the details of the RMI registry like hostname, port number and the connector name 
/jndi/rmi://hostname[:rmiPort]/connectorname 
  • hostname[:rmiPort] : RMI host and post number to locale JMX agent. By default, RMI port will be 1099 (if not specified). 
  • connectorname specifies the name which needs to be look-up in the RMI registry.
See the post, how to implement JMX MBean using Spring

Dynamic JMX Service URL

The URL consists of the serialized JMX object with Base 64 encoded value. See an example below
/stub/rO0ABdmVyLlJlpIDJyGvQkwAAAARod97VdgAEAeA==
We will see how to create JMX MBeans using dynamic URLs and how to access.

Happy Learning!!!!

Monday, November 4, 2013

Spring JMX - Expose POJOs as MBeans

Spring JMX allows you to easily expose POJOs as JMX MBeans. Even it allows the MBeans to deploy on application server which has MBean server running or can be run standalone. We can use jconsole to run the services provided by the MBean.
The configuration required to expose the POJO as Mbean is as follows. Here, MyBean is a POJO with at-least one public method.
<bean id="myMBean" class="com.test.MyBean"  />

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
   <property name="beans">
       <map>
          <entry key="bean:name=MyMBeanName" value-ref="myMBean" />
       </map>
   </property>
</bean>
MBeanExporter exposes the map of "beans" as MBeans. Here we exposed myMBean as "MyMMBeanName". This name will be shown in the jconsole. By default, all the public methods inside the POJO will be exposed as operations.
If the Spring JMX is not running under an application server, then we need a starter. Definition is as follows:
<!-- If not running on a server which has MBean server running, you must start here -->
<bean id="factory" class="org.springframework.jmx.support.MBeanServerFactoryBean" />
With the above configuration, The MBean can be accessed locally. The MBean can be exposed either using JMXJMP or RMI.
To expose using JMXJMP as follows. The default service URL to access is : service:jmx:jmxmp://localhost:9875
<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" />
To expose using RMI as follows.
<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean"
    depends-on="rmiRegistry">
    <property name="objectName" value="connector:name=rmi" />
    <property name="serviceUrl"
        value="service:jmx:rmi://localhost/jndi/rmi://localhost:10099/myconnector" />
</bean>

<bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="10099" />
</bean>
The complete configuration of exposing POJO using Spring JMX (With Remote access with RMI) without running an application server is as follows:
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <bean id="myMBean" class="com.test.MyBean"  />

    <bean class="org.springframework.jmx.export.MBeanExporter"
       lazy-init="false">
       <property name="beans">
           <map>
           <entry key="bean:name=MyMBeanName" value-ref="myMBean" />
           </map>
        </property>
    </bean>

    <!-- If not running on a server which has MBean server running, you must start here -->
    <bean id="factory" class="org.springframework.jmx.support.MBeanServerFactoryBean" />

    <bean class="org.springframework.jmx.support.ConnectorServerFactoryBean"
        depends-on="rmiRegistry">
        <property name="objectName" value="connector:name=rmi" />
            <property name="serviceUrl"
               value="service:jmx:rmi://localhost/jndi/rmi://localhost:10099/myconnector" />
    </bean>

    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
        <property name="port" value="10099" />
    </bean>

</beans>
The POJO MyBean.java is :
package com.test;

public class MyBean {
    public void start()
    {
        System.out.println("Started");
    }
 
    public void stop()
    {
        System.out.println("Stopped");
    }
}
The Application program to start is :
package com.test.application;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
   public static void main(String...args)
   {
       ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
       context.getBean("factory");
   }
}
When we run this program, it start the MBean. Connect to this using jconsole. The MBean with name "MyMBeanName" visible under MBeans Tab.

Happy Learning!!!!