Dustin's Pages

Monday, June 30, 2008

In my article Basic Java Persistence API Best Practices, I wrote that because JPA is the result of good ideas from many previous technologies (Hibernate, JDBC, JDO, etc.), it follows that many of the best practices associated with these inspiring technologies can and should be applied to JPA. I used named and positional parameters as an example of this.

The interesting thing about JDBC's PreparedStatement is the fact that, out of the box, the JDBC standard PreparedStatement does not support named parameters. Rather, the PreparedStatement supports placeholders in the SQL syntax that are "populated" via set methods that provide the index of the ? being replaced (counting from left to right).

The JPA 1.0 specification covers named parameters in section 3.6.3. This section indicates how to use named parameters and points out that named parameters are only portable across JPA providers for JPA Query Language statements (not for native queries).

In the case of JPA, hindsight is 20/20. JPA was able to leverage named parameter binding in JPA Query Language statements from the beginning. This allows JPA developers to take advantage of a feature that has been proven to be beneficial many times over and has led to custom implementations when named parameter support is not built into the language or framework.

The main SpketIDE Laszlo Editor page demonstrates many of the useful features Spket provides for OpenLaszlo development. Of course, there is color syntax highlighting support, but there is also support for more advanced features such as different types of code completion and occurrence marking. I like having the Laszlo documentation available in the editor as an added convenience because I otherwise find myself spending a lot of time flipping back and forth between my editor and the LZX Reference Manual.

Perhaps the most difficult aspect of getting a freshly written JSR-160 (Remote JMX) compliant application working is ensuring a proper JMXServiceURL. In this blog entry, I cover some of the most common JMXServiceURL-related exceptions one may run into when developing the client and server portions of a management and monitoring system using Remote JMX.

The JMX 1.4 Specification combines the original JMX specification with the Remote JMX specification in a single document (the JMX Remote API Specification is part III of this document). This third part covers the required RMIconnector as well as the optional JMXMP connector. In this blog entry, I'll be focusing on using the RMI connector with Java SE 6HotSpotplatform MBean server. Instead of using JConsole as a client, I'll use a simple custom client to illustrate some of the exceptions one may encounter when writing one's own client.

I am using essentially the same code in this blog for examples that I previously used in the previous blog entry Remote JMX: With and Without Spring and Proxies. I will not reproduce the code here, but it is sufficient to know that the JMX Connector server code generally establishes its JMXServiceURL as service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi. Note that the protocol is RMI, the host is localhost, the port is 1099, and the URL string is "jmxrmi". Because the JMX client needs to use the same JMXServiceURL as provided by the server, I appreciate it when third-party JMX servers provide this to me. For example, both GlassFish and the JMX Web Services ConnectorReference Implementationsample provide their JMXServiceURL to the console when they are executed.

When the JMXServiceURL is known, it is relatively straightforward to write a client. The most significant lines of code for doing this are extracted from the code in the previously referenced blog and displayed next:

As the code listing above demonstrates, it is fairly easy (and mostly boilerplate) to connect clients to a JMX Connector Server with a well-known JMXServiceURL. However, it is not uncommon for new JMX developers to struggle to get the JMXServiceURL appropriately set. In the remainder of this blog entry, I now look at some of the most common JMXServiceURL-related exceptions one may run into.

This NameNotFoundException was a result of inadvertently mistyping the client's String URL portion (jmx-rmi specified by the client rather than jmxrmi without the hyphen). This is different from the above error because a JMX Connector Server is at the specified host and port, but with a different String portion. Because multiple JMX Connector Servers can use the same host/port combination as long as they have unique String portions of their URLs, it is not surprising that no assumptions can be made about what String was intended.

The previous exception demonstrated the result of attempting to access a JMX Connector Server from a client with the correct host/port comibination, but with an incorrect String URL portion. This ClassCastException is the result of not specifying any String URL portion at all in the JMXServiceURL. In other words, the jmxrmi portion was left off the end of the client's JMXServiceURL.

Until now, all of the previously covered exceptions resulted from a JMX Client using a mistyped or otherwise incorrect JMXServiceURL that did not match that used by the JMX Connector Server. This exception, however, is a JMX Connector Server exception that results from two different applications trying to use the same JMXServiceURL on the same host/port with the same URL String.

ERROR: Problem with JMXServiceURL based on rmi:///jndi/rmi://localhost:1099/jmxrmi: Service URL must start with service:jmx:

