Friday Oct 24, 2008

Early Access 4 of the Web Services Connector for JMX is out

You can download it from ws-jmx-connector.dev.java.net.

The changes since the early access 3 are detailed in the release notes.

The major improvement is related to the JMX-to-XML mapping of CompositeData and TabularData. We have defined a much more compact representation that makes exchanged messages up to 3 time smaller.

To better address non Java clients we have added a taglet to help you generate the information that a pure WS-Management client would need to interoperate with your JMX application. An example of this taglet usage is provided. It covers all the tasks required to make VBScript to interoperate with an MBean, from MXBean interface development and documentation to VBScript writing.

In addition, a set of new VBScript samples provide some concrete examples of interoperability.

You can send us your feedback on users@ws-jmx-connector.dev.java.net

Regards

Jean-Fran├žois Denise

Friday May 23, 2008

Use VBScript to cheat at poker with JMX!

This year at JavaOne Eamonn and I presented during our technocal Session, where we stand with respect to JMX. Eamonn covered JMX in general and JMX 2.0, while I covered the Web Services Connector for JMX. At the end of the talk, we performed a demo named “CSPoker, JMX Technology, Java VisualVM and WinRM at the JavaOne Tournament's Final Table”. We linked together a set of JMX related technologies to offer, in an original Online Poker Web Site use case, an interesting setup highlighting the power of JMX (here's a PDF file of the demo architecture) .

At the end of the talk, some people asked me some questions about the WS-Management access to JMX we had just demonstrated. More details on the WS-Management to JMX interoperability can be found in this article.

Here, I am providing some details on the actual script used during the demo. This script automates the Poker Engine monitoring and management tasks. It first registers to listen for JMX Notifications exposed as WS-Eventing notifications. Each time a “Poker table joined” notification is received, it checks that the IP address from which the player joined is not already known to the system. If an IP address is already known, it means that another user already joined from the same host.... which is very bad if you want to avoid the same player using multiple identities....

When such a “bad user” is detected, the script ejects all the players that joined from that machine.

Intialisation of the WS-Management access

dim wsmanObj
set wsmanObj = CreateObject("WSMAN.Automation")
dim objConnectionOptions
set objConnectionOptions = wsmanObj.CreateConnectionOptions
dim iFlags
iFlags = wsmanObj.SessionFlagUseNoAuthentication
dim session
set session = wsmanObj.CreateSession("http://localhost:8080/admin", iFlags)

At this point, you have a WS-Management proxy (the session object), that allows you to interact with a JMX Agent attached to the Web Services Connector.


Subscription to the MBean notifications

The MBean we want to subscribe to is named : cspoker:type=CSPokerControl

Because the WS-Management session doesn't offer a nice API for subscriptions, we need to construct the subscription invocation request using the “all purpose” invoke method :


Dim reply
reply = session.invoke("http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe", _
"http://jsr262.dev.java.net/DynamicMBeanResource?ObjectName=cspoker:type=CSPokerControl", _
"<wse:Subscribe xmlns:wse='http://schemas.xmlsoap.org/ws/2004/08/eventing'>"_
& "<wse:Delivery Mode='http://schemas.dmtf.org/wbem/wsman/1/wsman/Pull'/></wse:Subscribe>")

At this point we have sent a WS-Eventing subscription request (in PULL mode, meaning that the client will send a request to pull notifications from the server) and received a response. The response contains the WS-Eventing context to be used to retrieve notifications.

Retrieving the Eventing context

To get the eventing context from the response, we need to make use of the VBScript DOM library : Microsoft.XMLDOM

Warning : Because namespaces are not handled well in this DOM library, we are trying to discover the Namespace prefix based on our knowledge of the way they are declared (ns<i>). I am not a VBScript expert and would be very interested to know if there is an equivalent to getElementsByTagNameNS using VBScript???

Function findElement(elem, tagElem)
' wscript.echo "Finding Element " & tagElem
 for i = 0 to 15
  set findElement = elem.getElementsByTagName("ns"& i &":" & tagElem)
  If findElement.Length > 0 Then Exit For
 next
End Function

Dim objXMLDoc
set objXMLDoc = CreateObject("Microsoft.XMLDOM")
objXMLDoc.async = False
objXMLDoc.loadXML(reply)

' Get the Eventing context to use in the next WS-Eventing Pull request
Dim nodeList
set nodeList = findElement(objXMLDoc.documentElement, "EnumerationContext")
dim context 
context = nodeList(0).text
wscript.echo "Subscription Enumeration Context " & context

