An MBean server forwards requests it receives to its default interceptor. A new feature of the Java Dynamic Management Kit (Java DMK) 5.0 enables you to modify this behavior of the MBean server and replace the default interceptor by another object implementing the same interface.
The example provided demonstrates how you can use the concept of MBean interceptors to forward requests to a specific interceptor, and to support “virtual” MBeans. The code samples in this chapter are from the files in the MBeanInterceptor example directory located in the main examplesDir (see “Directories and Classpath” in the Preface).
This chapter covers the following topics:
The concept of interceptors exploits the proxy design pattern to enable you to modify the behaviour of the MBean server. By default, the MBean server appears from the outside like a hollow shell that simply forwards every operation to the default interceptor. You can replace this default interceptor by another object implementing the same interface, to change the semantics of the MBean server. In most cases, you would use this other object to forward most or all operations to the default interceptor after doing some processing. However, you can also use it to forward some operations to other handlers instead, for instance depending on the object names involved. Figure 7–1 shows schematically how you can insert an interceptor between the MBean server and the default interceptor.
Some examples of the uses of interceptors are as follows:
Imposing security checks – The interceptor performs checks, for example it checks permissions, and only forwards operations that pass the security checks to the default interceptor.
Logging – The interceptor forwards all operations to the default interceptor, but also logs their parameters and results.
Creating virtual MBeans – The interceptor handles operations on MBeans it owns itself, and forwards others to the default interceptor. An interceptor might own all MBeans whose names match a particular pattern, for instance. In this way, MBeans do not necessarily have to be Java objects. This is very useful when there are a great many managed objects, or when they are very volatile.
Interceptors can be composed. When an interceptor is added, it is usually inserted between the MBean server shell and the current interceptor. Initially, the current interceptor is the default one. But if another interceptor has already been inserted, this other interceptor is the current one. Hence, a request could pass through several interceptors on its way to the default interceptor, for example a security checker and a logger.
The behavior to be implemented by an interceptor is specified by means of the MBeanInterceptor interface. An MBean interceptor has essentially the same interface as an MBean server. An MBean server forwards received requests to its default interceptor, which might handle them itself or forward them to other interceptors.
The default interceptor can be changed by using the setDefaultMBeanInterceptor method of the MBeanServerInt interface. The MBeanServerInt interface provides methods for getting and setting the DefaultMBeanInterceptor used for request treatment.
Particular care must be taken when replacing the default MBean interceptor with a user interceptor. The MBean server implemented in the Java DMK 5.0 passes requests to its default interceptor without checking the result returned, or the exceptions thrown by the interceptor.
Consequently, user interceptors, which implement most of the methods defined in the MBeanServer interface, must behave as specified for the corresponding MBeanServer methods in the JMX 1.1 specification. In particular, a method in an MBean interceptor must not throw any exceptions apart from the following:
Exceptions explicitly declared in the throws clause of the same method in the interface com.sun.jdmk.MBeanInterceptor
JMRuntimeException or a subclass of it
If an MBean interceptor does not respect this condition, and, for example, throws a NullPointerException exception, this might have unexpected effects on calling code, which might not be protected against such behavior.
The MBean interceptor example in the examples directory shows you two of the main functions of MBean interceptors, forwarding requests to a specific MBean interceptor, and creating virtual MBeans.
The examplesDir/MBeanInterceptor directory contains the following source files:
MasterInterceptor.java. This master interceptor receives all requests from the MBean server and, depending on the value of the domain part of the ObjectName, forwards them to one of the following interceptors:
The default MBean interceptor
Another MBean interceptor, the FileMBeanInterceptor
FileMBeanInterceptor.java. This is an MBean interceptor that mirrors the contents of a file system directory by faking MBeans which represent files and directories. These MBeans are completely virtual. The FileMBeanInterceptor owns a reserved domain name, the file domain in this example, which is used by the MasterInterceptor to decide which requests to divert to the FileMBeanInterceptor
Agent.java. This class implements a simple Java DMK agent which instantiates a MasterInterceptor and plugs in a FileMBeanInterceptor. This class shows how to instantiate the MasterInterceptor, how to plug it into the MBeanServer, and how to plug the DefaultMBeanInterceptor and FileMBeanInterceptor into the MasterInterceptor.
Compile all files in the examplesDir/MBeanInterceptor directory with the javac command.
For example, on the Solaris platform, type:
$ cd examplesDir/MBeanInterceptor/ $ javac -classpath classpath *.java
Run the example using the classes you have just built, by typing the following command in a terminal window:
$ java -classpath classpath Agent
Interact with the agent through the standard input and output in the window where it was started.
Load the agent's URL in your web browser:
You only see the MBeans registered in the DefaultMBeanInterceptor, namely the connector and adaptor MBeans, and the MBeanServerDelegate.
Press Enter to insert the FileMBeanInterceptor and view the files from the local directory as virtual MBeans.
Reload the agent's URL in your web browser to view the new MBeans:
Press Enter to stop the agent.