This error message is particularly descriptive and occurs when the JMXServiceURL does not begin with the specification-required service:jmx: portion. See Section 13.8 ("Connector Server Addresses") for additional details on all JMXServiceURLs beginning with this portion.

ERROR: Problem with JMXServiceURL based on service:jmx::///jndi/rmi://localhost:1099/jmxrmi: Missing or invalid protocol name: ""

As the error message indicates, the protocol is missing from the JMXServiceURL, which should be service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi, but the portion in red was omitted.

ERROR: Problem with JMXServiceURL based on service:jmx:nothing:///jndi/rmi://localhost:1099/jmxrmi: Unsupported protocol: nothing

Whereas the previous error message indicated a missing protocol designation, this error indicates an erroneous protocol specification. In this particular case, the incorrect JMXServiceURL used was service:jmx:nothing:///jndi/rmi://localhost:1099/jmxrmi where the "nothing" in red should have been "rmi".

ERROR: IOException trying to connect to JMX Connector Server: Failed to retrieve RMIServer stub: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial

This error message is displayed for the case where the second protocol listing in the JMXServiceURL is either omitted or has an incorrect value. In other words, if the highlighted portion of the correct JMXServiceURL (service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi)was omitted entirely or had something unexpected like "nothing," this error message would occur.

Other Remote JMX Exceptions/Errors Considerations

There are, of course, several other types of exceptions one can run into when remotely accessing a JMX Connector Server. These exceptions, which have not been covered here, are those that are thrown when the connection is successfully made, but the sought-after MBean cannot be found or some other problem occurs. The JMX Best Practices document outlines recommendations related to MBeans throwing standard exceptions and also recommends having MBeans intended for remote management/monitoring implement interfaces with operations that use the throwsIOException clause (more granular for client than available as UndeclaredThrowableException).

JMX Exceptions in General

The focus of this blog entry has been on common exceptions and errors encountered when running a custom JMX Connector Client with a custom JMX Connector Server. Note that JMX spells out its own exception hierarchy related to the JMX Agent. Section 6.4 (JMX Exceptions) of the JMX 1.4 Specification is devoted to these JMX exceptions. The section talks about the JMException, which is the main class and parent of all descendant exception classes (exception runtime exceptions) thrown by a JMX agent implementation. The JMX runtime exceptions are represented by JMRuntimeException and its descendant exceptions.

Tuesday, June 24, 2008

In this blog entry, I demonstrate generation of a simple RSS Reader using OpenLaszlo. The world certainly doesn't need another RSSreader, so the purpose of this blog entry is to demonstrate some of the easy-to-use features of OpenLaszlo.

The RSS reader shown in this blog entry will focus on blogs hosted on Blogger (blogspot.com). There are two URLs one can use to access RSS feeds from blogs with the blogspot.com domain. These are listed next with my own blog URL (marxsoftware.blogspot.com) used as the example.

This example will use the first type of URL to access blogspot.com-based RSS feeds and display the blog entries titles, URLs, and summaries if available. This simple reader allows the user to enter the main part of the blogspot.com blog name and the remainder of the appropriate RSS URL is constructed automatically. By default, this blog's RSS feed is initially displayed, but it can be changed to any other blog on the blogspot.com domain.

With an idea of how the RSS Reader built on OpenLaszlo works, it is time to turn to the code. I'll first list the entire listing for this OpenLaszlo application and then will focus on some pieces of it.

The dataset tag example shown above uses only three lines to associate a handle/name with the dataset called "blogRssFeed", instructs OpenLaszlo to initialize the dataset immediately, and provides the URL from which to access the data. I could have added the attribute type="http" to explicitly instruct OpenLaszlo that this data is obtained from an HTTP connection (rather than from a file), but using "http://" in the src attribute did essentially the same thing.

This sample blog RSS reader also provides examples of one of OpenLaszlo's most powerful features, the ability to use constraints. Constraints are easily identifiable by the ${---} syntax (similar to Ant properties syntax). In this example, I did not declare a constraint compiler directive, so it is implicitly assumed the compiler directive is always. Used this way, these constraints instruct OpenLaszlo to update attribute values immediately when the value to which they are constrained is updated.

A third interesting observation from this simplistic OpenLaszlo-based RSS Reader is the use of richinputtext with textformat:

