The under-the-hood implementation
of the MBean server in the RI is
com.sun.management.jmx.MBeanServerImpl
, but this
class should never be instantiated directly. Instead, the RI provides
a factory class called MBeanServerFactory
that
contains various static methods that allow you to obtain a reference
to the MBean server. In this section, we will describe each of those
static methods and give examples of how to use them. Example 6-1 is an abbreviated version of the
MBeanServerFactory
class.
Example 6-1. The static methods of MBeanServerFactory
package javax.management; // . . . public class MBeanServerFactory { // . . . public static MBeanServer createMBeanServer ( ) { // . . . } public static MBeanServer createMBeanServer (String domain) { // . . . } public static MBeanServer newMBeanServer ( ) { // . . . } public static MBeanServer newMBeanServer (String domain) { // . . . } public synchronized static ArrayList findMBeanServer (String AgentId) { // . . . } public static void releaseMBeanServer (MBeanServer mbeanServer) { // . . . } // . . . }
There are six static methods on
MBeanServerFactory
, as shown in Example 6-1. These methods allow you to create an
instance, find one or more instances, and release a reference to an
instance of an MBean server.
If no MBean server
instance exists (we’ll discuss how to find that out
later), there are four static methods that allow you to create one.
The first two, overloads of
createMBeanServer( ), allow you to create an
instance of the MBean server with the default domain name and a
specific domain name, respectively. When you create an instance of
the MBean server, MBeanServerFactory
maintains a
reference to the MBean server that was just created, ensuring that it
will not be garbage-collected. The second two methods, overloads of
newMBeanServer( ), do the same thing, but
MBeanServerFactory
does not
maintain a reference to the newly created MBean server—it is up
to the caller to maintain the reference.
If you want to create an instance of the MBean server and have
MBeanServerFactory
maintain an internal reference
to it, you have two choices. The first option is to call the version
of createMBeanServer(
)
with no parameters, which will create an
MBean server instance, store its reference inside the factory, and
return an MBeanServer
reference to you:
MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer( );
Recall from Chapter 2 that every MBean has a
unique ObjectName
instance associated with it.
Even though the MBean server itself is not technically a managed
resource, it must still have a domain name associated with it. In the
code above, the resulting MBean server would be created with the
default domain name, which in the JMX 1.0 RI is
"DefaultDomain"
. Figure 6-1
shows the management view of the MBean server when we use the
no-argument version of createMBeanServer( ).
Figure 6-1. The management view of the MBean server when the no-argument version of createMBeanServer( ) is used
If, however, we want to provide the MBean server with a
domain name other than
"DefaultDomain"
, we can pass a
String
argument containing that name:
String differentDomain = "TheTwilightZone"; MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(differentDomain);
The domain name of the resulting MBean server is now
"TheTwilightZone"
. Figure 6-2
shows the management view of this MBean server. As you can see, the
domain name of the MBean server is indeed what we passed to
createMBeanServer( ). But notice something
interesting about Figure 6-2. When the
Queue
instance is created in the
Controller
, the default domain is used. However,
the domain name of the Queue
MBean is now
"TheTwilightZone"
! Passing a domain name to
createMBeanServer( ) not only sets the domain
name of the resulting MBean server; it also sets the default domain
name for all MBeans registered within it.
Figure 6-2. The management view of the MBean server when a domain name is supplied to createMBeanServer( )
The internal references to MBean servers created using the
createMBeanServer( ) methods are stored within
MBeanServerFactory
. When a call to this static
method is made, the MBean server is instantiated and a reference to
it is added to this internal store.
However, if this is not the behavior you desire (e.g., if you
don’t want third-party components running within the
same JVM as your MBeans to be able to find your MBean server), you
can invoke one of the two static methods called
newMBeanServer( ) to avoid
MBeanServerFactory
’s default
behavior of keeping an internal reference to the newly created MBean
server. The syntax is identical to that of
createMBeanServer( ) in both cases, and the
resulting domain name follows the same rules as those for
createMBeanServer( ). To create an MBean server
with the domain name "DefaultDomain"
, simply use
the no-argument version of newMBeanServer( ):
MBeanServer mbeanServer = MBeanServerFactory.newMBeanServer( );
The resulting management view looks the same as the one shown in
Figure 6-1. To create an MBean server with the
domain name "TheTwilightZone"
, simply use the
other version of newMBeanServer( ):
String differentDomain = "TheTwilightZone"; MBeanServer mbeanServer = MBeanServerFactory.newMBeanServer(differentDomain);
The management view will look the same as the one shown in Figure 6-2.
To locate an existing
MBean server, use
MBeanServerFactory
’s static
findMBeanServer( ) method. Example 6-1 shows this method to be defined as:
public synchronized static ArrayList findMBeanServer (String AgentId) { // . . . }
This method takes a String
argument that is the
“agent ID” for the MBean server
you’re trying to find. This terminology is rather
vague, and I suspect that the designers of the specification intended
there to be some latitude in how this parameter is used from
implementation to implementation. According to the JMX 1.0 RI source
code, the agent ID is the name of the local host machine where the
JVM is running that contains the MBean server, followed by an
underscore character, followed by the system time in milliseconds
when the MBean server was instantiated.
For example, suppose the name of the local host is
"STEVE"
and the system time when the MBean server
was instantiated was 1002565476994 milliseconds. The agent ID in this
case would be "STEVE_
1002565476994"
. Clearly, it would be very
difficult (at best) to ask for a specific agent
ID using the RI. However, if you pass null
as the
argument to findMBeanServer( ), a list of all
the MBean servers in the JVM is returned. You can then iterate
through the list to find the MBean server that matches the domain in
which you are interested. For example, suppose we want to find the
MBean server for the "TheTwilightZone"
domain from
earlier in this chapter. We would call the findMBeanServer(
) static method of MBeanServerFactory
and then iterate through the list (we could also index through the
list, because the return value is a cloned version of the
ArrayList
that
MBeanServerFactory
keeps internally) until we find
the MBean server for the "TheTwilightZone"
domain:
String agentId = null; ArrayList mbeanServers = MBeanServerFactory.findMBeanServer(agentId); Iterator iter = mbeanServers.iterator( ); MBeanServer mbeanServer = null; while (iter.hasNext( )) { mbeanServer = (MBeanServer)iter.next( ); if (mbeanServer.getDefaultDomain( ).equals("TheTwilightZone")) { // found it! break; } else mbeanServer = null; } if (mbeanServer == null) { mbeanServer = MBeanServerFactory.createMBeanServer("TheTwilightZone"); }
If we had already created an instance of the MBean server with the
domain name "TheTwilightZone"
but used the static
method newMBeanServer( ) to do it, this code
would not find it. Recall that when we use newMBeanServer(
) to create an instance of the MBean server,
MBeanServerFactory
does not keep an internal
reference to it. Because findMBeanServer( )
returns the ArrayList
that serves as the internal
reference backing store, we will never find references to MBean
servers created with newMBeanServer( ). However,
the JMX RI doesn’t seem to care how many instances
of an MBean server are created with the same domain name, so the code
above will still find the instance we created with
createMBeanServer( ). A word to the wise: if you
anticipate ever needing to programmatically locate an MBean server by
its domain name, make sure you create it using
createMBeanServer( ), so that
MBeanServerFactory
will hold a reference to it.
Say that you need to
remove the internal reference stored
in MBeanServerFactory
to an MBean server instance
you created by calling createMBeanServer( ). You
can do so by calling releaseMBeanServer(
)
, which from Example 6-1 is
defined as:
public static void releaseMBeanServer(MBeanServer mbeanServer) { // . . . }
Note that calling this static method does not remove the MBean server
from the JVM; it simply removes it from the internal store of MBean
servers maintained by MBeanServerFactory
. You may
call this method only with an MBeanServer
reference obtained by a call to createMBeanServer(
). The syntax is very straightforward:
MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer( ); // // Do something with the reference // // Later on. . . // MBeanServerFactory.releaseMBeanServer(mbeanServer);
Once the call to releaseMBeanServer( ) is made,
subsequent calls to findMBeanServer( ) will fail
to locate a reference to the MBeanServer
just
released.