Using custom Java code to access the Derby MBeans

In addition to using a tool like JConsole, you can also access the Derby MBeans from a Java application. How to do this may depend on how you configure the JVM that is running Derby, how you configure user authentication and authorization, or the host(s) from which you want to access the MBeans.

This section has some example code to help you get started. You will find the JMX classes you need in the packages javax.management and javax.management.remote.

You do not need any Derby libraries in the JMX client application's classpath (unless MBean proxies are used).

Connecting to the MBean Server

Derby will attempt to register its MBeans with the platform MBean server of the JVM running the Derby system (embedded or Network Server). The following examples assume that you have configured the Derby JVM to enable remote JMX, which means that you have set a port number (com.sun.management.jmxremote.port) to be used by the JMX Server Connector.

The examples below assume that the port configured for remote JMX is 9999, that the host name of the host running Derby is example.com, and that this host is reachable from the client host. (This host name is fictitious, and is used for example purposes only.)

The following example code shows how to connect to the MBean Server when JMX security has been disabled:

    JMXServiceURL url = new JMXServiceURL(
            "service:jmx:rmi:///jndi/rmi://example.com:9999/jmxrmi");
    JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
    MBeanServerConnection mbeanServerConn = 
        jmxc.getMBeanServerConnection();

The following code shows how to connect to the MBean server when JMX password authentication is enabled (the default):

    JMXServiceURL url = new JMXServiceURL(
            "service:jmx:rmi:///jndi/rmi://example.com:9999/jmxrmi");
    // Assuming the following JMX credentials: 
    //  username=controlRole, password=derby
    String[] credentials = new String[] { "controlRole" , "derby" };
    HashMap<String,Object> env = new HashMap<String,Object>();
    // Set credentials (jmx.remote.credentials, 
    //  see JMX Remote API 1.0 spec section 3.4)
    env.put(JMXConnector.CREDENTIALS, credentials);
    // if the server's RMI registry is protected with SSL/TLS (JDK 6)
    //  (com.sun.management.jmxremote.registry.ssl=true), the following
    //  entry must be included:
    //env.put("com.sun.jndi.rmi.factory.socket", 
    //    new SslRMIClientSocketFactory());  // uncomment if needed

    // Connect to the server
    JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
    MBeanServerConnection mbeanServerConn = 
        jmxc.getMBeanServerConnection();
Note: Not specifying SslRMIClientSocketFactory when required may result in the error message java.rmi.ConnectIOException: non-JRMP server at remote endpoint.

Creating a ManagementMBean

The only Derby MBean that can be created by a JMX client is the ManagementMBean. This MBean is useful for controlling Derby management (for example, enabling and disabling management or MBeans), and to obtain information such as the system identifier (which may be needed to specify MBeans later).

If you create such an MBean from your application, and if Derby has already registered a ManagementMBean instance, the new MBean cannot have the same object name as the ManagementMBean already registered with the server. It is therefore recommended to use a different object name domain (that is, different from example.com) and/or a different type key property value (different from Management).

The following example code shows how to create and register a new ManagementMBean with the MBean server:

    ObjectName mgmtObjName = new ObjectName("com.example.app", 
                   "type", "DerbyManagement");
    try {
        ObjectInstance mgmtObj = 
            mbeanServerConn.createMBean("example.com.mbeans.Management", 
                mgmtObjName);
    } catch (InstanceAlreadyExistsException e) {
        // A management MBean with this object name already exists!
    }

Activating Derby management

Derby attempts to activate its JMX management service by default, so it will usually be active unless you explicitly deactivate it, providing that Derby has permissions to perform the activation. If Derby management is not active, you will not be able to access any MBeans except the ManagementMBean.

By accessing the ManagementActive attribute of the ManagementMBean, you can check whether the Derby JMX management service is active or not. The following example code performs this check and activates the Derby management service if it is not already active:

    // assuming we already have a reference to the
    //  ManagementMBean's object name
    Boolean active = (Boolean) 
        mbeanServerConn.getAttribute(mgmtObjName, "ManagementActive");
    if (!active.booleanValue()) {
        // start management
        mbeanServerConn.invoke(mgmtObjName, "startManagement", 
            new Object[0], new String[0]);
    }

Obtaining the system identifier

The system identifier is a unique String that distinguishes one running Derby system from another. All MBeans that are instantiated by Derby include the system identifier in their object names.

One way to access an MBean is to fully specify its object name when contacting the MBean server. For this, you need to know the current system identifier. (Alternative ways to access MBeans include querying the MBean server for all MBeans, or for MBeans whose object names match a specific pattern.)

The following example shows how to obtain the system identifier by accessing a ManagementMBean:

    // assuming we already have a reference to the 
    //  ManagementMBean's object name
    String systemID = (String) mbeanServerConn.getAttribute(mgmtObjName, 
        "SystemIdentifier");

The following example shows how to obtain the system identifier from a Derby MBean's object name:

    // assuming we already have a reference to the ObjectName
    //  of an MBean registered by Derby, for example the
    //  Derby-registered ManagementMBean
    String systemID = derbyMgmtObjectName.getKeyProperty("system");

Accessing a specific Derby-registered MBean

In the previous examples, you have already seen how to read a single MBean attribute, and how to invoke an MBean operation. In order to do this, you usually need a reference to the MBean's ObjectName.

If you consult the API documentation for the Derby MBeans at http://db.apache.org/derby/javadoc/publishedapi/jdbc4/ and obtain the system identifier of the Derby system you are accessing through JMX, you have all the information you need to be able to instantiate a javax.management.ObjectName object directly, by fully specifying its String representation (see the ObjectName API documentation for details).

The following example code shows how to obtain a reference to the VersionMBean for derby.jar:

    // Assuming we already know the system identifier 
    // (see examples above), systemID.
    // A list of key properties is available is each MBean's Javadoc API.
    Hashtable<String, String> keyProps = new Hashtable<String, String>();
    keyProps.put("type", "Version");
    keyProps.put("jar", "derby.jar");
    keyProps.put("system", systemID);
    // MBeans registered by Derby always belong to the 
    //  "org.apache.derby" domain
    ObjectName versionObjectName = 
        new ObjectName("org.apache.derby", keyProps);

    // we can now use the object name to read an attribute
    String versionString = 
        (String) mbeanServerConn.getAttribute(versionObjectName, 
            "VersionString");
    System.out.println("VersionString: " + versionString);

The output would look something like this:

VersionString: 10.9.1.1 - (1305115)
Related reference
Introduction to the Derby MBeans
Enabling and disabling JMX
Using JConsole to access the Derby MBeans
Troubleshooting JMX connection issues