At this point, the context variable contains the WS-Eventing context that identifies our subscription. This context is to be used to retrieve notifications.

Retrieving the Notifications

This is done by sending a Pull request to the server and providing it the context. The pull request blocks until some Notifications are emitted or the timeout (1 minute by default) is reached. As for subscribe requests, no Pull API is offered. We need to use the general purpose invoke operation. We have written a pull function that handles pull request timeouts properly. When the timeout occurs, instead of exiting the script, the error is trapped and the script continues. Because we expect multiple notifications, the Notification pulling is done in a loop.

Function pull(session, context)
 On Error Resume Next
Dim pullXml
pullXml = "<wsen:Pull xmlns:wsen='http://schemas.xmlsoap.org/ws/2004/09/enumeration'><wsen:EnumerationContext>" & context & "</wsen:EnumerationContext><wsen:MaxTime>PT1M0.000S</wsen:MaxTime><wsen:MaxElements>1000</wsen:MaxElements></wsen:Pull>"
 pull = session.invoke("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull", "http://jsr262.dev.java.net/MBeanNotificationSubscriptionManager", pullXml)
  On Error Goto 0
End Function

' This piece of script is called in an infinite loop

Dim notifs

 notifs = pull(session, context)

At this point, the notifs variable contains (or does not contain, if the timeout occurred) the JMX notifications in an XML format.

Extracting the Notification content and tracking the cheat

We only do this extraction if the list of notifications is not null. The VBScript DOM library is again used to parse the notifications. Because a pull request can return multiple notifications, we must iterate on all TargetedNotification elements contained in the notification list. A TargetedNotification is an XML representation of a JMX Notification defined by the JSR 262 (JSR in which the Web Services Connector is defined).

In our case, the TargetedNotification/Message XML Element contains the Player name. The TargetedNotification/UserData XML Element contains the IP Address as a string (eg:<jmx:String>192.168.0.1</jmx:String>)

To keep the IP <==> Player relationship, we use a Map data structure and array. In VBScript, we use a dictionnary (scripting.dictionary Libray)

' Create a Map
dim dict
set dict = CreateObject("scripting.dictionary")
Dim ipArray(10)
Dim arrayIndex
arrayIndex = 0

if Not(isNull(notifs)) then

  set objXMLNotif = CreateObject("Microsoft.XMLDOM")
  objXMLNotif.async = False
  objXMLNotif.loadXML(notifs)
  set NodeListNotifs = findElement(objXMLNotif.documentElement, "TargetedNotification")
  WScript.echo "Pull returned " & NodeListNotifs.length & " notifications"

  ' Now that we get the list of notifications, extract the content.
  Dim i
  Dim EventType
  Dim msgObj
  ' Loop over the received Notifications
  For i = 0 To NodeListNotifs.length - 1
      Dim listMsg
      set listMsg = findElement(NodeListNotifs(i), "Message")
      Dim eventMessage 
      eventMessage = listMsg(0).text

      Dim listUserData
      set listUserData = findElement(NodeListNotifs(i2), "String")
      ' We have an IP address
      if(listUserData.length > 0) then
           Dim ipAddress
           ipAddress = listUserData(0).text
           wscript.echo eventMessage & " Joined From " & ipAddress
           if dict.exists(ipAddress) then
              Dim prev
              prev = dict.item(ipAddress)
              if Not StrComp(prev,eventMessage) Eqv 0 Then 
                 dim users
                  users = Array(eventMessage, prev)
                  For Each user In users
                    wscript.echo user & " already connected from same host [" & ipAddress &"], will eject him." '"Type return."
                    wscript.echo "Ejecting player " & user
                    ejectPlayer session, user
                    wscript.echo "Player " & user & " ejected"
                  Next
              end if
           else
             dict.add ipAddress, eventMessage
           end if
      else
         wscript.echo eventMessage
      end if
  Next

Ejecting the player

The function ejectPlayer calls the ejectPlayer MBean operation by making use of the general purpose invoke operation.

Function ejectPlayer(session, playerName)
 dim pokerURI
 pokerURI = "http://jsr262.dev.java.net/DynamicMBeanResource?ObjectName=cspoker:type=CSPokerControl"
 dim xmlInvoke
 xmlInvoke = "<jmx:ManagedResourceOperation name=" & Chr(34) & "ejectPlayer" & Chr(34) & " xmlns:jmx=" & Chr(34) & "http://jsr262.dev.java.net/jmxconnector" & Chr(34) & "><jmx:Input><jmx:Param><jmx:String>" & playerName & "</jmx:String></jmx:Param></jmx:Input></jmx:ManagedResourceOperation>"
 session.invoke "http://jsr262.dev.java.net/DynamicMBeanResource/Invoke", pokerURI, xmlInvoke
