Advanced JSR 160

Intercepting calls between the JSR 160 JMXConnectorServer and the MBeanServer

JSR 160 offers a standard way of intercepting calls between the JMXConnectorServer and the target MBeanServer.
Such interception can be useful for logging, for granting access in a dynamic way (for example based on the value of the arguments for a certain call to an MBean - this cannot be achieved via the standard security policy files), for caching of values, and whatever else you may find useful.

In the examples bundled with the MX4J distribution, there is an example of how to setup such an interception, and here we will show in brief how to do it. Refer to the example's javadocs for further information.

First of all, you need to implement the interceptor. In the past, these interceptor were all implementation-dependent, but JSR 160 standardized the interface to achieve this: javax.management.remote.MBeanServerForwarder. Below you can find a simple (incomplete) example of how to track the Subject of the current invocation.

Example 3.11. Simple subject interceptor skeleton

               
public class SubjectTrackingMBeanServer implements MBeanServerForwarder
{
   private MBeanServer server;

   public synchronized MBeanServer getMBeanServer()
   {
      return server;
   }

   public synchronized void setMBeanServer(MBeanServer server) throws IllegalArgumentException
   {
      if (server == null) throw new IllegalArgumentException("Cannot forward to a null MBeanServer");
      this.server = server;
   }

   private void trackSubject()
   {
      Subject subject = Subject.getSubject(AccessController.getContext());
      System.out.println("Subject = " + subject);
   }

   public void addNotificationListener(ObjectName observed, NotificationListener listener, NotificationFilter filter, Object handback)
           throws InstanceNotFoundException
   {
      trackSubject();
      getMBeanServer().addNotificationListener(observed, listener, filter, handback);
   }

   ...

}
               
            

It is very simple to add this interceptors to a JMXConnectorServer, to intercept calls directed to the target MBeanServer. It is important to do this before the JMXConnectorServer is started, because if done afterwards it will have no effect (interception will not take place).

Example 3.12. Setting up the interception on the JMXConnectorServer

               
MBeanServer server = ...;
File passwords = ...;

Map environment = new HashMap();
JMXAuthenticator authenticator = new PasswordAuthenticator(passwords);
environment.put(JMXConnectorServer.AUTHENTICATOR, authenticator);

JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, environment, server);

// Here we setup the interception
SubjectTrackingMBeanServer interceptor = new SubjectTrackingMBeanServer();
cntorServer.setMBeanServerForwarder(interceptor);

// Start the connector server
cntorServer.start();