Monday, March 17, 2008

JMX, IOException, and NameNotFoundException

When using JMX connectors, it is important that the connector client URL and the connector server URL appropriately match. The only protocol required of remote JMX is RMI and so it is often RMI that is used in conjunction with remote JMX. There are several different types of exceptions that might occur depending on different JMX RMI URL problems, but the focus of this blog entry is on the NameNotFoundException.

The first code listing shown is a very simple JMX client.

JmxSpringClientMain.java

package client;

import java.io.IOException;
import java.net.MalformedURLException;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JmxSpringClientMain
{
public static void main(String[] aArguments)
{
final String jmxRmiStr =
"service:jmx:rmi://localhost/jndi/rmi://localhost:1099/dustinjmxrmi";
try
{
final JMXServiceURL jmxUrl = new JMXServiceURL(jmxRmiStr);
final JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxUrl);
final MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
System.out.println( "MBean Count: " + mbsc.getMBeanCount() );
System.out.println( "MBean Default Domain: " + mbsc.getDefaultDomain() );
}
catch (MalformedURLException badUrl)
{
System.err.println( "ERROR: Problem with JMXServiceURL based on "
+ jmxRmiStr + ": " + badUrl.getMessage() );
}
catch (IOException ioEx)
{
System.err.println( "ERROR: IOException trying to connect to JMX "
+ "Connector Server: " + ioEx.getMessage() );
}
}
}


The JMX Connector server that the above client would connect to could be set up programmatically, but I am going to use the Spring framework to do this for me. Here is an excerpt from the appropriate Spring configuration file.

spring-jmx-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="stateHandler"
class="dustin.StateHandler">
<property name="state" value="Colorado" />
<property name="capital" value="Denver" />
</bean>

<bean class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="dustin.example:name=jmx,type=spring"
value-ref="stateHandler" />
</map>
</property>
<property name="assembler" ref="assembler" />
</bean>

<bean id="assembler"
class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<property name="managedInterfaces">
<list>
<value>dustin.AppStateIf</value>
</list>
</property>
</bean>

<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<property name="port" value="1099"/>
</bean>

<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean"
depends-on="registry">
<property name="objectName" value="connector:name=rmi"/>
<property name="serviceUrl"
value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/dustinjmxrmi"/>
</bean>

</beans>


If you compare the lines highlighted in the JMX Client code and in the Spring XML to be used to set up the server, you'll see that they match. If the last part of the JMXServiceURL is changed (from "dustinjmxrmi" to say "jmxrmi"), an IOException is thrown by the client with the following output:

Failed to retrieve RMIServer stub: javax.naming.NameNotFoundException: jmxrmi

Note that this is thrown as an IOException when the client code tries to access the JMX connector server. The NameNotFoundException mentioned in the IOException message extends NamingException.

The IOException/NameNotFoundException is a result of having matching host and port information between connector client and server, but having a mismatch on the name at the end of the JMX RMI URL. If the server is not up at all or is at a different host/port combination than specified by the JMX client, the exceptions underlying the resulting IOException in this case are ServiceUnavailableException and two varieties of ConnectException. The exact message is:

Failed to retrieve RMIServer stub: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connect]

Like the NameNotFoundException, ServiceUnavailableException also extends NamingException.

For additional details on constructing a JMX RMI URL with JMXServiceURL, see Monitor Your Applications with JConsole - Part 3, JMX Accelerated HowTo (see section titled "RMI and JMXMP URLs"), the Sun JMX forum entry JMXServiceUrls, and DongWoo Lee's JMX RMI Proxy/NAT Connection image.

Wednesday, March 12, 2008

Collaborate08 Events and Announcements

Collaborate08 is just a month away and so it is not surprising that I'm beginning to see many activities and announcements related to that conference. Here are some of the most interesting.

Collaborate 08 Hands-on Labs: Service Enable E-Business Suite / PeopleSoft / Siebel / JD Edwards E1 with Oracle SOA Suite
* Sessions held multiple times April 14 through 16 (2008)
* Held at Hyatt Regency Denver, Mineral B


Denver Metro Convention & and Visitors Bureau Welcome

* Resources regarding events and attractions in the Denver area