End Function


Hope that these VBScript extracts helped you understand better how you can use this path to interoperate with JMX.

Thanks.

Jean-François Denise

jfd@sun.com




        
    

Thursday Mar 13, 2008

RESTful Access to JMX Instrumentation, Via URI-fication of MBean Attributes

As you perhaps know from reading my posts, I am involved in the definition of JSR 262, Web Services Connector for JMX Agents. JSR 262 offers an access to Web Services that is very far removed from Representational State Transfer (RESTful) Web Services. So, this blog is not about JSR 262, but instead it describes some of the investigations and development I have performed related to the Java API for RESTful Web Services (JAX-RS API) and the JMX API.

Having simple HTTP-based access to a Java Management Extensions (JMXTM) MBean is an idea that I like a lot and one for which I think that there are thousands of real use cases. For example, when developping a Web application, integrating a piece of information obtained from JMX instrumentation, such as the status of a service, should be as simple as loading an HTML page.

My first attempt was to define and implement a merge of JSR 262 and a RESTful approach... All in vain! The two technologies cannot co-habit, so you are forced to choose between them. You either have to go down the WS-\* path or you have to go down the RESTful path. There's no way to make one leverage the other to offer a tidy solution. In this case, keeping the two parts separate is much better than trying to bundle them together. In this investigation, I have limited the scope just to retrieving information from JMX instrumentation. Setting MBean attributes or invoking operations has not been addressed (yet).

June 2008. UPDATE TO THE ORIGINAL ENTRY. I added description for support of notifications and snapshot of values in this new entry.

If you want to play with this prototype for RESTful access to JMX instrumentation (based on Jersey, which you will need to download) before reading the blog entry, you can jump straight to Running the Adaptor. This RestFul JMX Adaptor is hosted by the OpenDMK java.net project.

But first, let's start with a bit of background. The next sections describe how the information from JMX instrumentation is accessed, and how this information can then be mapped into a format that is acceptable to the RESTful approach.

JMX Instrumentation Information Tree

So, how does JMX instrumentation present its information? First, we have an MBean server in which MBeans are registered. Each MBean contains a set of attributes that represent an actual piece of information. MBean attributes are not always exactly actual pieces of data, though, as this is dependent upon the Java class of the attribute. If the attribute is a primitive type, then yes, the attribute is indeed an actual piece of data. If it is a complex type (or a collection), then it is not. Complex types need to be traversed to discover the actual data.

So, we can represent the whole set of information exposed by the JMX instrumentation as a tree. The root of the tree is the MBean server, the MBeans are the root's child nodes and the attributes are the MBeans' child nodes. Some attributes are terminal nodes (primitive nodes), some other attributes (complex types) are intermediary nodes.

The following figure presents the JMX instrumentation information tree:


In this tree, we can see the data path as leaves.


Here, we can identify three elements:

  1. The leaf node, which is a data container.

  2. The intermediary node, which is a child container.

  3. The data path, which is composed of the set of parent/child relationships from the root to the leaf.

Traversing Complex Types

We just saw that you need to traverse complex types to access the actual data. However, how to deal with every sort of complex type that can be defined is outside the scope of these investigations. So, we have limited ourselves to Array, List, Set and the generic JMX types CompositeData (which is very similar to Map) and TabularData (which is a table of CompositeData).

The above list of types complies with MXBean usage, so we are able to go quite far, even with this limited set. These types are traversed in different ways, as follows:

  • To traverse a List or an Array, you need to iterate the structure.

  • To traverse a CompositeData, you need to find out each key and retrieve the associated value.

  • To traverse a TabularData, you need to iterate the structure and then traverse each CompositeData (as described above).

Mapping the Information Tree to RESTful Web Services

I am not making a revolutionary statement by saying that nodes are resources and data paths are URIs. In our information tree, we have two kinds of resources, container resources that are referenced by other resources, and the content resources. These resources can be identified by URIs, as explained in the next sections.

Resource URIs