In the snippet above, a handler is specified for the richinputtext element by nesting the handler element within the richinputtext element and providing the type of event it should handle (ontext) via the name attribute of handler.

The snippet above also demonstrates use of textformat (replaces the deprecated LzTextFormat and intended for script [not LZX XML markup] only). It also demonstrates using textformat in conjunction with the richinputtext element to create HTML text. In this case, it creates an HTML link to the designated RSS feed URL and does so in a new browser window.

Although this example provides several additional interesting things to highlight, I'll end this entry with one more thing of personal interest. Several pieces of the OpenLaszlo application take advantage of OpenLaszlo's XPath syntax support to query XML from the dataset populated via the RSS feed URL. The ability to use XPathsyntax is advantageous because of its familiarity to those who have used XPath in other things (such as XQuery or XSLT), because of the standard nature of XPath, and because of the expressive but concise nature of XPath syntax.

In this blog entry, I've attempted to demonstrate by example that OpenLaszlo supports several standards including XML, XPath, HTTP, and ECMAScript. OpenLaszlo also supports an implementation of the de facto "standard" XMLHttpRequest for non-XML data handling. With OpenLaszlo's basis in and support of common web development standards, it is a relatively easy technology to learn and apply.

UPDATE (14 July 2008): There are a couple of updates to note related to this OpenLaszlo-based RSS Reader. They are listed next with hyperlinks to more details.

Sunday, June 22, 2008

The June 2008 edition of the Tiobe Programming Community Index highlights the fact (in its introductory text) that ActionScript has entered the index's top twenty. This places ActionScript higher on the index than such venerable languages as Fortran and Smalltalk and above trendy languages such as Groovy, Erlang, and Scala.

I have written about things I like about ActionScript 3.0 in other blog entries, but I am using this blog entry to articulate in one place some of the things I most like about ActionScript 3.0 in honor of this Top 20 June 2008 ranking.

UPDATE (15 August 2008): The announcement this week that the ECMAScript committee has decided to move on a smaller incremental version of ECMAScript (3.1) rather than the complete overhaul originally envisioned for ECMAScript 4 can be disheartening for many of us. However, if the browser vendors are able to fully and completely meet the reduced ECMAScript 3.1 standard, that is a positive. Also, it sounds like ActionScript will continue to be a forward-leaning web language despite this decision.

What I Like Most About ActionScript (at least today!)

1. Browser Differences Are Just a Terrible Memory

Although there are things I really don't like about JavaScript, by far my biggest problem with JavaScript is the need to write different code for different browsers. If ActionScript provided no other advantage than the fact that I could write it once for any browser, it would be worth using. Interestingly, this is essentially what OpenLaszlo provides -- a subset of JavaScript that allows the developer to write to the same API regardless of browser. ActionScript goes well beyond JavaScript as most of us know it and as described in the remaining advantages listed next.

2. Static Typing

At home or when working on small projects, there are many things I enjoy about a dynamically typed language such as Ruby. However, when working on large enterprise applications with large groups of developers, I have found static languages to be preferable. It is a matter of personal taste, but my preference is to have the static support (default for ActionScript 3.0 in Flex 2 and Flex 3). For those who prefer dynamic typing, Flex allows the static typing to be turned off.

3. Class-Based Object-Oriented Features

JavaScript's prototype-based object-orientation has always been difficult for me to apply effectively, primarily because I keep trying to force my thinking about JavaScript into my experience with C++, Java, and C#. I'm not alone in this as evidenced by the fact that so much JavaScript I encounter simply doesn't take advantage of the prototype features.

In my opinion, it bodes well for ActionScript and developers learning ActionScript that Mozilla has accepted Adobe's contribution of ActionScript Virtual Machine to the Mozilla Tamarin project. Adobe has contributed many members of the Tamarin project and the current plans are to use the same ECMAScript Edition 4 implementation in Mozilla 2 (Firefox 4) and Adobe's ActionScript implementations.

6. ActionScript is Friendly to Java Developers

Experience with Java is usually of very little benefit when learning JavaScript and can even be a detriment. ActionScript, however, uses many features, syntax, and concepts that are very similar to Java. As discussed above, ActionScript supports static typing and class-based object-oriented features similar to Java. Another example is that ActionScript also provides a Javadoc-like tool called ASDoc.

7. ActionScript Complements Other Programming Languages