Application Express Best Practices


Find AppsLab at Collaborate08



The User Group Conferences are Coming


Justification Letter to Attend Collaborate08 (Link to http://www.ioug.org/collaborate08/attending/COLLABORATE_08_Justification_Letter.doc is no longer valid.)

Independent Oracle Users Group Plans for Collaborate08

I will be presenting on using Flex, OpenLaszlo, and Flash with Oracle database at Collaborate08.

Tuesday, March 11, 2008

Spring JMX Configuration with XML Schema-Based Configuration

In a previous blog entry, I demonstrated basic Spring XML configuration to use Spring's JMX support. The configuration style I used in that blog entry is the traditional DTD-based Spring beans configuration. In this blog entry, I'll show the same configuration file, but this time I am using the newer XML Schema-based Spring JMX configuration. Specifically, I will demonstrate use of the "p namespace" and the "util" schema.

The code listing shown next shows the how the Spring XML configuration appears when making use of the XML Schema-supported configuration:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

<bean id="jmxService"
class="marx.SimpleBean"
p:action="Spring Action"
p:behavior="Spring Behavior"
/>

<util:map id="exposedMBeans">
<entry key="dustin:type=marx" value-ref="jmxService" />
</util:map>

<bean class="org.springframework.jmx.export.MBeanExporter"
p:beans-ref="exposedMBeans"
p:assembler-ref="assembler" />


<util:list id="manageableInterfaces">
<value>marx.SimpleBeanIf</value>
</util:list>

<bean id="assembler"
class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"
p:managedInterfaces-ref="manageableInterfaces" />

<bean id="registry"
class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
p:port="1099" />

<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean"
depends-on="registry"
p:objectName="connector:name=rmi"
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"
/>

</beans>


I highlighted the significant changes to use Spring's XML Schema-based configuration. The util namespace and p namespace are defined at the top and a schemaLocation is defined for the util namespace.

Note that no schemaLocation is provided for the p namespace because it is handled in the core Spring framework code. This prevents the restriction of the names in the p-namespace so that they can match your given property names. Several of the highlighted examples demonstrate the p-namespace in action (note the p: syntax). Additional details on the p-namespace can be found in the Spring Framework 2.5 Reference under Shortcuts and Other Convenience Options for XML-based Configuration Metadata.

The example above of using Spring's JMX configuration with the XML Schema-based format also demonstrates two uses of the util namespace. In this case, the util:map used for articulating the beans to be exposed as MBeans and the util:list used for specifying the interfaces exposed through JMX for the Spring beans-turned-MBeans are both used instead of special map and list elements within a property.

In short, the Spring XML Schema-based configuration can be more concise and readable than the older DTD-based configuration. While there are things I like about this new format, I have not yet convinced myself that I necessarily like this new format better than the tried and true format. However, as this blog entry shows, it is pretty easy to convert the old format to this new format when desired. Other perspectives regarding the "p namespace" include Matt Raible's and Sergio Bossa's blog entries.

The Spring reference points out that this newer XML Schema-based approach can be less flexible than the older DTD-based approach and that it is advisable not to mix the approaches on a given project due to trouble understanding and maintaining the inconsistent configuration approaches.

Tuesday, March 4, 2008

Spring Exposing RMI With and Without Declared RMI Host

This blog entry is intended to provide some details about using Spring's RMI Registry exporting capabilities. The two listings below show snippets of a Spring configuration file and are exactly the same snippets of XML with the exception of one line. The one line that makes these snippets different is not contained in the first listing and is highlighted in the second listing. This line specifies a host to use for the Spring-loaded RMI Registry.


<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<property name="port" value="1099"/>
</bean>

<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean"
depends-on="registry">
<property name="objectName" value="connector:name=rmi"/>
<property name="serviceUrl"
value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/>
</bean>



<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<property name="host" value="localhost" />
<property name="port" value="1099"/>
</bean>

<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean"
depends-on="registry">
<property name="objectName" value="connector:name=rmi"/>
<property name="serviceUrl"
value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/>
</bean>


At first glance, it would seem simple to assume, because localhost is the default setting for RMI registry host exposed by Spring, that these two XML snippets would result in the same functionality for the Spring-based application. However, there is a significant difference caused by the presence or lack of this one line.

In the first case (no host specified), Spring will start an RMI registry if it cannot find one. That RMI registry will be started on the localhost.

At this point, it is natural to assume that the second listing will lead to the same result because localhost is explicitly specified as the host. However, this is not the case. When localhost is explicitly specified as a host, the RMI registry must be started externally first (for example, by running rmiregistry) and then Spring will use that running RMI registry. If one specifies localhost explicitly and has not previously started an RMI registry on that host and port, an exception will be encountered that includes this line: java.rmi.ConnectException: Connection refused to host: localhost.

This is the case for RmiRegistryFactoryBean as used in the examples above, but the same thing is just as true for using RmiServiceExporter for RMI remoting. The only difference is that RmiServiceExporter has registryHost rather than host for the attribute that affects whether an RMI registry needs to be running before the Spring container is started.

Monday, March 3, 2008

Controlling JConsole's MBean ObjectName Presentation

I sometimes find myself learning something the hard way and then finding that it was already available online after I have figured it out. One case of this happened recently when I played with JConsole and my naming of my JMX MBeans. I noticed that the "type" property in each ObjectName of my MBeans was listed first no matter where it fell in the order of properties. The remainder of the ObjectName properties were listed in the order they appeared in the ObjectName. What this implies is that MBean developers should provide the list of properties in order so that they will appear together correctly in the JConsole hierarchical tree. It also demonstrates the importance of using "type" in MBean names so that the first level will be set with this value automatically.

Chapter 3 ("Using JConsole") of the Java SE Monitoring and Management Guide covers this in much greater detail in the section called "Constructing the MBean Tree."

This section outlines the same observations I made above and learned the hard way, but it also adds a way to control the order of the displayed properties in the tree from the command line. The system property -Dcom.sun.tools.jconsole.mbeans.keyPropertyList can be used to specify a list of property names. The order of the specified list will be the order of nested hierarchical levels in JConsole's MBeans tree.

I had planned to write a more extensive blog on the appropriate naming of one or more MBeans to appropriately take advantage of JConsole's assumptions. However, the article cited above covers this thoroughly, so this blog entry has turned into a pointer to that article.

Using Spring Metadata MBean Exporting for Greater Descriptive Detail

I typically use InterfaceBasedMBeanInfoAssembler approach when configuring the Spring Framework to expose specific operations and attributes on my beans-turned-MBeans. However, there are times when the ability to easily associate metadata with a bean class can be useful in order to provide greater detail (MBeanInfo data) to the JMX client (such as JConsole). This blog entry demonstrates how easy this is to accomplish with Spring and how the results look in JConsole. Along the way, a few nuances of interest will also be pointed out.

One disadvantage of the in-source metadata approach is that the beans which can be simple Java classes when using the interface-based approach must now have Spring-specific annotations applied to their source code. The benefit that comes for this price is the ability to instruct Spring to set much more of the generated Model MBean's metadata.

The following class, ManageMe, shows an otherwise normal Java class that has the Spring-specific annotations (JDK annotations in this case, though Commons Attributes could have been used instead).

ManageMe.java

package jmx.spring.dustin;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;

/**
* This class's main purpose is to test and showcase Spring 2.5's support for
* annotations-based MBean exposure.
*/
@ManagedResource(
objectName="dustin:name=springJmxWithAnnotations",
description="Example and test of Spring's support for annotations-based detail")
public class ManageMe
{
private String manageableString;
private boolean manageableBoolean;
private boolean anotherBoolean;

@ManagedAttribute(description="The manageableString Attribute")
public String getManageableString()
{
return this.manageableString;
}

@ManagedAttribute(description="Set the manageableString Attribute")
public void setManageableString(String string)
{
this.manageableString = string;
}

@ManagedAttribute(description="Get the manageableBoolean Attribute")
public boolean isManageableBoolean()
{
return this.manageableBoolean;
}

@ManagedAttribute(description="Set the manageableBoolean Attrbiute")
public void setManageableBoolean(boolean bool)
{
this.manageableBoolean = bool;
}

@ManagedAttribute(description="Get value of another boolean")
public boolean isAnotherBoolean()
{
return this.anotherBoolean;
}

@ManagedOperation(description="Setter for another boolean")
@ManagedOperationParameters({
@ManagedOperationParameter(name="bool",description="Setter for another boolean") })
public void setAnotherBoolean(boolean bool)
{
this.anotherBoolean = bool;
}

@ManagedOperation(description="Textbook Hello World example.")
public String helloWorld()
{
return "Hello World!";
}

@ManagedOperation(description="Slightly more interesting variant of Hello World")
@ManagedOperationParameters({
@ManagedOperationParameter(name="subject",description="Subject of Hello") })
public String helloWorld(String subject)
{
return "Hello " + subject;
}
}


I set the bean class ManageMe up intentionally to expose multiple attributes and operations for comparison purposes. I intentionally annotated one of the attribute accessor methods (setAnotherBoolean) with the @ManagedOperation annotation rather than the normally used @ManagedAttribute annotation. For the other attributes, I used the proper @ManagedAttribute. I also used @ManagedOperation on real operations that are not getter or setter methods for an attribute.

The Spring XML configuration file I used for this is shown next.

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="beanTurnedMBean"
class="jmx.spring.dustin.ManageMe">
<description>A JMX Service</description>
<property name="manageableString" value="springXmlDefault" />
<property name="manageableBoolean" value="false" />
</bean>

<bean class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler" ref="annotationsAssembler"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>

<bean id="annotationsAssembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>

</beans>


The most interesting aspect of this XML file for our use is MBeanExporter's use of MetadataMBeanInfoAssembler and its use of AnnotationJmxAttributeSource.

Now, it is time to look at this managed bean using JConsole and see the extra provided data. Click on any screen snapshot to see a larger version of that screen snapshot.

The first screen snapshot (below) shows that the managedString attribute is both writable and readable. This is because the @ManagedAttribute annotation was applied to both the setter and getter method for that attribute in the ManageMe class shown above.



Note in the screen snapshot of JConsole shown above that the description is also shown. While the Readable and Writable fields are true in this String attribute case, the Is field is false.

The next screen snapshot (below) demonstrates the JConsole output for AnotherBoolean. In this case, the field Readable is still true, but Writable is false. This is because I "mistakenly" applied an @ManagedOperation attribute to the setter for AnotherBoolean rather than the appropriate @ManagedAttribute annotation. Note also that the Is field is marked true because this is a boolean and the getter is correctly annotated.



The final screen snapshot (below) displays what JConsole looks like for a boolean that has both its getter (or is method) and setter set correctly with @ManagedAttribute. As you can see in the snapshot, all three fields (Readable, Writable, and Is) are true in this case.



In all three of the above screen snapshots, you will note that there is no setAnotherBoolean listed because of the problem of misapplying @ManagedOperation to a setter method. The other getters and setters are there because the @ManagedAttribute annotation was properly applied to them. For completeness, you can note that @ManagedOperation does work for true operations that are not actually getters or setters for attributes. The two helloWorld methods prove this.

In summary, Spring's support for metadata-configurated MBean exporting is easy to apply to garner extra exposed MBean detail. One of the most important take-aways from this blog entry is that @ManagedAttribute must be used on getter and setter methods and that @ManagedOperation should be used on methods that are not getters or setters for any attributes.

One thing I did not show here is that if neither annotation is applied to a getter or setter method, it is not shown as an operation in JConsole. In other words, the only way to get a getter or setter method to show up is to use @ManagedAttribute for each piece (once for the getter and once for the setter). If you want a read-only attribute from a JMX client perspective, apply @ManagedAttribute to only the getter. If you want a write-only, apply that annotation only to the setter method.

Chapter 20 of the Spring 2.5 reference focuses on Spring's JMX support. Of particular interest related to this blog entry are sections 20.3.3 ("Using JDK 5.0 Annotations") and 20.3.4 ("Source-Level Metadata Types"). The latter section includes Table 20.2 ("Source-Level Metadata Types") which confirms that @ManagedAttribute should be applied to methods that are getters and setters for attributes while @ManagedOperation should be applied to all methods other than getters and setters.

Saturday, March 1, 2008

JMX Specifications: An Overview

The world of Java Management Extensions (JMX) is specified in multiple specifications. The purpose of this blog entry is to provide an organized list of these JMX-related specifications with a few interesting notes about each. Note that a list of the JMX-related Java Specification Requests (JSRs) is available here.

The basic JMX concept is one of the oldest of the Java Specification Requests. The third JSR (JSR-3) is Java Management Extensions (JMX) Specification. In fact, because JSR-2 has been withdrawn, the only older JSR than JMX is the Realtime Java JSR (JSR-1). The final release of JMX 1.0 was on 7 September 2000. The first maintenance release for JMX (JMX 1.1) was released on 15 January 2002 followed by the second JSR-3 maintenance review (JMX 1.2, introducing MBeanServerConnection interface and four-parameter removeNotificationListener methods among other things) on 27 August 2002. JMX 1.3 (third maintenance release of JSR-3, introducing MXBeans) was released on 25 April 2006 and was quickly followed by the release of JMX 1.4 (fourth maintenance release of JSR-3) on 15 August 2006.

As described in my previous blog entry, JMX 1.3 dropped the concept of having the JMX reference implementation separate from the JMX platform server implementation. Java SE 6 provides a JMX Platform Server that is also the JMX 1.4 reference implementation.

While JSR-3 and its maintenance releases describe much of the core of present-day JMX, the standardization of remote JMX access is accomplished with JSR-160 ("Java Management Extensions (JMX) Remote API"). This JSR's initial final release date was 23 October 2003. This JSR provided standard definitions of JMX Connectors. The specification itself calls out several key predictions that turned out to be the actual realization as well. These include definition of two transport protocols (RMI and JMXMP), the decision to not call out any new discovery mechanisms, and the plan to support existing discovery mechanisms of SLP, Jini, and JNDI.

One interesting observation related to the JMX-related JSRs discussed so far (JSR-3 and JSR-160) is that when these were both changed to have 1.4 as their version numbers (JMX API 1.4 and JMX Remote API 1.4), they were also placed in the same overall specification. The JMX 1.4 specification available at http://java.sun.com/javase/6/docs/technotes/guides/jmx/JMX_1_4_specification.pdf contains both the core JMX specification (Parts I [JMX Instrumentation Specification] and II [JMX Agent Specification]) and the JMX Remote specification (Part III - "JMX Remote API Specification").

A more specific JSR related to remote JMX is JSR-262 ("Web Services Connector for Java Management Extensions (JMX) Agents"). This JSR calls for a web services JMX connector that is compliant with JMX connectors as outlined by JSR-160. A significant advantage of this, of course, is the ability to use JMX with web services. It is also useful because it allows JMX remote connector-compliant clients (such as JConsole) to communicate with managed resources via HTTP and thus more easily through firewalls. While JSR-262 is not 100% finalized, an implementation of it is available at https://ws-jmx-connector.dev.java.net/.

The next major release of JMX, JMX 2.0, is specified with JSR-255 ("Java Management Extensions(JMX) Specification, version 2.0"). According to the specification, JMX 2.0 was intended to be part of Java SE 6. That obviously did not happen, so now it is projected as part of Java SE 7. The blog entry JMX 2.0 API Early Draft Review covers the features of JMX 2.0 in the review and mentions the plan to release JMX 2.0 with Java SE 7.

Two Java management-related specifications have close ties with JMX. These are
JSR 77 ("J2EE Management") and JSR 88 ("Java EE Application Deployment").

Three JMX-related JSRs have been withdrawn. The withdrawn JMX-related JSRs are JSR-70 ("IIOP Protocol Adapter for JMS Specification") [IIOP = Internet Inter-ORB Protocol], JSR-71 ("JMX-TMN Specification") [TMN = Telecommunication Management Network], and JSR-146 ("WBEM Services: JMX Provider Protocol") [WBEM = Web Based Enterprise Management].

In a previous blog entry, I talked about the aged nature of the available JMX books. As evidenced by this brief history of JMX-related specifications, much has happened since even the latest of these books was published and much more is to come with JMX 2.0.