The different resources in our information tree are identified by the following URIs:

  • MBean server: http://<host>:<port>/<root context>

  • MBean: http://<host>:<port>/<root context>/<MBean ObjectName>

  • MBean attribute: http://<host>:<port>/<root context>/<MBean ObjectName>/<attributeName>

  • Collection (list or array) element: http://<host>:<port>/<path to complex type>/<index>

  • Map element: http://<host>:<port>/<path to complex type>/<URL encoded(key.toString)>

  • CompositeData entry: http://<host>:<port>/<path to complex type>/<key>

  • TabularData element: http://<host>:<port>/<path to complex type>/<index>

Container Resources

MBean servers, MBeans, arrays, lists, sets, CompositeData entries and TabularData elements are all container resources. A simple XML definition is enough to represent these resource types. To avoid defining a new XML element, we can reuse the XHTML list element (<ul><li></li></ul>).

References to a child can either be relative to the current resource or absolute. I chose to make them absolute. Below are some examples of representations of different container resources.

  • MBean server containing two MBeans:

    <ul>
    <li>http://<host>:<port>/<root context>/java.lang:type=Memory</li>
    <li>http://<host>:<port>/<root context>/java.lang:type=Thread</li>
    </ul>
  • MBean with two attributes, NonHeapMemoryUsage and HeapMemoryUsage:

    <ul>
    <li>http://<host>:<port>/<root context>/java.lang:type=Memory/NonHeapMemoryUsage</li>
    <li>http://<host>:<port>/<root context>/java.lang:type=Memory/HeapMemoryUsage</li>
    </ul>
  • CompositeData, composed of commited and init keys:

    <ul>
    <li>http://<host>:<port>/<root context>/java.lang:type=Memory/NonHeapMemoryUsage/commited</li>
    <li>http://<host>:<port>/<root context>/java.lang:type=Memory/NonHeapMemoryUsage/init</li>
    </ul