I like to be comfortable with multiple languages because different languages are best suited for different types of problems. ActionScript is one of those languages that a developer is likely to use in conjunction with one or more other languages. Especially within in Flex applications, ActionScript will often be used on the client side and a server-side language such as Java/Java EE, Ruby, Python, or Perl will be used with the Flex front-end. What this means is that ActionScript does not necessarily replace anyone's favorite language, but complements developers' favorite languages. Even the language that ActionScript might be mostly likely to replace (JavaScript) can be used with ActionScript. Because of this nature of ActionScript's common use case, ActionScript may sometimes avoid or be less affected by the defensiveness of developers who might think their favorite language is threatened by ActionScript's growing popularity.

Conclusion

With so many developers discovering the ease and power of using Flex, it is not surprising that ActionScript is gaining in popularity. In this blog entry, I've attempted to describe some reasons why I believe ActionScript is so popular for web development (and, with AIR, for desktop development). The rising popularity of Flex necessarily brings ActionScript along for the ride (much in the same way the Ruby on Rails framework brought Ruby newfound fame), but ActionScript has many positive features of its own (just as Ruby has many positive features of its own) to keep developers interested and happy.

SIDE NOTE:

By the way, I'm not the only one who has run into significant issues with JavaScript. Evidence of this is the title of the recently released book JavaScript: The Good Parts. Not only does the title imply that there are significant "bad parts," but the book's description goes beyond implication and explicitly spells out that JavaScript has some more than its fair share of issues.

Saturday, June 21, 2008

I'll demonstrate the tremendous utility of the JMXMXBean in this blog entry. While doing so, I'll also demonstrate the usefulness of a J2SE 5enum for reporting a set of discrete status values and will demonstrate the highly useful JMX (introduced with Java SE 6) class's newMBeanProxy and newMXBeanProxy methods.

The MXBean was introduced in J2SE 5, but was only available for predefined system MXBeans (platform MXBeans). The ability for JMX developers to write their own custom MXBeans was provided with Java SE 6. With MXBeans, the "standard" set of JMX MBeans is now Standard MBean, Dynamic MBean, Model MBean (used heavily in Spring JMX), Open MBean, and MXBean. In many ways, the MXBean is like a souped-up standard MBean. It follows similar conventions as the standard MBean, but provides much greater support for representing custom data types in remote JMX clients.

The standardized MXBean should not be confused with the JBoss-specific XMBean. The JBoss XMBean is not an MXBean, but is actually a JBoss Model MBean approach similar to how the Spring Framework approaches Model MBeans.

For my MXBean example in this blog entry, I will be taking advantage of one of my favorite features added to Java since the ubiquitous JDK 1.4.2: the Java enum. I wrote about the advantages of the Java enum for representing finite sets of related values in the OTN article Basic Java Persistence API Best Practices and in a previous blog entry The Power and Flexibility of the Java Enum. Because JMX is often used to access an application's state or status and because such a state or status can often be defined in a set of finite choices, the enum can be a highly useful construct in JMX applications.

For my demonstration, I will build the same functionality using both a Standard MBean and an MXBean. The next two listings show the Standard MBean interface (StatusMBean) and the very similar looking MXBean (StatusMXBean) interface. Note how they are nearly identical. The MXBean interface is only one byte larger than the MBean interface and that is due to the extra "X" added to the interface's name. They are identical other than that extra X. Therefore, it is easy to port a Standard MBean to an MXBean in terms of the MBean itself.

StatusMBean.java (Standard MBean interface)

package server;

public interface StatusMBean{ public StatusEnum getStatus();

public void setStatus(final StatusEnum status);

public enum StatusEnum{ SUCCESSFUL, FAILURE, UNSPECIFIED };}

StatusMXBean.java (MXBean Interface)

package server;

public interface StatusMXBean{ public StatusEnum getStatus();

public void setStatus(final StatusEnum status);

public enum StatusEnum{ SUCCESSFUL, FAILURE, UNSPECIFIED };}

With the Standard MBean and MXBean interfaces defined, it is time to look at their implementations. These are shown in the next two listings.

The rules (or required conventions) for MXBeans are less strict than those for Standard MBeans. For example, you may have noticed that the MXBean implementation class shown above is actually Status2. I had to use simply Status.java for the implementation of the Standard MBean interface StatusMBean, but did not need to do so for StatusMXBean. If I was to try to do the same thing with the Standard MBean, say by adding a "3" on the end of the implementation class so that it is Status3.java, I would see a runtime error similar to that shown in the next screen snapshot when I tried to register that Standard MBean.

