Version 7

    Exposing JMX MBeans To Remote Clients

     

    Any MBean can be exposed to a remote client. All that is needed is to configure the proxy factory which will create a proxy for the MBean and bind it into JNDI.

     

    Let's see how it's done. Suppose, we have the following MBean:

    public interface MyServiceMBean
    {
       String myAction(String arg);
    
       Object invoke(org.jboss.invocation.Invocation mi) throws Exception;
    }
    
    public class MyService
       implements MyServiceMBean
    {
       public String myAction(String arg)
       {
          System.out.println("MyService.myAction> arg=" + arg);
          return "myAction";
       }
    
       public Object invoke(Invocation mi) throws Exception
       {
          System.out.println("MyService.invoke> method=" + mi.getMethod().getName());
          return "invoke";
       }
    }
    

     

    This MBean can be deployed into JBoss with the following -service.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <server>
      <mbean code="org.jboss.test.MyService" name="mine:service=MyService"></mbean>
    </server>
    

     

    Now, we want a remote client to have a proxy for MyService of type MyServiceMBean. For that we configure the proxy factory like this (we can add this in the same -service.xml MyService is defined in):

       <!-- Proxy factory for MyService that will call target method on the target service -->
       <mbean code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
          name="jboss.jmx:type=adaptor,name=MyServiceInvokeTarget,protocol=jrmp,service=proxyFactory">
          <!-- Use the standard JRMPInvoker from conf/jboss-service.xxml -->
          <depends optional-attribute-name="InvokerName">jboss:service=invoker,type=jrmp</depends>
          <!-- The target MBean -->
          <depends optional-attribute-name="TargetName">mine:service=MyService</depends>
          <!-- Where to bind the proxy factory -->
          <attribute name="JndiName">MyServiceInvokeTarget</attribute>
          <!-- Invoke target method instead of invoke(Invocation mi) -->
          <attribute name="InvokeTargetMethod">true</attribute>
          <!-- Comma-separated list of exported interfaces -->
          <attribute name="ExportedInterfaces">org.jboss.test.MyServiceMBean</attribute>
          <!-- client-side interceptors -->
          <attribute name="ClientInterceptors">
              <interceptors>
                 <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
                 <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                 <interceptor>org.jboss.jmx.connector.invoker.client.InvokerAdaptorClientInterceptor</interceptor>
                 <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
              </interceptors>
          </attribute>
       </mbean>
    

     

    This will create a proxy factory, create a proxy for the MBean and bind it under MyServiceInvokeTarget JNDI name. Remote client can now access the service on the server:

          InitialContext ic = new InitialContext();
          MyServiceMBean myService = (MyServiceMBean)ic.lookup("MyServiceInvokeTarget");
          String result = myService.myAction("param");
          assertEquals("myAction", result);
    

     

    Note: we are not required to export the MBean interface. We could export any other interface that has myAction method with the same signature.

     

    In the server.log we'll get:

    [STDOUT] MyService.myAction> arg=param
    

     

    There is an alternative way for the MBean to receive invocations, i.e. with the managed operation invoke(Invocation mi). The Invocation class is a representation of the method invocation and contains information about the method name, parameters, client's principal and credentials and other payload added on the client side (add your own client interceptors if you want to add other payload to the invocation). In the invoke(Invocation mi) method you can extract all this payload and handle the invocation. To make the MBean proxy to call invoke operation instead of the target method directly, set the InvokeTargetMethod attribute in the proxy factory definition to false.

       <!-- Proxy factory for MyService that will call invoke(Invocation mi) on the target service -->
       <mbean code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
          name="jboss.jmx:type=adaptor,name=MyService,protocol=jrmp,service=proxyFactory">
          <!-- Use the standard JRMPInvoker from conf/jboss-service.xxml -->
          <depends optional-attribute-name="InvokerName">jboss:service=invoker,type=jrmp</depends>
          <!-- The target MBean -->
          <depends optional-attribute-name="TargetName">mine:service=MyService</depends>
          <!-- Where to bind the proxy factory -->
          <attribute name="JndiName">MyService</attribute>
          <!-- Invoke invoke(Invocation mi) operation instead of the target method -->
          <attribute name="InvokeTargetMethod">false</attribute>
          <!-- MyService interface -->
          <attribute name="ExportedInterfaces">org.jboss.test.MyServiceMBean</attribute>
          <attribute name="ClientInterceptors">
              <interceptors>
                 <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
                 <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                 <interceptor>org.jboss.jmx.connector.invoker.client.InvokerAdaptorClientInterceptor</interceptor>
                 <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
              </interceptors>
          </attribute>
       </mbean>
    

     

    Now if the following client code is executed

          InitialContext ic = new InitialContext();
          MyServiceMBean myService = (MyServiceMBean)ic.lookup("MyService");
          String result = myService.myAction("param");
          assertEquals("invoke", result);
    

     

    the following will be logged:

    [STDOUT] MyService.invoke> method=myAction
    

     

    Note: the InvokeTargetMethod managed attribute was added to JRMPProxyFactory MBean after 3.2.6 was released. For 3.2.6 and earlier versions the target MBean must implement invoke(Invocation mi) method, i.e. it's equivalent to InvokeTargetMethod=false.