Note: You will notice that I am not using the HTML link tag (<a href="..."></a>). This is because I am not defining HTML access (such as that provided by the JMX technology's HTML adaptor), but rather XML access.

Container resources like those above are not of particularly great interest to us. They help with navigation when you are having difficulties finding your way through the information tree, but when you know where you want to go, they are almost useless. When you know where you want to go you don't need to navigate at all, you just jump at light speed to the end of the path by providing the full URI.

However, in some cases where the information is dynamic, container resources can be really helpful.

Content Resources

In this prototype, actual data is represented by straightforward plain text. For example, Hello world, is plain text...

A Restful Adaptor for JMX Instrumentation

I have developed a prototypal implementation of the above mapping using the JAX-RS Reference Implementation (a.k.a the Jersey project). The adaptor attaches to the platform MBean server that is located inside any Java Virtual Machine (JVMTM) from Java Development Kit (JDK) version 5.0 or above. The adaptor offers URI-based navigation, and the returned pages are in either HTML or XML format, according to the receiving client's "Accept Headers" setting.

The current prototype covers all the types exposed by the JVM software's MXBean interfaces (used for monitoring memory, threads, classes, etc.). If your MBeans are also MXBeans, they you should be able to navigate to them without problems. I re-used the HTML <ul><li> tags to handle lists in XML. In HTML, the <a href="..."> tag is used in conjonction with the <li> tag in order to make clickable URLs.

The adaptor provides an API (JMXWSMBeanRestResource#setListXMLTags) that allows you to change these list tags and provide your own.

If your MBeans expose unsupported types, you can provide your own resources by calling JMXWSMBeanRestResource#registerResourceHandler. Look at the source code for JMXWSMBeanRestResource.CollectionResource to understand how the adaptor's JAX-RS resources are defined.

JAX-RS Resources

JAX-RS allows you to define “top level” resources that return sub-resources. I defined a top level resource named JMXWSMBeanRestResource, which serves as the JMX adaptor's entry point and handles the MBean server and the MBean resource types. It also delegates the navigation of attribute values to sub-resources. The current sub-resources are the following:

  • PlainResource

  • ArrayResource

  • CollectionResource

  • MapResource

  • CompositeResource

  • TabularResource

Each resource handles a data type and, in turn, delegates it to other sub-resources to reach the leaf (the plain text resource).

The JAX-RS resource / sub-resource pattern allows for very simple tree navigation. Each resource is annotated using JAX-RS annotations. The following ArrayResource shows what a sub-resource actually does:

public class ArrayResource { 

/\*\* Returns the list of URI that point to array items. \*\*/

@GET

@ProduceMime("text/xml")

public Response getXMLItemURIs() throws Exception {

return getURIs();

}

/\*\* Returns the Sub resource pointed by the array index. ResourceFinder is a reference to the JMXWSMBeanRestResource that manages Sub Resources. \*\*/

@Path("collection/{index}")

public Object getItem(@UriParam("index") String index) throws Exception {

int idx = Integer.valueOf(index).intValue();

return resourceFinder.findResource(Array.get(array, idx));

}

...

}

That's about it for the introduction. Now you can see the adaptor in action.

Running the adaptor

  1. You need first to do a CVS checkout of the Restful Adaptor sources from OpenDMK java.net project

    1. export CVSROOT=:pserver:guest@cvs.dev.java.net:/cvs

    2. cvs co opendmk/contributions/rest-adaptor

    3. Open the NetBeans project rest-adaptor/RestAdaptor.

  2. Follow the steps documented in Restful Adaptor readme file.

  3. Run the adaptor (this requires a minimum of JDK version 5.0, although JDK 6 is recommended).

  4. The adaptor will display the URL on which it is bound, as well as some other information, such as the composition of the URIs and the names of the MBeans.

  5. In your browser type the following URL : http://localhost:9999/rest/jmx.

  6. If your browser is set to accept XML headers by default over HTML headers (as is the case for Firefox), you will receive the resources in XML form, which is not really the best form for a browser. However, you can still navigate by copying and pasting the URIs until you reach a leaf. The best thing to do is to change your Firefox settings to accept HTML headers by default over XML headers, as follows:

    1. In your browser, type about:config

    2. Go to network.http.accept.default

    3. Prefix the value with text/html.

    You can now navigate from the root to the leaves.

But, as I said previously, navigation is really not the best way. What you really want to do is to jump to a value using a well-known URL. But where are these well known URLs? They are there already, waiting for you. If you want to see them all, go to the following URI:

http://localhost:9999/rest/jmx/all

This URI references a special resource that lists ALL the leaves of a JMX information tree for a given MBean server. All listed URLs identify an actual piece of data.


This list of URLs (that can be very long) can be filtered by using a URI parameter that contains the following JMX specification ObjectName pattern: http://localhost:9999/rest/jmx/all?pattern={your jmx ObjectName pattern}

Well Known URLs

In a system being managed by JMX instrumentation, the set of exposed MBeans is generally well defined. The set of MBean ObjectName instances is well known and documented so that clients can access the exposed information. We can take advantage of this and select a set of URLs that will never change for a given system. For example, the URIs that identify the commited heap memory of the JVM software from JDK version 5.0 or version 6 will never change, except for the host and port deployment information, as shown below :

http://<host>:<port>/rest/jmx/java.lang:type=Memory/NonHeapMemoryUsage/commited

This file contains the URIs you expect to find in a JVM implementation from JDK version 6, regardless of your context. For monitoring and management of the JDK software, the URLs that change are related to Array and TabularData (i.e. thread IDs, system properties, logger names, etc.) and to memory managers that are not identical as far as the hardware architecture is concerned.

You can easily discover these URLs without navigating through the tree, by starting at index 0 and incrementing by 1 until you reach a 404 error. For example, to retrieve all the thread IDs, you just have to increment the {index} :

http://<host>:<port>/rest/jmx/java.lang:type=Threading/AllThreadIds/{index 0-N}

The example of thread IDs shows up a major limitation of this approach when the information is very dynamic (as threads are). The array size and elements can change in such a way as makes the returned values invalid. In this case we would need a snapshot of the array.

June 2008. UPDATE TO THE ORIGINAL ENTRY. I added description for support of notifications and snapshot of values in this new entry.

Conclusion

This RESTful adaptor provides a possible way of implementing a RESTful access to JMX instrumentation. I have a strong feeling that it could be very helpful when aggregating loosely coupled pieces of information. The current adaptor does not address all data structures (although MXBeans are fully handled), but it is provided in Java source code and offers an API for you to add your resource handlers.

Possible usages:

  • Develop AJAX based dashboads to monitor Java VM and/or your applications.

  • Quickly construct HTML pages to offer human readable access to the internals of your systems.

What are the next steps:

  • Add a support for Notifications.

  • Add a support for POST/PUT.

  • Add a support for snapshot of values.

I would like to thank Paul Sandoz for is great help. REST philisophy is Paul's second nature. Expose him your problem and he will Restify it. Really smart!

I would be very happy to receive any feedback about this approach. Feel free to contact me and thank you for reading.

Regards.

Jean-François Denise

Monday Feb 18, 2008

Web Services Connector for JMX enters Public Review

The JSR 262 has just entered the Public Review phase. The Early Access 3 of the Connector, that implements the Public Review, can be downloaded from http://ws-jmx-connector.dev.java.net.

Specification changes since Early Access 2:

  • PUSH mode supported for notifications. This is specified in the client by including JMXWSDefinitions.JMX_WS_NOTIFICATION_PUSH_MODE_URL in the Map given to JMXConnectorFactory.connect. Some related Map entries on the client and server configure security. A new interface JMXWSCredentialsProvider specifies how the connector server gets the credentials it needs to connect to any given client and push notifications.

  • New JMX types supported for MBean operations: NotificationResult, NotificationFilterSupport, AttributeChangeNotificationFilter, MBeanServerNotificationFilter. This allows the JSR 262 connector to support the new Event Service being defined by JSR 255, which has MBean operations that use those types. We also added support for java.lang.Enum and java.util.Set.

  • Connection identifiers supported consistently with the JMX Remote API (JSR 160) specification. This was already alluded to in the Early Draft 2 but is now formalized consistently.

  • Removed the interface JMXWSManResourceHandler. This was a halfway house between the Connector and Adaptor models. The model now is that for a Connector (client sees the JMX Remote API), the protocol is completely specified and invariable.

  • Some minor reshuffling of static final fields between JMXWSConnectorServer and JMXWSDefinitions.

  • The getMBeanInfo operation is now mapped as a Custom Action. Previously the MBeanInfo was a property of the MBean resource, alongside all the attributes of the MBean. This mix of data and metadata was strange.

  • JMXAuthenticator.authenticate method. The passed Object parameter used to be a String[2]. It is now a String[3]. The third element contains a client certificate in case HTTPS Mutual authentication is enabled (null otherwise).

  • XML Element NotificationLost has been removed from the schema. WS-Management already offers such definition by the mean of DroppedEvents XML element. NotificationLost was a redundant redefinition.

  • The schema has been updated, mostly to reflect the changes above, and some minor refactoring.

Implementation changes since Early Access 2:

  • Leverage of the Metro stack components (as detailed in my previous blog entry) in order to increase interoperability and efficiency of the Connector. We are currencly observing a \*3 increase in performance.

  • Rely on the latest JAX-WS 2.1.3 release.

  • Introduction of an adaptor API that allows you to change the way MBeans are exposed in the WS-Management world (javadoc is bundled in the Early Access 3 auto extractible jar under docs directory).

The document that covers interoperability with Microsoft WinRM tooling (winrm command line, VBScript API and Event Viewer support for WS-Management events) has been updated in order to reflect the Public Review changes.

Feedbacks on the specification can be sent to jsr262-spec-comments@sun.com. Feedbacks on the connector implementation can be sent to users@ws-jmx-connector.dev.java.net.

Thanks.

Jean-Francois Denise

Monday Feb 11, 2008

Up the Metro stack to JMX Technology: A Wise Man's Journey

Up the Metro stack to JMX Technology: A Wise Man's Journey


What a long trip... We started by driving on the HTTP highway, slid on SOAP, turned left at the XML crossroads, passed over the WS-Addressing bridge, visited WS-Enumeration, WS-Eventing and WS-Transfer, got a bit lost in WS-Management country, discovered that JMX was not so far off, and finally took a rest (but not a RESTful one) in the Web Services Connector... Did we do all that on our own? No, we did it with a set of friends, the Metros, or the high-performance, extensible, easy-to-use web service stack.


OK, I guess you get it. This little journey lists the set of standards that have been pressed into service to expose JMX MBeans as WS-Management resources. Luckily we didn't have to implement them all. The JAX-WS (a core Metro component) and WiseMan (a WS-Management Java implementation) projects have been of great help.

Now Sun has announced that the WiseMan project is to become part of the Glassfish community. So, it seems to be an appropriate time to look at how the Web Services Connector for JMX Agent RI makes use of WiseMan and Metro.


In this article, I will describe how we changed WiseMan to use part of the Metro stack, what the benefits were, and finally how these technologies are leveraged in the Web Services Connector for JMX Technology

Moving WiseMan to the Stack

In 2007, some significant engineering tasks were undertaken in the WiseMan project to bring the benefits of Metro to WiseMan. This section outlines the steps that were needed to make this move a reality.

The details of this technology switch are of interest to anyone who wants to make their existing applications benefit from Metro's features.

From Servlet to JAX-WS 2.0

WiseMan, was, in its pre-1.0 release, closely coupled with Servlet. At the time, Servlet container was the only way to deploy a WiseMan-based application. We decided to add a JAX-WS Endpoint to the WiseMan project and suddenly we found we could be much more agile. Deployments like the Java SE and Java EE platforms became possible. What a change! For example, being able to base our test suite on the lightweight HTTP server bundled with JAX-WS made our lives much easier...

The JAX-WS Endpoint we developed is a Provider<SOAPMessage>. Simply annotating with @WebService was not possible. WS-Addressing makes intensive use of SOAP headers to convey part of the protocol information. To access to such headers, we need full access to the SOAP Message. After some redesigning of the existing code we extracted a WSManAgent Class that is accessible from a JAX-WS Endpoint or a Servlet.

We took this opportunity to switch to the JAXB release contained in Metro.

So we were happy and impatient to move forward. We already knew that the JAX-WS team was working on adding WS-Addressing support and were waiting for it eagerly.

From JAX-WS 2.0 to JAX-WS 2.1

JAX-WS 2.1 comes with support for WS-Addressing. It's a very smart integration. By just using annotations, your Endpoint becomes addressable thanks to WS-A.

The @Addressing annotation that you can use to tag your Endpoint implies that the WS-Addressing 1.0 release is to be used. However, WS-Management requires the use of another release of the WS-A standard, which is a great pity. We discovered that we were not able to leverage this support. We were afraid this was the end of the road, but the JAX-WS engineering team came back to us showing us the Metro specific API. We were not the first customer with a dependency on a Membership Submission and they defined another “non standard but supported” Annotation to express our requirement : com.sun.xml.ws.developer.MemberSubmissionAddressing

With this annotation added, we removed all the code related to WS-A request-response headers.

So we were happy...but not for long. Our great friends Yves and Sandra of the JMX QA team started to develop some simple stress tests and we started to discover horrible things...

From SOAPMessage to Message

We discovered that 80% of the time spent handling a request was spent in the DOM/SAAJ layer. That's 80% of some big numbers, too...

You remember? Our Endpoint is a Provider<SOAPMessage>. This means that when called, a SOAPMessage object is injected and a SOAPMessage object is expected as the returned value. So we were either stuck, or we had to re-implement the SOAP layer to rely on the STAX API, or we were left with our disapointing figures.

Could the Metro API solve this issue? Yes, the Metro API solved this issue. Once again we were not the first customer, etc., etc., etc. As a solution, an efficient implementation of SAAJ, that is very well integrated with JAXB, is exposed as the Message API (located in the com.sun.xml.ws.api.message package). In order to benefit from its power, you must completely forget all the development you have done on top of SAAJ and rewrite everything on top of this new API. Which is exactly what we did. OK, we re-designed it to make both approaches live together nicely, but we also designed a new API for WiseMan, that was completely isolated from SAAJ. And things started to work much faster (3 to 4 times quicker). The numbers were becoming acceptable, for this kind of XML based processing.


Current WiseMan Architecture




The diagram above shows the different products that are used to build the WiseMan stack on the client and the server. You can see that the WiseMan client stack doesn't rely on Metro, yet. A work-in-progress aims to define and implement such a move, which will greatly improve performance and ease of use.

Improvements for the WiseMan Project

This move helped the project to:

  • Improve deployability

  • Improve alignment and reuse

  • Improve interoperability

  • Improve performance

Deployability, interoperability and performance are the key words of the Web Services Connector for JMX Technology. Based on these new capabilities, WiseMan is becoming the WS-Man implementation of choice for the Web Services Connector for JMX.

When using this connector you are not directly in contact with the stack but you indirectly benefit from the properties you are interested in.


Web Services Connector for JMX Continues Leveraging Metro

This section looks at how the the Web Services Connector for JMX Technology continues leveraging Metro.

Fast Infoset

- "Increase performance!"

- "Increase performance? Hmm..."

Simple, use Fast Infoset! It comes with the stack, it's efficient, it doesn't break interoperability and it's easy to use. We did it and we experienced another big improvement. To enable Fast Infoset in your client API, access the BindingProvider and provide a Fast Infoset key to the request context. For example:

BindingProvider provider = (BindingProvider) port;

Map<String, Object> requestContext = provider.getRequestContext();

requestContext.put("com.sun.xml.ws.client.ContentNegotiation", "pessimistic");

Dispatch<Message> on the client side.

On the client side of the connector, we use the JAX-WS Dispatch class. A Dispatch instance can be seen as an Endpoint proxy that deals with the complete SOAP Message (as opposed to classical JAX-WS proxies that expose a service level API). Since JAX-WS 2.1, Dispatch also handles WS-Addressing. Using Metro specific API, we are creating an efficient Dispatch that is compliant with the WS-Addressing Membership Submission release.

The following code extract shows how to create a Dispatch<Message> for Membership Submission:

Dispatch<Message> port = service.createDispatch(JMXWSConfiguration.JMX_WS_CONNECTOR_PORT, Message.class, Service.Mode.MESSAGE, new MemberSubmissionAddressingFeature(true, true));

Endpoint on the client side

WS-Management defines a way for a WS-Management Agent to deliver its Events in a PUSH mode. This delivery mode implies that the event sink (the client) is itself an Endpoint. We deploy a JAX-WS Endpoint (Provider<Message>) inside our connector client to receive pushed events.

WS-A EndPointReference API

The JMX Web Services Connector RI exposes a non-standard API to customize the mapping of MBeans to WS-Management resources. In this API, we allow customers to hook their customization as low as the WS-Management protocol itself. We needed a WS-Addressing Endpoint reference to expose.

The JAX-WS class javax.xml.ws.EndpointReference offers a standard 1.0 representation that we are internally translating into a Membership Submission via the Metro API (using the class com.sun.xml.ws.developer.MemberSubmissionEndpointReference).

Security

JAX-WS offers support for HTTP Basic Authentication and HTTPS. We are leveraging both.

HTTP Basic Auth

You provide the credentials to a Dispatcher via the request context. The following code extract shows how to provide your credentials.

BindingProvider provider = (BindingProvider) port;

Map<String, Object> requestContext = provider.getRequestContext(); requestContext.put(BindingProvider.USERNAME_PROPERTY, “user); requestContext.put(BindingProvider.PASSWORD_PROPERTY, “password”);

Server Side Security

The way you secure the server side depends on the container in which the Connector is deployed. For more details about how to use the HTTP server bundled in Metro, check the HTTP server API documentation.

Current Web Services Connector Architecture




Interoperability

Based on this architecture, we performed interoperability testing with WinRM (Microsoft's WS-Management based set of tools and API).

This document sums up the scenarios we are testing.

We didn't experience any problems related to interoperability.

Conclusion

Choosing Metro was definitely the right choice. On nearly all levels it has offered the features we were hoping for. When the boundaries of the standards were reached, Metro-specific API entered the scene and offered a solution. Metro really is ahead of the field in terms of improving performance.

So who is the wise man? The ones who defined such long stacks? No, I don't think so....

But Glassfish could be. Its management and monitoring features are based on JMX technology.

So?

So, by deploying the Web Services Connector for JMX (for which the Public Review specification and Early Access 3 RI will be available mid-February) in a Glassfish Server, all the existing MBeans (such as those defined by AMX, by JSR 77, and by you) are automatically exposed as WS-Management resources.

You can imagine the long journey we went through. Would you want to do this on your own, to expose your tiniest resources?

Be wise and use JMX, let us fill in the gaps!

Jean-François Denise

PS: My sincere thanks to Jitendra and Rama from the JAX-WS team for their help. Special thanks to Stuart Clements, my personnal editor and grammar checker.

Saturday May 05, 2007

JMX Web Services Connector is out, in WS-Man dress.


JMX Web Services Connector (JSR 262) RI is out! You can download it here.

The novelety in comparaison with the previous Early Access is that the Connector protocol is now based on WS-Management (WS-Man). Connector WS-Man implementation is based on the WiseMan project.

Native WS-Man clients can now interact with MBeans. MBeans are no more the exclusivity of JMX clients. Clients such as Windows Remote Manager (WinRM) and openwsman, can retrieve MBean attributes, call MBean operations and subscribe to MBean notifications.

JSR 262 specification defines a mapping between JMX MBeans and WS-Man Managed Resources. More details can be found in the Early Draft 2 specification. Have a look to the spec and send us your feedbacks.

Next Thursday, at JavaOne, during Eamonn and myself Technical Session, we are presenting an interoperability demo that highlights these new JMX interoperation capabilities. Demo is composed of three scenario:
  • HP Open View Operations / JSR 262 (done by Denis Rachal from HP)
  • Microsoft WinRM Scripting for JSR 262
  • Microsoft Vista Event Viewer to subscribe to MBeans
See you there!

Jean-Fran├žois
About

jeanfrancoisdenise

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today