As the screen snapshot above indicates, not following the Standard MBean convention of naming the implementation identically to the interface sans the "MBean" suffix leads to a NotCompliantMBeanException with the message that the particular non-conforming implementation class "does not implement DynamicMBean, neither follows the Standard MBean conventions" and "is not a JMX compliant Standard MBean." The fact that we don't see this same error message for the Status2 implementation of StatusMXBean demonstrates that the MXBean naming conventions are looser than those for Standard MBeans.

Related to the last point, another potential advantage of the MXBean over the Standard MBean is that an MXBean implementation class can be in a different package than its defining MXBean interface. I'll not demonstrate it here, but Eamonn McManus explains in this JMX forum thread that MXBean does not have some of these restrictions that the Standard MBean has.

The looser naming convention and packaging structure of the MXBean can be nice advantages for certain situations, but I still have not demonstrated what is likely to be the biggest advantage most JMX developers enjoy with an MXBean. To see this advantage, it is now time to access the Standard MBean and MXBean shown above remotely.

The following class shows the registration of the Standard MBean and the MXBean with the MBeanServer. This class looks much more difficult than it really is. Most of the lines in the class are the handling of the checked exceptions thrown by the various calls and by the import statements for those exceptions. This class (SimpleMBeanServer) instantiates the Standard MBean and the MXBean and registers both with the MBean server.

With the server code written and running so that it is exposed to remote clients, it is time to turn to the client. We'll start with the readily available JConsole and then use our own client. The next couple of screen snapshots demonstrate how the Standard MBean's status (StatusEnum) is handled differently than the MXBean's status (also a StatusEnum). The first screen snapshot shows the JConsole display of the Standard MBean status attribute and the second screen snapshot demonstrates the JConsole display for the same status via the MXBean.

Standard MBean Enum Attribute Not Available

MXBean Enum Attribute Displayed Correctly

The most important difference in the above two screen snapshots is that the MXBean's attribute's value is correctly displayed, but the Standard MBean's enum attribute value is "Unavailable." Also note that JConsole provides additional details regarding the MXBean attribute type in the Descriptor section. This demonstrates another advantage of the MXBean.

We'll now move on to a custom client and call it SimpleClient. As with the server code, the checked exception handling and associated import statements make the functionality appear at first glance to be more complicated than it really is.

One of the more interesting highlights of the custom client is the use of the methods JMX.newMBeanProxy and JMX.newMXBeanProxy. As these names imply, there are versions of these methods for creating proxies on the client side for both standard MBeans and MXBeans. Underneath the covers, these methods seem to turn around and call the MBeanServerInvocationHandler.newProxyInstance method that I used for client-side proxy support in a previous blog entry. While the MBeanServerInvocationHandler.newProxyInstance approach works just fine, the JMX.newMBeanProxy approach tends to be a little easier to use and is a nice Java SE 6 addition to JMX.

With some knowledge of the MBean interface available on the client side, both the Standard MBean and the MXBean work well. This is demonstrated in the next screen snapshot which shows the results of running the custom client and seeing the correct returned values for both the Standard MBean and the MXBean.

The JMX Best Practices document recommends using the Standard MBean interface where possible because of its increased usability (including easy Javadoc support and client-side proxies). While this JMX Best Practices document does reference MXBeans, it was written before they were available for custom MXBeans and it is probably safe to say that MXBeans could be substituted for Standard MBeans in any recommendation regarding use of Standard MBeans. In other words, because MXBeans provide the same usability advantages as Standard MBeans with the additional client-size data type flexibility, developers using Java SE 6 or later will likely want to consider the MXBean as their first option when writing new JMX MBeans.

Java SE 6 built on J2SE 5's JMX support and added several nice new features. Some of these that were highlighted in this blog entry include support for custom MXBeans and the introduction of JMX.newMBeanProxy. Other Java SE 6 advantageous additions include the much-improved JConsole and removal of the need to specify -Dcom.sun.management.jmxremote for local JMX access (thanks to the JMX Attach API). Mandy Chung's blog provides a comprehensive list of Java SE 6 JMX enhancements. MXBeans and other Java SE 6 enhancements to JMX make Java Management Extensions easier than ever to use.

For my example, I'm running the simple sample server that is bundled with the JSR-262 reference implementation. There is an Ant build.xml file included in the jsr262-ri\samples\simple\server directory that can be run without options to start the server portion. The next screen snapshot shows this:

As I did for running the JSR-262 reference implementation simple sample server, I'm going to use the Command Shell for running the winrm client side portions. It is vital in Vista that you start this shell as an administrator. Running Command Shell as an administrator is demonstrated in the next screen snapshot and is done by right-clicking on a shortcut for the Command Shell and selecting "Run as administrator."

For the client side, it is necessary to configure winrm by using the winrm qc (or winrm quickconfig) command. This and three other commands that should be run to configure winrm properly for the example are spelled out in the "Windows Vista WinRM Set up" section of the JMX Interoperation with Non Java Technologies document.

While in the JMX Interoperation with Non Java Technologies document, refer also to the section "Extras - WinRM Command Line Tool Examples" (toward the end). This section contains many direct winrm (no VBScript required) commands that can be run against the simple server started earlier. This is an easier way to see winrm work as a WS-Management implementation with the JMX Web Services Connector than trying to use VBScript (though the document contains VBScript code snippets as well).

One of the highlighted "extra WinRM Command Line Tool Examples" is the command to obtain MBean Server domain names. It is as follows:

This can appear a little cryptic when not used to winrm syntax. A good starting point for learning to use winrm is its usage information. You can get usage/help information by entering winrm -? (or winrm help) at the command-line. This shows, for example, that the get command used above could also have been expressed as simply “g” and is used for getting or retrieving management information. Likewise, the invoke or “i” is used to execute an operation on the managed resource.

To get more information on the get command, one can enter winrm help get and the usage displayed shows that a RESOURCE_URI should be passed to the get command.

In the example above, there is a clause –fragment://:Domain. The command winrm help switches provides more details on this. The help for –fragment:VALUE tells us that this option is used to specify a portion of the instance XML file. In this case, the value is //:Domain which corresponds to any Domain element in the XML structure (the // is XPath syntax for recursive search and : is XPath syntax for namespace separator).

The winrm help remoting command tells us what the –r option (or –remote) option does. The –r:VALUE command specifies the remote endpoint. As used in the example above it is a URL consisting of four pieces: transport, host, protocol, and prefix.

The final option in the command above is –a:None. The –a (or –authentication) option is used to specify the authentication mechanism used and is None in this example, but could have been Basic, Digest, Negotiate, or Kerberos. More information on the authentication mechanism can be found using the command winrm help auth.

Another useful winrm command that can be used against the JMX Web Services implementation allows us to retrieve the ObjectNames of all registered MBeans:

Some of this is the same as the previous command analyzed here. The –r (remote) option takes the same URL as before and the –a:None indicates that we don’t want any authentication employed for this example.

A difference in this example from the last one is the use of enumerate instead of get. Using winrm help enumerate provides information on its usage and explains that this option allows application of a filter to the returned results. In this case, one of enumerate’s options (-returnType=VALUE) is set to EPR which means that only end point references (applicable Resource URI and selectors) are displayed. The other two objects are object form (hierarchical presentation of object values) or ObjectAndEPR (a combination of the other two).

I'll show the full output of the most concise of these return types (EPR only) here:

The object version and object+EPR versions are significantly longer than this and I won't show them here.

So what's the big deal about all of this? The big deal is that this demonstrates the use of a non-Java client (in this case Windows Vista winrm) to access Java Management Extensions on the server. With the JMX Web Services Connector, you no longer need a Java-based client to monitor and manage JMX-instrumented resources (including the JVM itself)!

For my example, I am only demonstrating one "server side" of the remote JMX example. I am using Spring to implement this server-side portion of the JMX RMI Connector because Spring makes it much easier. However, everything implemented here for the server side can be implemented without Spring. There is not as much difference in implementation details for the client side, so I will show examples both using and not using Spring on the client side.

The common JMX server-side code for my example is contained in three Java class files (a main executable class, a Spring-exposed bean class, and an interface that the Spring bean implements) along with a Spring XML configuration file. These four files constituting the server-side of the application are shown next.

As you can see in the code above, most of the work for exposing a simple bean as a JMX MBean is done in Spring's XML configuration (the first file listed). In that XML configuration file, the JMXServiceURL is highlighted in blue because this same URL will be needed for the client-side code, which is shown next.

The first type of client I'll demonstrate is a "straight JMX" client that does not use the Spring Framework. It does not matter that the server, as shown above, was ultimately implemented via the Spring Framework. The client can be run with or without Spring and I'll show both here.

ClientMain.java (Only Class Needed for JMX Client without Spring)

Because Spring is not involved, there is no XML file for configuration. To simplify things, I stuffed all of the client side functionality into a single class called ClientMain whose code listing is shown next.

There is no Spring used in the code above. However, the code above does show how with regular JMX client-side code, one can connect to a JMX agent remotely either using direct reflection (ClientMain.demonstrateClientJmxWithoutProxy(MBeanServerConnection,ObjectName) method) or using a proxy (ClientMain.demonstrateClientJmxWithProxy(MBeanServerConnection,ObjectName) method). The main(String[]) function of this class performs all of the functionality required to connect to the JMX Server without Spring's help. This includes instantiating the JMXServiceURL and acquiring the JMXConnector to ultimately acquire an MBeanServerConnection. The MBeanServerConnection is required to connect to the JMX agent remotely whether direct reflection or proxies are used. To obtain this MBeanServerConnection, three checked exceptions must be handled.

To see how much easier it is to use a proxy as compared to direct reflection, one need only compare the lines of code in the method ClientMain.demonstrateClientJmxWithProxy (proxy) to the lines of code in the method ClientMain.demonstrateClientJmxWithoutProxy (direct reflection). The direct reflection approach requires handling of four checked exceptions compared to none required for the proxy approach. Also, as the number of operations desired to be run against a particular remote MBean increases, the additional complexity of the reflection approach becomes greater compared to the proxy approach.

The above single class demonstrated how one can access a remote JMX agent from a client. I'll now move onto how to accomplish the same functionality, but will take advantage of the Spring Framework on the client side this time.

My JMX Client assisted by Spring example has three files. The three files are the main Java class that bootstraps the Spring container, the Spring bean that interacts with the MBeanServer with direct reflection and with proxies, and the XML configuration file for the client application's Spring context.

spring-client.xml (XML Configuration for Client-side Spring Container)Note that this XML file is much simpler than that used for the JMX server side.

Finally, note that the "common" features of the JMX MBeanServer (default domain, hosted MBean count, etc.) can be obtained directly from the MBeanServerConnection and therefore the decision whether to use proxy or direct reflection does not apply to those calls. Rather, one must decide between proxy or direct reflection when operating on remotely hosted MBeans themselves (not the host).

The above example of a JMX client with Spring's assistance demonstrates that one thing that Spring provides on the JMX client side is the ability to inject an MBeanServerConnection into the code via Spring's container and wiring. Once the MBeanServerConnection is obtained, everything else associated with accessing a remote JMX agent is essentially the same in the above example. Like the non-Spring client example, the Spring-assisted client accesses the server side both using reflection and using proxies. The proxy approach is essentially the same as for the non-Spring client shown earlier just as the reflection approach is also essentially the same for a Spring-assisted approach as for a non-Spring JMX client.

However, Spring can do even more for us on the client side using a proxy. Instead of using the MBeanServerInvocationHandler.newProxyInstance, we can configure Spring in its XML configuration file to inject the proxy into the code. This allows us to make the client side access of the remote JMX MBean even easier. The method for accessing the remote object now simplifies to this:

/** * Demonstrate accessing remote JMX agent via RMI and via a client-side proxy * with Spring injecting the proxy so that it does not need to be provided as * a parameter. */ public void demonstrateClientJmxWithProxyInjected() { System.out.println( "PROXY (Spring-injected) Says: The Status is " + this.status.getStatus() ); }

As the simple code listing above demonstrates, it is really easy now to access the remote MBean. In fact, this code shows no obvious signs that an MBean is being accessed remotely. To make this work, a data member was added to the class to store the status and it was injected via Spring using the additional XML snippet shown next:

When used to its full extent, Spring allows for the configuration and injection of both the MBeanServerConnection and the proxy to the remote MBean to be implemented via XML and removed from the code. This greatly simplifies the client-side code.

The conclusion from all of this is that whether using Spring for your JMX client or not using Spring for your JMX client, the use of proxies is generally simpler and safer than using direct reflection. It is not surprising, therefore, that the JMX Best Practices recommend using proxies for the client-side access of remote JMX MBeans.