The WebLogic Diagnostic Framework (WLDF) is a very powerful capability that has been in the product since WebLogic 9.0. WebLogic's product documentation does a good job of describing the fine detail of WLDF, but I believe that the high level overview it provides is too verbose and makes WLDF seem more complicated than it is. This is probably one reason why I don't see WLDF used quite as often as it should be, in place of custom coded monitoring solutions.
A couple of years ago I created my own diagram showing WLDF's composition, in an attempt to demonstrate that it's actually a fairly simple concept. However, I never got around to publishing it. Prompted by a recent request, I thought I'd address this ommision now, so here is that diagram...
Hopefully this helps to better show the power of WLDF and that it's not as complex as one might think.
Song for today: Maps by Yeah Yeah Yeahs
Saturday, August 28, 2010
Wednesday, August 11, 2010
Review of the new JRockit book
As promised, here's my review of the new JRockit book...

Having used JRockit for years (mostly sitting beneath WebLogic) I've been waiting for something like this book to arrive and lift the lid off the JVM to show what's inside. I'm glad to say that I am not disappointed. This book is a must-have for any serious enterprise Java developer or administrator who uses JRockit and wants to better understand how to tune, manage and monitor the JVM. The book also provides the Java developer with a clearer direction on the do's and don't's for developing a well behaving application on top of JRockit, especially in regard to memory management and thread management. Even for users of other JVMs, like Hotspot, much of the first half of the book, which concentrates on the JVM's internals, is relevant and insightful into the workings of Java virtual machines generally.
The first half of the book concentrates on providing in-depth knowledge of JRockit's internals and focusses on:
As I read this book, it became evident that the JRockit engineers are extremely passionate about their work and that they live and breath it. It is re-assuring to know that they are constantly striving to improve the product, based on deep scientific theory yet always with an eye on pragmatism and real-world usage. I'm sure this is why JRockit is fast and powerful whilst remaining easy to manage and run applications on. Throughout the book, the ethos of JRockit's design is very clear. It's an adaptive JVM, where the internal runtime is constantly and automatically being re-evaluated and re-tuned, according to the current nature of the hosted application's usage and load. Reading the book, I can better appreciate the argument that server-side Java is faster than an equivalent native C application. A native application only has one-shot, at compile time, to generate optimal native code. JRockit, however, takes the opportunity to revisit this at runtime, when it has a much better idea of actual usage patterns.
The second half of the book provides an introduction and detailed reference into JRockit's rich and powerful management and monitoring toolset, including:
Finally, at the end of the book there is an introductory chapter covering JRockit Virtual Edition (VE). JRockit VE enables the JRockit JVM, accompanied by a small JRockit kernel, to be run in a virtualised environment. This runs directly on-top of a hypervisor (eg. Oracle VM) without requiring the use of a conventional, heavy-weight, general-purpose operations system such as Linux, Solaris or Windows. Such a fully functional operating systems would otherwise burden the system with a layer of unwanted latency. This chapter in particular makes me realise that the JRockit Engineers are proverbial Rocket Scientists (or should that be Rockit Scientists? :D ). I defy anyone not to be impressed by the ambition of JRockit VE and and the high level of technical expertise that must have gone into developing it!
To summarise, I highly recommend this book. Easy to read yet very insightful. Once you've read it, it will remain as a handy reference to come back to, especially when needing to use the JRMC tools to diagnose issues and tune the JVM and hosted applications.
Song for today: Speed Trials by Elliot Smith

Having used JRockit for years (mostly sitting beneath WebLogic) I've been waiting for something like this book to arrive and lift the lid off the JVM to show what's inside. I'm glad to say that I am not disappointed. This book is a must-have for any serious enterprise Java developer or administrator who uses JRockit and wants to better understand how to tune, manage and monitor the JVM. The book also provides the Java developer with a clearer direction on the do's and don't's for developing a well behaving application on top of JRockit, especially in regard to memory management and thread management. Even for users of other JVMs, like Hotspot, much of the first half of the book, which concentrates on the JVM's internals, is relevant and insightful into the workings of Java virtual machines generally.
The first half of the book concentrates on providing in-depth knowledge of JRockit's internals and focusses on:
- Code Generation (Java bytecode, generation of native code, JRockit 's Just In Time compilation strategy with subsequent optimised code re-generation)
- Memory Management (heap usage, thread-local allocation, garbage collection strategies, deterministic-GC, 32-bit vs 64-bit memory management, potential pitfalls)
- Threads and Synchronisation (green vs O.S. threads, synchronisation patterns/anti-patterns, code generation strategies for locking/unlocking, thin and fat locks, lock profiling)
- Benchmarking and Tuning (throughput vs latency, tuning tips, benchmarking tips)
As I read this book, it became evident that the JRockit engineers are extremely passionate about their work and that they live and breath it. It is re-assuring to know that they are constantly striving to improve the product, based on deep scientific theory yet always with an eye on pragmatism and real-world usage. I'm sure this is why JRockit is fast and powerful whilst remaining easy to manage and run applications on. Throughout the book, the ethos of JRockit's design is very clear. It's an adaptive JVM, where the internal runtime is constantly and automatically being re-evaluated and re-tuned, according to the current nature of the hosted application's usage and load. Reading the book, I can better appreciate the argument that server-side Java is faster than an equivalent native C application. A native application only has one-shot, at compile time, to generate optimal native code. JRockit, however, takes the opportunity to revisit this at runtime, when it has a much better idea of actual usage patterns.
The second half of the book provides an introduction and detailed reference into JRockit's rich and powerful management and monitoring toolset, including:
- JRockit Mission Control (JRMC), composed of the Management Console, the Flight Recorder (plus Runtime Analyzer which it replaces) and the Memory Leak Detector
- JRockit Command line tool (JRCMD), including in-depth examples of all the important commands
- JRockit Management APIs, including the Java API for direct in-line access to the JRockit JVM from hosted Java applications plus the JMX version of the API for remote access to the JRockit JVM
Finally, at the end of the book there is an introductory chapter covering JRockit Virtual Edition (VE). JRockit VE enables the JRockit JVM, accompanied by a small JRockit kernel, to be run in a virtualised environment. This runs directly on-top of a hypervisor (eg. Oracle VM) without requiring the use of a conventional, heavy-weight, general-purpose operations system such as Linux, Solaris or Windows. Such a fully functional operating systems would otherwise burden the system with a layer of unwanted latency. This chapter in particular makes me realise that the JRockit Engineers are proverbial Rocket Scientists (or should that be Rockit Scientists? :D ). I defy anyone not to be impressed by the ambition of JRockit VE and and the high level of technical expertise that must have gone into developing it!
To summarise, I highly recommend this book. Easy to read yet very insightful. Once you've read it, it will remain as a handy reference to come back to, especially when needing to use the JRMC tools to diagnose issues and tune the JVM and hosted applications.
Song for today: Speed Trials by Elliot Smith
Wednesday, August 4, 2010
New release of DomainHealth WebLogic monitoring tool
I've just released the latest version of DomainHealth - version 0.9.
DomainHealth is an open source "zero-config" monitoring tool for WebLogic. It collects important server metrics over time, archives these into CSV files and provides a simple web interface for viewing graphs of current and historical statistics.
This release includes a new look and feel and a new page navigation mechanism (based on some contributions from Alain Gregoire). Other new features included are Web-App monitoring, EJB monitoring and various minor improvements and tweaks. For a full list of changes see the Release Notes document listed alongside the DomainHealth download files.
You can download DH from the project home page at http://sourceforge.net/projects/domainhealth.
The help docs for DH are at http://sourceforge.net/apps/mediawiki/domainhealth.
I'd like to say a big thank you to Alain Gregoire for his valuable design and code contributions to this version of DomainHealth.
Song for today: Lets Go For A Ride by Cracker
DomainHealth is an open source "zero-config" monitoring tool for WebLogic. It collects important server metrics over time, archives these into CSV files and provides a simple web interface for viewing graphs of current and historical statistics.
This release includes a new look and feel and a new page navigation mechanism (based on some contributions from Alain Gregoire). Other new features included are Web-App monitoring, EJB monitoring and various minor improvements and tweaks. For a full list of changes see the Release Notes document listed alongside the DomainHealth download files.
You can download DH from the project home page at http://sourceforge.net/projects/domainhealth.
The help docs for DH are at http://sourceforge.net/apps/mediawiki/domainhealth.
I'd like to say a big thank you to Alain Gregoire for his valuable design and code contributions to this version of DomainHealth.
Song for today: Lets Go For A Ride by Cracker
Friday, June 18, 2010
New JRockit book
A new book, "Oracle JRockit: The Definitive Guide", has just been published.
More info is available on the publisher's main landing page for the book.
I've got the book on order and I'll review it here once I've digested it. Judging by the content and the names of the esteemed JRockit engineers that wrote it, I'm expecting this to be an invaluable tome on all things JRockit.
Song for today: Mr.November by The National
More info is available on the publisher's main landing page for the book.
I've got the book on order and I'll review it here once I've digested it. Judging by the content and the names of the esteemed JRockit engineers that wrote it, I'm expecting this to be an invaluable tome on all things JRockit.
Song for today: Mr.November by The National
Monday, February 22, 2010
WLDF and Spring-generated Custom MBeans
In last week's blog, I mentioned a problem which occurs when trying to configure the WebLogic Diagnostic Framework (WLDF) to reference Spring-generated custom MBeans. Here I will describe how this issue can be addressed in a fairly simple way.
Originally, after deploying a web-app containing a Spring-generated MBean, I had attempted to configure a WLDF module using WebLogic's Admin Console to harvest an attribute of this MBean. However, as shown in the screen-shot below, the WLDF tooling was not detecting this custom MBean type as something that could be monitored.
The Spring-generated custom MBean type is not listed (it should begin with test.management...).
After doing a little digging around, I realised that WebLogic's WLDF documentation at section "Specifying Type Names for WebLogic Server MBeans and Custom MBeans" hints to why this should not work. Specifically it states: "...if the MBean is a ModelMBean and there is no value for the MBean Descriptor field DiagnosticTypeName) then the MBean can't be harvested".
Basically, when you try to define a Collected Metric or Watch Rule in a WLDF Diagnostic Module, WLDF needs to know the MBean's implementation class type for the way WLDF categorises MBeans of interest. Even if we don't use the Admin Console and instead use WLST or hack the XML for the domain config diagnostic module directly, we still have this problem because we have to declare the MBean implementation type.
In Sun's JMX standard, 3 of the 4 possible JMX MBean types (Standard, Dynamic and Open) are implemented directly by a Java class, which WLDF can automatically detect. However, for the 4th type (Model MBean), no direct Java class is used to define the MBean. Instead, the MBean is defined using metadata. As there is no MBean implementation class for WLDF to base its configuration on, it needs a hint for what the implementation class should be assumed to be. Spring-generated custom MBeans are Model MBeans and thus are affected by this issue. The WLDF documentation states that the 'implementation hint' should take the form of an explicitly declared MBean Descriptor field called DiagnosticTypeName.
The left-hand side of the screen-shot below shows the Spring-generated custom MBean, as seen via JConsole. The Model MBean descriptor is missing the WebLogic-specific field and hence the MBean can't be used by WLDF. The right-hand side of the screen-shot shows the generated MBean after the WLDF-required field DiagnosticTypeName has been included (the rest of this blog will show you how to achieve this).
So, for an adequate solution, I really needed a way for Spring to generate MBeans with this field automatically set to an appropriate value. Looking at the documentation for Spring's MBeanExporter (which I described in my last blog entry), I found that MBeanExporter has an optional property called assembler, which, if not defined, defaults to org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler. This default assembler uses reflection to generate Model MBeans by introspecting the simple Java-bean style classes. I didn't really want to lose the power and simplicity of this, but needed some way to ensure that the generated MBeans included the extra descriptor field. Then I hit upon the idea of extending this Spring assembler class and overriding its populateMBeanDescriptor() method to add the extra field after first calling the overridden method to have the other descriptor fields created as normal. So I implemented the following one-off class.
In my Spring bean definition file (WEB-INF/applicationContext.xml) I declared my custom assembler class which extends the Spring default assembler class, and then modified the exporter Spring bean to explicitly reference this assembler, as shown in bold below.
This time when I re-deployed my web-app to WebLogic and used JConsole to view it, the extra DiagnosticTypeName field was present in the MBean (see the right-hand side of the screen-shot above).
I tried again to create a custom Harvested Metric for an attribute in my Spring generated custom MBean, using WebLogic's Admin Console, and this time I was able to find and select my MBean type as shown in the screen-shot below.
On the next page, I was then able to see the available attributes of the MBean type to monitor and choose the 'PropA' one, as shown below.
Finally, I was given the option to select the instance of the MBean to monitor, before pressing finish to save the WLDF module, as shown in the screen-shot below.
Once my WLDF module was activated, I then waited a few minutes before using JConsole to change, dynamically at runtime, the value of PropA on my custom MBean. I then went to the Admin Console | Diagnostics | Log File page, and selected HarvestedDataArchive as the log file, to view the WLDF harvested data. The screen-shot below shows the value of the harvested 'PropA' attribute, taken every 30 seconds, with the new value shown at the base of the page.
In summary, it is possible to use WLDF to monitor Spring-generated custom MBeans as long as a WebLogic-specific descriptor field is defined for the generated MBean. In this blog, I have shown one way to achieve this, using a simple class that only has to be written once and then re-used and applied for every MBean required in a deployed app.
Song for today: Saints Around My Neck by Come
Originally, after deploying a web-app containing a Spring-generated MBean, I had attempted to configure a WLDF module using WebLogic's Admin Console to harvest an attribute of this MBean. However, as shown in the screen-shot below, the WLDF tooling was not detecting this custom MBean type as something that could be monitored.
The Spring-generated custom MBean type is not listed (it should begin with test.management...).
After doing a little digging around, I realised that WebLogic's WLDF documentation at section "Specifying Type Names for WebLogic Server MBeans and Custom MBeans" hints to why this should not work. Specifically it states: "...if the MBean is a ModelMBean and there is no value for the MBean Descriptor field DiagnosticTypeName) then the MBean can't be harvested".
Basically, when you try to define a Collected Metric or Watch Rule in a WLDF Diagnostic Module, WLDF needs to know the MBean's implementation class type for the way WLDF categorises MBeans of interest. Even if we don't use the Admin Console and instead use WLST or hack the XML for the domain config diagnostic module directly, we still have this problem because we have to declare the MBean implementation type.
In Sun's JMX standard, 3 of the 4 possible JMX MBean types (Standard, Dynamic and Open) are implemented directly by a Java class, which WLDF can automatically detect. However, for the 4th type (Model MBean), no direct Java class is used to define the MBean. Instead, the MBean is defined using metadata. As there is no MBean implementation class for WLDF to base its configuration on, it needs a hint for what the implementation class should be assumed to be. Spring-generated custom MBeans are Model MBeans and thus are affected by this issue. The WLDF documentation states that the 'implementation hint' should take the form of an explicitly declared MBean Descriptor field called DiagnosticTypeName.
The left-hand side of the screen-shot below shows the Spring-generated custom MBean, as seen via JConsole. The Model MBean descriptor is missing the WebLogic-specific field and hence the MBean can't be used by WLDF. The right-hand side of the screen-shot shows the generated MBean after the WLDF-required field DiagnosticTypeName has been included (the rest of this blog will show you how to achieve this).
So, for an adequate solution, I really needed a way for Spring to generate MBeans with this field automatically set to an appropriate value. Looking at the documentation for Spring's MBeanExporter (which I described in my last blog entry), I found that MBeanExporter has an optional property called assembler, which, if not defined, defaults to org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler. This default assembler uses reflection to generate Model MBeans by introspecting the simple Java-bean style classes. I didn't really want to lose the power and simplicity of this, but needed some way to ensure that the generated MBeans included the extra descriptor field. Then I hit upon the idea of extending this Spring assembler class and overriding its populateMBeanDescriptor() method to add the extra field after first calling the overridden method to have the other descriptor fields created as normal. So I implemented the following one-off class.
package customjmx; import javax.management.Descriptor; import org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler; public class WLDFAwareReflectiveMBeanInfoAssembler extends SimpleReflectiveMBeanInfoAssembler { private static final String WLDF_MBEAN_TYPE_DESCPTR_KEY = "DiagnosticTypeName"; private static final String NAME_MBEAN_DESCPTR_KEY = "name"; private static final String MBEAN_KEYNAME_SUFFIX = "MBean"; @Override protected void populateMBeanDescriptor(Descriptor descriptor, Object managedBean, String beanKey) { super.populateMBeanDescriptor(descriptor, managedBean, beanKey); descriptor.setField(WLDF_MBEAN_TYPE_DESCPTR_KEY, descriptor.getFieldValue(NAME_MBEAN_DESCPTR_KEY) + MBEAN_KEYNAME_SUFFIX); } }In my example code, I just take the original Spring POJO class's name and add the suffix 'MBean' to come up with a name which I feel best conveys the way the MBean is implemented, for the benefit of WLDF. In my example, the DiagnosticTypeName descriptor field is created for the MBean with a value of test.management.TestManagerBeanMBean. You could easily implement this sub-class code differently to generate a field value using your own convention.
In my Spring bean definition file (WEB-INF/applicationContext.xml) I declared my custom assembler class which extends the Spring default assembler class, and then modified the exporter Spring bean to explicitly reference this assembler, as shown in bold below.
<bean id="assembler" class="customjmx.WLDFAwareReflectiveMBeanInfoAssembler"/> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> <property name="beans"> <map> <entry key="com.test:name=TestMgr" value-ref="testMgrBean"/> </map> </property> <property name="server" ref="jmxServerRuntime"/> <property name="assembler" ref="assembler"/> </bean>
This time when I re-deployed my web-app to WebLogic and used JConsole to view it, the extra DiagnosticTypeName field was present in the MBean (see the right-hand side of the screen-shot above).
I tried again to create a custom Harvested Metric for an attribute in my Spring generated custom MBean, using WebLogic's Admin Console, and this time I was able to find and select my MBean type as shown in the screen-shot below.
On the next page, I was then able to see the available attributes of the MBean type to monitor and choose the 'PropA' one, as shown below.
Finally, I was given the option to select the instance of the MBean to monitor, before pressing finish to save the WLDF module, as shown in the screen-shot below.
Once my WLDF module was activated, I then waited a few minutes before using JConsole to change, dynamically at runtime, the value of PropA on my custom MBean. I then went to the Admin Console | Diagnostics | Log File page, and selected HarvestedDataArchive as the log file, to view the WLDF harvested data. The screen-shot below shows the value of the harvested 'PropA' attribute, taken every 30 seconds, with the new value shown at the base of the page.
In summary, it is possible to use WLDF to monitor Spring-generated custom MBeans as long as a WebLogic-specific descriptor field is defined for the generated MBean. In this blog, I have shown one way to achieve this, using a simple class that only has to be written once and then re-used and applied for every MBean required in a deployed app.
Song for today: Saints Around My Neck by Come
Tuesday, February 16, 2010
Creating Custom MBeans for WebLogic using Spring
In my previous blog I discussed how WebLogic provides some features to better integrate Spring-enabled apps into the app-server, including WebLogic auto-generated MBeans to monitor Spring specific elements of an application. In this blog, I instead focus on Spring's built-in ability to let developers create their own custom MBeans and how these can then be published to WebLogic's Runtime MBean Server rather than the underlying JVM's default Platform MBean Server.
Why would a developer want to create a custom MBean? Well the developer may want to provide a standards-based management capability for his/her deployed application, to enable third-party tools to manage and monitor the application remotely.
Why would the developer want to publish these MBean's to WebLogic's Runtime MBean Server? Well, in addition to being visible to generic remote JMX client tools (eg. Sun's JConsole tool), the MBeans are then easily accessible from WebLogic specific tools such as the WebLogic Scripting Tool (WLST) and even the WebLogic Diagnostic Framework (WLDF). Also, WebLogic's capabilities can be leveraged to secure the custom MBeans when associated with WebLogic's MBean Servers. For example, one could secure access to the MBeans using the t3s protocol with a valid username and password.
A few months ago, Philippe Le Mouel wrote a great article on how to create custom MBeans and register them with WebLogic, using pretty much standard JavaEE code. As you can see from his article, it takes quite a lot of effort and boilerplate Java code to define an MBean and then register it with the server at start-up.
In contrast, Spring makes it really easy to generate an MBean as part of your developed JavaEE app and avoid a lot of this coding effort. The Spring Reference (chapter 20) describes how to do this in detail. In essence, just include a Java-bean style POJO in your JavaEE web-app, like the following, for example:
In our application's Spring WEB-INF/applicationContext.xml file, we can then define our Spring bean in the normal way with some initial values to be injected into the bean's two properties, e.g.:
We can then traverse the JVM's Platform MBean Server, using JConsole's built-in MBean browser. As you can see below, in the MBean list, we can view the standard JVM java.lang MBeans, like the OperatingSystem MBean and the Memory MBean, together with our custom MBean which has an ObjectName of com.test:name=TestMgr.
We can even click in the the shown field for one of the properties (e.g. PropA), change the value to "Hello World!", press enter and value is changed in the running MBean. If we view the system-output for the WebLogic Server JVM's O.S. process, we will see the following text logged:
What we really want to do though, is have this MBean registered with WebLogic's MBean Server, not the JVM's Platform MBean Server. To do this in Java code we'd have to add a lot of JMX code at application start-up and shut-down time to register/un-register our MBean with the WebLogic MBean Server. However, because we're using Spring, its much easier. In our Spring applicationContext.xml file, we simply add a bean definition to tell Spring to use JNDI to locate the WebLogic Runtime MBean Server object at the well known WebLogic JNDI path. Then we modify our exporter bean definition to set an optional server property of Spring's MBeanExporter, giving it the handle to the JMX Server which Spring should export MBeans to. The additions to the Spring bean definition file are shown below in bold:
We can now see that our MBean is contained in the same JMX list as all WebLogic's server runtime MBeans.
We can even launch WLST to access our custom MBean by looking up the MBean using the JMX APIs and its ObjectName:
In summary, when it comes to creating management interfaces for developed applications hosted on WebLogic, Spring comes into its own, making things much easier and less error prone. Developers can rely on the comfort of a POJO based programming model for development of application management logic in addition to core business logic.
One final word. At the start of this blog entry I stated that by exporting custom MBeans to WebLogic's MBean Servers, we can use WebLogic tools like WLST and WLDF for monitoring these custom MBeans. Whilst this is true for custom MBeans in general, it turns out that for WLDF and Spring generated MBeans specifically, there's a slight hitch which means you can't use WLDF to harvest a Spring-generated custom MBean's properties or define a Watch/Notify for these properties. In my next blog entry, I intend to explain why this problem occurs and highlight a simple and re-usable workaround to address this and thus enable Spring-generated custom MBeans to be fully usable with WLDF.
Song for today: Just Because by Jane's Addiction
Why would a developer want to create a custom MBean? Well the developer may want to provide a standards-based management capability for his/her deployed application, to enable third-party tools to manage and monitor the application remotely.
Why would the developer want to publish these MBean's to WebLogic's Runtime MBean Server? Well, in addition to being visible to generic remote JMX client tools (eg. Sun's JConsole tool), the MBeans are then easily accessible from WebLogic specific tools such as the WebLogic Scripting Tool (WLST) and even the WebLogic Diagnostic Framework (WLDF). Also, WebLogic's capabilities can be leveraged to secure the custom MBeans when associated with WebLogic's MBean Servers. For example, one could secure access to the MBeans using the t3s protocol with a valid username and password.
A few months ago, Philippe Le Mouel wrote a great article on how to create custom MBeans and register them with WebLogic, using pretty much standard JavaEE code. As you can see from his article, it takes quite a lot of effort and boilerplate Java code to define an MBean and then register it with the server at start-up.
In contrast, Spring makes it really easy to generate an MBean as part of your developed JavaEE app and avoid a lot of this coding effort. The Spring Reference (chapter 20) describes how to do this in detail. In essence, just include a Java-bean style POJO in your JavaEE web-app, like the following, for example:
package test.management; public class TestManagerBean { public String getPropA() { return propA; } public void setPropA(String propA) { this.propA = propA; System.out.println("PropA set to: " + propA); } public int getPropB() { return propB; } public void setPropB(int propB) { this.propB = propB; System.out.println("PropB set to: " + propB); } private String propA; private int propB; }This example provides two properties to be JMX-enabled (one String, one int). Obviously, in a real-world application, the getter and setter code would reach inside the rest of the application's code to obtain data or change settings.
In our application's Spring WEB-INF/applicationContext.xml file, we can then define our Spring bean in the normal way with some initial values to be injected into the bean's two properties, e.g.:
<bean id="testMgrBean" class="test.management.TestManagerBean"> <property name="propA" value="Some text"/> <property name="propB" value="1000"/> </bean>The real add-value that Spring then provides, is the ability for Spring to auto-generate the MBean for us, for inclusion in our deployed app, by using Spring's MBeanExporter capability. This is enabled by adding the following definition to our applicationContext.xml file, for example:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> <property name="beans"> <map> <entry key="com.test:name=TestMgr" value-ref="testMgrBean"/> </map> </property> </bean>Now, when you deploy the app to WebLogic, the MBean is generated and registered with an MBean Server. However, by default, the Spring runtime only really knows about the standard Platform MBean server in the underlying JVM that Spring is running on. As a result, upon deployment, Spring registers this generated MBean with the JVM's built-in Platform MBean server only. Spring has no awareness of the possibility to use one of WebLogic's own MBean Servers. We can demonstrate that the JVM's Platform MBean server is currently hosting the deployed custom MBean, by launching the JDK's 'jconsole' tool, from the same machine as the WebLogic is running on, using the following commands:
$ . /opt/oracle/Middleware/wlserver_10.3/server/bin/setWLSEnv.sh $ jconsoleWe then select the local Java process corresponding to WebLogic to connect to - we don't specify a username/password:
We can then traverse the JVM's Platform MBean Server, using JConsole's built-in MBean browser. As you can see below, in the MBean list, we can view the standard JVM java.lang MBeans, like the OperatingSystem MBean and the Memory MBean, together with our custom MBean which has an ObjectName of com.test:name=TestMgr.
We can even click in the the shown field for one of the properties (e.g. PropA), change the value to "Hello World!", press enter and value is changed in the running MBean. If we view the system-output for the WebLogic Server JVM's O.S. process, we will see the following text logged:
PropA set to: Hello World!(we coded this println statement in our example POJO earlier)
What we really want to do though, is have this MBean registered with WebLogic's MBean Server, not the JVM's Platform MBean Server. To do this in Java code we'd have to add a lot of JMX code at application start-up and shut-down time to register/un-register our MBean with the WebLogic MBean Server. However, because we're using Spring, its much easier. In our Spring applicationContext.xml file, we simply add a bean definition to tell Spring to use JNDI to locate the WebLogic Runtime MBean Server object at the well known WebLogic JNDI path. Then we modify our exporter bean definition to set an optional server property of Spring's MBeanExporter, giving it the handle to the JMX Server which Spring should export MBeans to. The additions to the Spring bean definition file are shown below in bold:
<bean id="jmxServerRuntime" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jmx/runtime"/> </bean> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> <property name="beans"> <map> <entry key="com.test:name=TestMgr" value-ref="testMgrBean"/> </map> </property> <property name="server" ref="jmxServerRuntime"/> </bean>Once re-deployed, we can launch JConsole again, but this time we connect to the WebLogic Runtime MBean Server using T3 to communicate remotely, using the following commands:
$ . /opt/oracle/Middleware/wlserver_10.3/server/bin/setWLSEnv.sh $ jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar: $JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/weblogic.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remoteFor the connection URL we specify "service:jmx:t3://localhost:7001/jndi/weblogic.management.mbeanservers.runtime" and we provide the WebLogic administrator username/password:
We can now see that our MBean is contained in the same JMX list as all WebLogic's server runtime MBeans.
We can even launch WLST to access our custom MBean by looking up the MBean using the JMX APIs and its ObjectName:
$ /opt/oracle/Middleware/wlserver_10.3/common/bin/wlst.sh
> connect('weblogic','welcome1','t3://localhost:7001')
> serverRuntime()
> myMBean = mbs.getObjectInstance(ObjectName('com.test:name=TestMgr'))
> print myMBean
test.management.TestManagerBean[com.test:name=TestMgr]
If we want to get or set a property on the custom MBean using JMX in WLST, we can:> print mbs.getAttribute(ObjectName('com.test:name=TestMgr'), 'PropA') Some text > mbs.setAttribute(ObjectName('com.test:name=TestMgr'), Attribute('PropA', 'Hello World!')) > print mbs.getAttribute(ObjectName('com.test:name=TestMgr'), 'PropA') Hello World!Or alternatively, we can use the more convenient WLST commands to navigate and manipulate our custom MBean rather than issuing complicated JMX commands:
> custom() > ls() drw- com.test > cd('com.test') > ls() drw- com.test:name=TestMgr > cd('com.test:name=TestMgr') > ls() -rw- PropA Some text -rw- PropB 1000 > print get('PropA') Some text > set('PropA', 'Hello World!') > print get('PropA') Hello World!(remember, when in the custom tree we can't use the WLST cmo variable)
In summary, when it comes to creating management interfaces for developed applications hosted on WebLogic, Spring comes into its own, making things much easier and less error prone. Developers can rely on the comfort of a POJO based programming model for development of application management logic in addition to core business logic.
One final word. At the start of this blog entry I stated that by exporting custom MBeans to WebLogic's MBean Servers, we can use WebLogic tools like WLST and WLDF for monitoring these custom MBeans. Whilst this is true for custom MBeans in general, it turns out that for WLDF and Spring generated MBeans specifically, there's a slight hitch which means you can't use WLDF to harvest a Spring-generated custom MBean's properties or define a Watch/Notify for these properties. In my next blog entry, I intend to explain why this problem occurs and highlight a simple and re-usable workaround to address this and thus enable Spring-generated custom MBeans to be fully usable with WLDF.
Song for today: Just Because by Jane's Addiction
Monday, February 1, 2010
WebLogic and Spring
In this blog topic I describe some of the integration points that WebLogic provides for Spring based applications.
I have mixed feelings about Spring. I definitely prefer its primary focus on the Dependency Injection pattern (DI) instead of the more typical JavaEE model of using the Service Locator pattern (think JNDI lookups). If used the right way, both patterns can help promote loosely coupled and easily unit-testable solutions. However, Spring's prescriptive DI approach makes the process of developing loosely-coupled solutions feel more intuitive and natural. Also, Spring offers an easy way to leverage Aspect Oriented Programming (AOP) when needed (and yes I emphasise the word when - excessive sprinkling of aspects can make applications hard to understand, debug and troubleshoot).
On the downside, it sometimes feels like Spring has evolved from a light-weight framework for making J2EE easier, into a vast and competing component model for building enterprise applications. It's not clear to me how much the balance in Spring has shifted from Innovating to Re-inventing, and whether this shift is a good thing or not.
Fortunately, WebLogic makes it pretty easy to deploy Spring based apps, whether your application uses Spring in a just-enough-dependency-injection way or in a use-nearly-every-Spring-feature-under-the-sun way. On most levels it doesn't really matter what version of Spring you use with a particular version of WebLogic. If you have an issue, you use the Oracle Support organisation for help with WebLogic specific problems and any Spring parts to your application are treated just like your own custom code is, from an Oracle Support perspective.
In addition, Oracle actually provides explicit certification for specific versions of Spring running on specific versions of WebLogic. For example, on WLS 10.3.x, Oracle explicitly certifies the use of Spring version 2.5.3 (and any later `double-dot' Spring releases). For the official certification matrix, see the spreadsheet titled System Requirements and Supported Platforms for Oracle WebLogic Server 10.3 on the supported configurations page. As a matter of interest, it's also worth noting that internally* WebLogic uses elements of Spring and its AOP capabilities to implement some of WebLogic's newer JavaEE features like EJB 3.0, by using the Spring Pitchfork codebase under the covers.
* WebLogic prefixes the package names of its internally bundled Spring classes to avoid potential class-loading clash issues with Spring classes bundled in any deployed applications. Application developers can also separately choose to bundle the classes from the Spring Pitchfork project to enable Spring beans to be injected into Servlets and EJBs in their own developed application.
When using an Oracle certified version of Spring with WebLogic, extra integration features are also available to help Spring based applications become first-class WebLogic citizens, in the same way that normal JavaEE applications are. This is described in WebLogic's help documentation on Spring. By including some boilerplate text in your web-app's Manifest.mf file to refer to an optional package and by ensuring WL_HOME/server/lib/weblogic-spring.jar is first deployed to WebLogic as a shared library, the following 3 WebLogic features are automatically enabled:
1. Spring MBeans. WebLogic automatically generates a set of Spring related MBeans, hanging off the normal WebLogic ApplicationRuntimeMBeans, into each server's Runtime Service JMX tree. Examples of these MBeans are SpringRuntimeMBean, SpringApplicationContextRuntimeMBean and SpringTransactionManagerRuntimeMBean. See the WebLogic MBean Reference for more info on these Spring MBeans. The Spring MBeans are read-only and enable administrators to have better visibility into what's going on inside the Spring parts of deployed applications. The screenshot below shows the use of WLST to inspect some of these MBeans. If the Manifest.mf file is not correctly defined, WebLogic does not detect the presence of Spring elements in the application and thus will not generate the Spring MBeans; SpringRuntimeMBean would not appear in the list of child MBeans shown in the screenshot.
2. Spring Console Extension. WebLogic provides an Admin Console extension for Spring to provide administrators with visual tools for monitoring the Spring parts of deployed applications (first navigate to WebLogic Admin Console's Preferences | Extension menu option and and enable spring-console). This Spring console extension is basically a set of pages which are added amongst the normal pages of the standard WebLogic admin console, rather than being a separate console per se. The extension provides a view onto the values of the WebLogic generated Spring MBeans (see point 1). If you navigate to the deployed web-app in the Admin Console, select the Configuration tab, and then select the Spring Framework sub-tab, you will see a read-only view of the contents of the application's Spring application context(s), as shown in the example screenshot below.
In the Deployment's Monitoring tab, if you select the Spring Framework sub-tab, as shown in the example below, you can drill into read-only views of the types and amounts of Spring beans that have currently been created in the deployed application's Spring application context(s). It also lets you view the WebLogic managed transactions that have been initiated via the Spring library code in the deployed application.
By selecting one of the Spring application contexts listed in this table, you will see statistics showing how many beans have been created in the context, what scope they have and their performance metrics, as shown in the screenshot below.
3. WebLogic Injected Spring Beans. During the start-up process for the Spring-enabled web-application (see point 1), WebLogic intercepts the creation of the web-app's normal Spring Application Context (using AOP under the covers), and transparently adds a parent context to the normal context. This parent context is pre-populated with the following 3 WebLogic specific beans, ready to be used by the application:
Using the Spring console extension discussed in point 2, we can actually navigate to and view the contents of the parent application context, at runtime, in addition to the normal app context, as shown in the first two screenshots in point 2.
During the application initialisation process, WebLogic also sets the application's default Spring Transaction Manager to be org.springframework.transaction.jta.WebLogicJtaTransactionManager to enable WebLogic's Transaction Manager to always be used for managing JTA transactions initiated in Spring code.
Note: A 4th bean (a WebLogic System Work Manager bean) is also populated in the parent context. However, this bean is meant for internal WebLogic system usage and is not for application developers to use, as it does not implement commonj.work.WorkManager. Developers who do want to utilise WebLogic Work Managers, should just declare the work managers they require in the WebLogic domain's configuration, in the normal way, and then use org.springframework.scheduling.commonj.WorkManagerTaskExecutor in their Spring Bean context XML files, to enable the work managers to be injected into application code.
In summary, in this blog topic I have described some of the ways that WebLogic handles applications that use Spring. Not all the integration points between WebLogic and Spring have been discussed. For example, I have not described how WebLogic can integrate with Spring Security (a.k.a. Acegi), how WebLogic's fast RMI/T3 binary wire protocol can be used for Spring Remoting and I have only mentioned in passing the ability to use Spring Dependency Injection into Servlets and EJBs.
Footnote: Brand new in WebLogic 10.3.2 is un-documented and un-supported tech-preview support for the Service Component Architecture (SCA) using Spring. This tech-preview uses Spring to wire up the POJOs inside components and composites, and to declaratively specify the invocation protocol bindings for these composites. The WebLogic-Spring capabilities discussed here in my blog entry are unrelated to the SCA tech-preview support.
Song for today: Rid of Me by PJ Harvey
I have mixed feelings about Spring. I definitely prefer its primary focus on the Dependency Injection pattern (DI) instead of the more typical JavaEE model of using the Service Locator pattern (think JNDI lookups). If used the right way, both patterns can help promote loosely coupled and easily unit-testable solutions. However, Spring's prescriptive DI approach makes the process of developing loosely-coupled solutions feel more intuitive and natural. Also, Spring offers an easy way to leverage Aspect Oriented Programming (AOP) when needed (and yes I emphasise the word when - excessive sprinkling of aspects can make applications hard to understand, debug and troubleshoot).
On the downside, it sometimes feels like Spring has evolved from a light-weight framework for making J2EE easier, into a vast and competing component model for building enterprise applications. It's not clear to me how much the balance in Spring has shifted from Innovating to Re-inventing, and whether this shift is a good thing or not.
Fortunately, WebLogic makes it pretty easy to deploy Spring based apps, whether your application uses Spring in a just-enough-dependency-injection way or in a use-nearly-every-Spring-feature-under-the-sun way. On most levels it doesn't really matter what version of Spring you use with a particular version of WebLogic. If you have an issue, you use the Oracle Support organisation for help with WebLogic specific problems and any Spring parts to your application are treated just like your own custom code is, from an Oracle Support perspective.
In addition, Oracle actually provides explicit certification for specific versions of Spring running on specific versions of WebLogic. For example, on WLS 10.3.x, Oracle explicitly certifies the use of Spring version 2.5.3 (and any later `double-dot' Spring releases). For the official certification matrix, see the spreadsheet titled System Requirements and Supported Platforms for Oracle WebLogic Server 10.3 on the supported configurations page. As a matter of interest, it's also worth noting that internally* WebLogic uses elements of Spring and its AOP capabilities to implement some of WebLogic's newer JavaEE features like EJB 3.0, by using the Spring Pitchfork codebase under the covers.
* WebLogic prefixes the package names of its internally bundled Spring classes to avoid potential class-loading clash issues with Spring classes bundled in any deployed applications. Application developers can also separately choose to bundle the classes from the Spring Pitchfork project to enable Spring beans to be injected into Servlets and EJBs in their own developed application.
When using an Oracle certified version of Spring with WebLogic, extra integration features are also available to help Spring based applications become first-class WebLogic citizens, in the same way that normal JavaEE applications are. This is described in WebLogic's help documentation on Spring. By including some boilerplate text in your web-app's Manifest.mf file to refer to an optional package and by ensuring WL_HOME/server/lib/weblogic-spring.jar is first deployed to WebLogic as a shared library, the following 3 WebLogic features are automatically enabled:
1. Spring MBeans. WebLogic automatically generates a set of Spring related MBeans, hanging off the normal WebLogic ApplicationRuntimeMBeans, into each server's Runtime Service JMX tree. Examples of these MBeans are SpringRuntimeMBean, SpringApplicationContextRuntimeMBean and SpringTransactionManagerRuntimeMBean. See the WebLogic MBean Reference for more info on these Spring MBeans. The Spring MBeans are read-only and enable administrators to have better visibility into what's going on inside the Spring parts of deployed applications. The screenshot below shows the use of WLST to inspect some of these MBeans. If the Manifest.mf file is not correctly defined, WebLogic does not detect the presence of Spring elements in the application and thus will not generate the Spring MBeans; SpringRuntimeMBean would not appear in the list of child MBeans shown in the screenshot.
2. Spring Console Extension. WebLogic provides an Admin Console extension for Spring to provide administrators with visual tools for monitoring the Spring parts of deployed applications (first navigate to WebLogic Admin Console's Preferences | Extension menu option and and enable spring-console). This Spring console extension is basically a set of pages which are added amongst the normal pages of the standard WebLogic admin console, rather than being a separate console per se. The extension provides a view onto the values of the WebLogic generated Spring MBeans (see point 1). If you navigate to the deployed web-app in the Admin Console, select the Configuration tab, and then select the Spring Framework sub-tab, you will see a read-only view of the contents of the application's Spring application context(s), as shown in the example screenshot below.
In the Deployment's Monitoring tab, if you select the Spring Framework sub-tab, as shown in the example below, you can drill into read-only views of the types and amounts of Spring beans that have currently been created in the deployed application's Spring application context(s). It also lets you view the WebLogic managed transactions that have been initiated via the Spring library code in the deployed application.
By selecting one of the Spring application contexts listed in this table, you will see statistics showing how many beans have been created in the context, what scope they have and their performance metrics, as shown in the screenshot below.
3. WebLogic Injected Spring Beans. During the start-up process for the Spring-enabled web-application (see point 1), WebLogic intercepts the creation of the web-app's normal Spring Application Context (using AOP under the covers), and transparently adds a parent context to the normal context. This parent context is pre-populated with the following 3 WebLogic specific beans, ready to be used by the application:
- A WebLoigc Transaction Manager bean (ref="transactionManager") which extends org.springframework.transaction.jta.JtaTransactionManager
- A WebLogic Edit Server MBean Connection bean (ref="editMBeanServerConnection") which implements javax.management.MBeanServerConnection
- A WebLogic Runtime Server MBean Connection bean (ref="runtimeMBeanServerConnection") which implements javax.management.MBeanServerConnection
<bean id="myTestBean" class="com.acme.MyTestBean">
<property name="mbeanSvrConn" ref="runtimeMBeanServerConnection"/>
</bean>
The exact set of WebLogic beans injected into the parent application context can be deduced by unzipping the file WL_HOME/wlserver_10.3/server/lib/weblogic-spring.jar and viewing the contents of the file weblogic/spring/beans/SpringServerApplicationContext.xml.Using the Spring console extension discussed in point 2, we can actually navigate to and view the contents of the parent application context, at runtime, in addition to the normal app context, as shown in the first two screenshots in point 2.
During the application initialisation process, WebLogic also sets the application's default Spring Transaction Manager to be org.springframework.transaction.jta.WebLogicJtaTransactionManager to enable WebLogic's Transaction Manager to always be used for managing JTA transactions initiated in Spring code.
Note: A 4th bean (a WebLogic System Work Manager bean) is also populated in the parent context. However, this bean is meant for internal WebLogic system usage and is not for application developers to use, as it does not implement commonj.work.WorkManager. Developers who do want to utilise WebLogic Work Managers, should just declare the work managers they require in the WebLogic domain's configuration, in the normal way, and then use org.springframework.scheduling.commonj.WorkManagerTaskExecutor in their Spring Bean context XML files, to enable the work managers to be injected into application code.
In summary, in this blog topic I have described some of the ways that WebLogic handles applications that use Spring. Not all the integration points between WebLogic and Spring have been discussed. For example, I have not described how WebLogic can integrate with Spring Security (a.k.a. Acegi), how WebLogic's fast RMI/T3 binary wire protocol can be used for Spring Remoting and I have only mentioned in passing the ability to use Spring Dependency Injection into Servlets and EJBs.
Footnote: Brand new in WebLogic 10.3.2 is un-documented and un-supported tech-preview support for the Service Component Architecture (SCA) using Spring. This tech-preview uses Spring to wire up the POJOs inside components and composites, and to declaratively specify the invocation protocol bindings for these composites. The WebLogic-Spring capabilities discussed here in my blog entry are unrelated to the SCA tech-preview support.
Song for today: Rid of Me by PJ Harvey
Friday, December 11, 2009
Deciding to use DomainHealth
DomainHealth (DH) is an open source "zero-config" monitoring tool for WebLogic. It collects important server metrics over time, archives these into CSV files and provides a simple web interface for viewing graphs of current and historical statistics.
So when should you consider using DomainHealth?
When you don't have a full monitoring solution in place already for your WebLogic environment. Ideally an organisation will have standardised on using Oracle Enterprise Manager or a 3rd party management tool, for its comprehensive monitoring needs. Oracle Enterprise Manager also caters for various management requirements in addition to monitoring, which DH does not. The scope of DH's monitoring capabilities is purely focussed on tracking current and historic usage of certain key server resources. DH is not applicable for profiling your deployed applications (instead see Oracle AD4J) or intensively monitoring your JVM (instead see Oracle JRockit Mission Control). However, some organisations using Enterprise Manager may find that DH acts as a convenient and complementary addition to their monitoring solution.
The most comparable tool to DomainHealth is the WebLogic Diagnostic Framework Console Extension which ships as standard with WebLogic. I use both of these tools in my day to day work, where different situations and requirements dictate the use of one over the other.
I use DomainHealth (with its built-in WLDF harvesting mechanism) rather than the WLDF Console Extension, in situations where some of the following factors are advantageous:
DomainHealth project home page: http://sourceforge.net/projects/domainhealth
DomainHealth help documentation: http://sourceforge.net/apps/mediawiki/domainhealth
Song for today: Gimme Shelter by The Rolling Stones
So when should you consider using DomainHealth?
When you don't have a full monitoring solution in place already for your WebLogic environment. Ideally an organisation will have standardised on using Oracle Enterprise Manager or a 3rd party management tool, for its comprehensive monitoring needs. Oracle Enterprise Manager also caters for various management requirements in addition to monitoring, which DH does not. The scope of DH's monitoring capabilities is purely focussed on tracking current and historic usage of certain key server resources. DH is not applicable for profiling your deployed applications (instead see Oracle AD4J) or intensively monitoring your JVM (instead see Oracle JRockit Mission Control). However, some organisations using Enterprise Manager may find that DH acts as a convenient and complementary addition to their monitoring solution.
The most comparable tool to DomainHealth is the WebLogic Diagnostic Framework Console Extension which ships as standard with WebLogic. I use both of these tools in my day to day work, where different situations and requirements dictate the use of one over the other.
I use DomainHealth (with its built-in WLDF harvesting mechanism) rather than the WLDF Console Extension, in situations where some of the following factors are advantageous:
- Zero-configuration. An administrator does not have to first work out and configure the server objects to monitor. An administrator does not have to spend time creating a complex WLDF module with the correct object types, names and attributes in it. An administrator does not have to work out what graphs to plot and then configure specific graphs for each server in the domain for every new environment (eg. Test, Pre-Prod, Prod1, Prod2).
- Minimal performance impact on Managed Servers. Obtains a set of statistics once and ONLY once, regardless of how many times you come back to view the same statistics in the graphs. The background statistics collection work is driven from the admin server, once per minute, lasting far less than a second.
- Tools friendly storage of statistics in CSV files. Administrators can open the CSVs in MS Excel or Open Office for off-line analysis and graphing. Using CSV files rather than WebLogic Persistent File Stores on the admin server has no detrimental performance impact. It doesn't matter if it takes 10 microseconds or 100 milliseconds to persist the set of statistics - timeliness only has to be to the nearest minute. The file I/O for writing data to CSV files on the admin server is not in the 'flight-path' of transactions that happen to be racing through the managed servers.
- Minimal administrator workstation pre-requisites. Doesn't require Java Applet support on the administrator's workstation; it's browser-friendly and just uses very simple HTML and PNG images to display graphs.
- Hot deployable. Deployable to an already running domain for diagnosis of currently occurring problems, without needing to restart the admin server.
- Statistics don't constantly scroll whilst trying to analyse them. Administrators can focus in on the current window of time or an historic window of time, in a graph, without it continuously refreshing and moving to a later time. A simple set of navigation buttons is provided to move backwards or forwards in time or just go to the most current time.
- Statistics can be viewed for non-running Managed Servers. If a managed server has has just died, graphs of its recent statistics can still be viewed to help diagnose the failure cause, without first requiring the managed server to be recovered and re-started.
- Infinitely configurable. Administrators get to choose exactly what server resources they want to monitor.
- Fine-grained statistics capture. Statistics are gathered and displayed at a much higher frequency than just once every minute.
- Shipped as part of WebLogic. No need for an administrator to seek corporate approval to download and provision a 3rd party open source application into the organisation's WebLogic environment.
- Statistics can be retrieved for the periods of time when the Admin Server was down. As long as an administrator has previously configured a WLDF module with the right harvested objects and attributes, statistics can still be retrieved retrospectively, by the Console's graphs, following a period of time when the admin server was down and unable to contact the managed servers.
DomainHealth project home page: http://sourceforge.net/projects/domainhealth
DomainHealth help documentation: http://sourceforge.net/apps/mediawiki/domainhealth
Song for today: Gimme Shelter by The Rolling Stones
Thursday, December 10, 2009
New DomainHealth WebLogic monitoring tool version
I've just released the latest version of DomainHealth - version 0.8 (well actually 0.8.1 because of a fix for a last minute bug spotted by Kris).
DomainHealth (DH) is an open source "zero-config" monitoring tool for WebLogic. It collects important server metrics over time, archives these into CSV files and provides a simple web interface for viewing graphs of current and historical statistics.
You can download it from the project home page at http://sourceforge.net/projects/domainhealth.
The help docs for DomainHealth are at: http://sourceforge.net/apps/mediawiki/domainhealth.

This release includes many minor fixes and enhancements (see the Release Notes document listed alongside the DH download file), plus the following major additions:
Song for today: Touched by VAST
DomainHealth (DH) is an open source "zero-config" monitoring tool for WebLogic. It collects important server metrics over time, archives these into CSV files and provides a simple web interface for viewing graphs of current and historical statistics.
You can download it from the project home page at http://sourceforge.net/projects/domainhealth.
The help docs for DomainHealth are at: http://sourceforge.net/apps/mediawiki/domainhealth.

This release includes many minor fixes and enhancements (see the Release Notes document listed alongside the DH download file), plus the following major additions:
- Now provides the ability to harvest and retrieve server statistics using a WLDF module (configured on the fly by DH), rather than using JMX to poll each server for statistics. This is now the default behaviour when running on WLS version 10.3.x or greater. For WLS versions 9.0 to 10.0.x, it still uses JMX Polling. If you prefer to use JMX Polling for the recent WLS versions, you can force this behaviour with a special parameter (see the Help docs). It is worth noting that, although I don't believe the load that the periodic JMX Polling puts on the managed servers (once a minute), is noticeable, I was still keen for DH to move to use WLDF by default. This way, DH acts as a WebLogic 'good citizen' and is also able to better cope with the increased number of MBean statistics that inevitably come with each new DH release.
- Now shows a lot more interesting Thread Pool statistics on the main page (including Throughput and QueueLength).
- Previously, for domains with many servers, it was difficult to drill into the statistics for just one specific server at a time, in the graphical web pages. Now you have the option to select which server you want to see on the web page, in isolation, by selecting the server's name from a drop down list.
- When using the WLDF based mechanism for collecting metrics, statistics for all Work Managers and all Server Channels (protocol server sockets) are now also retrieved and displayed. I have not added this capability for the JMX Polling based mechanism because I'm wary of putting too much load on each managed server during the polling process (I may revisit this decision at a later date).
Song for today: Touched by VAST
Saturday, October 24, 2009
New WebLogic book is out
A new book titled Professional Oracle WebLogic Server (Wiley/Wrox, 2009) is out now.

I am a contributing author having written the Web Services chapter (ch.9). A colleague of mine, Josh, wrote the Security chapter and the main bulk of the book was written by Robert, Phil and Greg, with Robert pulling the whole thing together into what we hope is a single cohesive and instructive resource (Robert and Phil are colleagues of mine too).
It's an intermediate to advanced-level, best practices style book aimed at WebLogic Server version 11g (10.3.1). However, for the most part, the content is equally applicable to earlier versions of WebLogic too, from 9.0 onwards, with the notable exception of its EJB 3.0 and JAX-WS 2.1 coverage.
You can get the book from the main book home page, where you can also download the Table of Contents in PDF form, it you first want to better understand what topics are covered. This home page also includes a link for you to download the book's sample code which includes the Web Services example projects, that I wrote to accompany chapter 9.
You can also get the book from Amazon UK, Amazon US and most other major book retailers out there. Parts of the book can be previewed at Google Books.
Enjoy!
Song for today: I've Made Enough Friends by The Wrens

I am a contributing author having written the Web Services chapter (ch.9). A colleague of mine, Josh, wrote the Security chapter and the main bulk of the book was written by Robert, Phil and Greg, with Robert pulling the whole thing together into what we hope is a single cohesive and instructive resource (Robert and Phil are colleagues of mine too).
It's an intermediate to advanced-level, best practices style book aimed at WebLogic Server version 11g (10.3.1). However, for the most part, the content is equally applicable to earlier versions of WebLogic too, from 9.0 onwards, with the notable exception of its EJB 3.0 and JAX-WS 2.1 coverage.
You can get the book from the main book home page, where you can also download the Table of Contents in PDF form, it you first want to better understand what topics are covered. This home page also includes a link for you to download the book's sample code which includes the Web Services example projects, that I wrote to accompany chapter 9.
You can also get the book from Amazon UK, Amazon US and most other major book retailers out there. Parts of the book can be previewed at Google Books.
Enjoy!
Song for today: I've Made Enough Friends by The Wrens
Thursday, September 3, 2009
Attempting to Quickly Diagnose Production Memory Leaks with JRockit
I just wanted to mention my favourite, not well known, JRockit diagnostic command which I've used a few times recently to resolve tricky JVM heap related issues in production environments.
Imagine the situation: You've performance tested and tuned your server and application to the hilt, but on day 3 after going live, the production servers are exhibiting excessive heap memory usage issues. You've been pushed into the noisy server room, the pressure's on and the project sponsor is pacing up and down behind you. Until a sys-admin sorts out a non-headless machine for you to run JRockit's Mission Control on, you're stuck with the command line on the production server you've just SSH'd into. You're desperate to be able to just issue a command or two into the shell to quickly see what's happening in the JVM heap before the sys-admin bounces the server to prevent it from going pop with out of memory errors. Well there is such a command that might just save you....
Using JRockit's JRCMD command line tool you can issue a command called heap_diagnostics.
This command was new in JRockit R26.4 which was bundled with some of the later WLS 9.x versions and with all WLS versions from 10.0 onwards. It produces a diagnostic text dump of the state of the live JRockit heap, into sys-out of your command shell. The dump includes a summary of the current heap size and heap free, the layout of the native memory used by the JVM, the layout of the JVM's heap, and the state of soft/weak/phantom references and finalizers at the last garbage collection. Most crucially though, the dump also includes the number, percentage and size of every object type currently held in the heap, in order of the largest consumer first. If you suspect a memory leak and look at the names of the classes listed at the top of this list, you have a good chance of very quickly discovering which objects are being leaked. This may not directly point you at the root cause, but it will give you a much better idea of where the problem may lie.
As an example, to produce a diagnostic dump on a Unix based host environment, run the following commands to: (i) make the JRockit JRE and tools visible to your shell, (ii) determine the operating system's process ID of the WebLogic instance you want to probe, and (iii) generate the diagnostic dump into a text file:
The command takes a second or two to complete (depending on the current size of your heap and how much is in there). In the environment where I was chasing a memory leak, the dump text file was about 0.5 MB in size, which I've truncated and shown below.
In this specific example, by looking at the first few entries in the "Detailed Heap Statistics" section of the dump, showing largest heap consumers first, I was able to take an educated guess that the cause of my memory leak was due to some SNMP related classes in the package 'monfox' in WebLogic 10.0.1 rather than in my application code. In my case, having so many of these types of objects in the heap was not to be expected. However in other cases, top consuming objects may be legitimate and not be leaked objects, so this is only a potential indicator. Incidentally, if you need a patch for this specific SNMP issue, raise an Oracle Support case using Metalink refering to Bug#8185278.
Song for today: Turn Around by Whiskeytown
Imagine the situation: You've performance tested and tuned your server and application to the hilt, but on day 3 after going live, the production servers are exhibiting excessive heap memory usage issues. You've been pushed into the noisy server room, the pressure's on and the project sponsor is pacing up and down behind you. Until a sys-admin sorts out a non-headless machine for you to run JRockit's Mission Control on, you're stuck with the command line on the production server you've just SSH'd into. You're desperate to be able to just issue a command or two into the shell to quickly see what's happening in the JVM heap before the sys-admin bounces the server to prevent it from going pop with out of memory errors. Well there is such a command that might just save you....
Using JRockit's JRCMD command line tool you can issue a command called heap_diagnostics.
This command was new in JRockit R26.4 which was bundled with some of the later WLS 9.x versions and with all WLS versions from 10.0 onwards. It produces a diagnostic text dump of the state of the live JRockit heap, into sys-out of your command shell. The dump includes a summary of the current heap size and heap free, the layout of the native memory used by the JVM, the layout of the JVM's heap, and the state of soft/weak/phantom references and finalizers at the last garbage collection. Most crucially though, the dump also includes the number, percentage and size of every object type currently held in the heap, in order of the largest consumer first. If you suspect a memory leak and look at the names of the classes listed at the top of this list, you have a good chance of very quickly discovering which objects are being leaked. This may not directly point you at the root cause, but it will give you a much better idea of where the problem may lie.
As an example, to produce a diagnostic dump on a Unix based host environment, run the following commands to: (i) make the JRockit JRE and tools visible to your shell, (ii) determine the operating system's process ID of the WebLogic instance you want to probe, and (iii) generate the diagnostic dump into a text file:
$ . /opt/oracle/WLS103/wlserver_10.3/server/bin/setWLSEnv.sh $ jps -l | grep weblogic 9681 weblogic.Server $ jrcmd 9681 heap_diagnostics > heapdump.txt
The command takes a second or two to complete (depending on the current size of your heap and how much is in there). In the environment where I was chasing a memory leak, the dump text file was about 0.5 MB in size, which I've truncated and shown below.
In this specific example, by looking at the first few entries in the "Detailed Heap Statistics" section of the dump, showing largest heap consumers first, I was able to take an educated guess that the cause of my memory leak was due to some SNMP related classes in the package 'monfox' in WebLogic 10.0.1 rather than in my application code. In my case, having so many of these types of objects in the heap was not to be expected. However in other cases, top consuming objects may be legitimate and not be leaked objects, so this is only a potential indicator. Incidentally, if you need a patch for this specific SNMP issue, raise an Oracle Support case using Metalink refering to Bug#8185278.
======== BEGIN OF HEAPDIAGNOSTIC ========================= Total memory in system: 3434975232 bytes Available physical memory in system: 2001797120 bytes -Xmx (maximal heap size) is 536870912 bytes Heapsize: 536870912 bytes Free heap-memory: 470024072 bytes mmStartCompaction = 0x8c00000, mmEndCompaction = 0xac00000 Memory layout: 00000000-00002000 ---p 00000000 00:00 0 08048000-08057000 r-xp 00000000 08:06 11421468 /opt/oracle/wls1001/jrockit_150_11/bin/java 08057000-08058000 rwxp 0000f000 08:06 11421468 /opt/oracle/wls1001/jrockit_150_11/bin/java 08060000-080e0000 rwxp 08060000 00:00 0 08100000-08901000 rwxp 08100000 00:00 0 .........truncated......... --------- Detailed Heap Statistics: --------- 26.1% 12083k 108775 -541k [C 12.8% 5924k 5586 +18k [B 7.2% 3338k 142444 -52k java/lang/String 6.4% 2974k 54389 -4k monfox/toolkit/snmp/util/OidTree$Node 3.8% 1753k 16028 +0k [Lmonfox/toolkit/snmp/util/OidTree$Node; 2.6% 1218k 38978 -39k monfox/toolkit/snmp/agent/ext/table/SnmpMibTableAdaptor$AdaptorMibNode 1.2% 555k 7069 +0k java/lang/Class 0.5% 225k 3213 -2k java/util/TreeMap$Entry .........truncated......... 46258kB total --- --------- End of Detailed Heap Statistics --- ------------------- Printing heap --------------------- "o"/"p" = 1k normal/pinned objects "O"/"P" = 50k normal/pinned objects "."/"/" = <1k br="" fragmentation="" normal="" objects="" pinned="">" "/"_" = 1k/50k free space ------------------------------------------------------- OOOOOOOOOOOOOOOOooooooooooooooooooo.oooooooooooo.. 0x8ccb5e8 ..o.oooooooooooooooooo.O.............OOooooooooooo 0x8cfb770 ooooooooooo.Oooooooooooooooooooooooooooooooooooooo 0x8d13a28 .........truncated......... __________________________________________________ 0x28a36420 ____________________________________ 0x28bfd178 -------------- Done printing heap --------------------- --- Verbose reference objects statistics - old collection -------- 456.7 MB free memory (of 512.0 MB) after last heap GC, finished 0.137 s ago. Soft references: 326 (146 only soft reachable, 0 cleared this GC) java/lang/ref/SoftReference: 215 (140, 0) 71 ( 32, 0) java/lang/reflect/Method 45 ( 45, 0) [Ljava/lang/reflect/Method; .........truncated......... Softly reachable referents not used for at least 228.349 s cleared. Weak references: 15268 (0 cleared this GC) java/lang/ref/WeakReference: 12834 (0) 11355 ( 0) java/lang/Class 888 ( 0) com/sun/jmx/interceptor/DefaultMBeanServerInterceptor$ListenerWrapper .........truncated......... Final handles: 743 (0 pending finalization, 0 became pending this GC) 244 ( 0, 0) java/util/zip/Inflater 228 ( 0, 0) java/util/jar/JarFile 48 ( 0, 0) com/rsa/jsafe/JA_RSAPublicKey .........truncated......... Weak object handles: 42096 (0 cleared this GC) 26308 ( 0) java/lang/String 12262 ( 0) sun/misc/Launcher$AppClassLoader .........truncated......... Phantom references: 366 (330 only phantom reachable, 0 became phantom reachable this GC) com/bea/xbean/store/Locale$Ref: 330 (330, 0) 330 (330, 0) com/bea/xbean/store/Cursor jrockit/vm/ObjectMonitor: 22 (0, 0) 4 ( 0, 0) weblogic/work/ExecuteThread 3 ( 0, 0) weblogic/kernel/ServerExecuteThread .........truncated......... --- End of reference objects statistics - old collection --------- Dark matter: 7207024 bytes Heap size is not locked ======== END OF HEAPDIAGNOSTIC ===========================1k>
Song for today: Turn Around by Whiskeytown
Sunday, June 14, 2009
Truly Dynamic Web Services on WebLogic using JAX-WS
In my last blog (a long time ago I know) I talked about the potential for using JAX-WS on WebLogic 10.3 to fulfil the 8 key values that I believe are important for Web Service based Messaging. I've been using JAX-WS in WebLogic a lot over the last half a year and I've been very impressed with its power. As promised, I'm now (finally) going to describe the results of my experiments, with JAX-WS Providers/Dispatchers specifically, to see if they can achieve 8 out of 8 on my scorecard. Does JAX-WS give me the power and freedom I desire when doing web services?
For the experiment, I have used a Customer based web service example, like I've used before. Using an Interface-First approach, I created a WSDL and associated XSD Schema for a fictitious "Change Customer Information" HTTP SOAP web service. Then I created the Java Web Service (JWS) implementing a JAX-WS Provider interface, rather than using a strongly-typed JAX-WS Service Endpoint Interface (SEI). To test out the integration between the WebLogic's JAX-WS runtime and WebLogic's Security sub-system, I included a WS-Policy in my WSDL to force service consumer applications to provide a WS-Security UserToken (username/password) in the SOAP header for authentication.
My code for the Provider is shown below:
I bundled this Provider JWS into a plain WAR archive and deployed to WebLogic. I then created the service consumer code as a standalone Java application. The code for this client, which uses the JAX-WS Dispatch API to locate and invoke the remote Web Service, is shown here:
Notice that I have not used any generated XML-to-Java classes for the parameters and return values from within the client or in the service itself. Once compiled and run, the client application works completely as expected, and successfully authenticates with the remote web service using the specified username/password WS-Security credentials.
Here are my observations from the experiment:
So to wrap up, how does JAX-WS in WebLogic 10.3 stack up against my 8 criteria?
Well pretty well actually. I would say 7.75 out of 8. A full score on the first 7 criteria in the list and on the 8th (integration with the host container's Security Framework), just a 1/4 point dropped. This is due to a lack of full flexibility in defining declarative or programmatic access control for a service, when using message-level authentication.
Song for today: Festival by Sigur Rós
For the experiment, I have used a Customer based web service example, like I've used before. Using an Interface-First approach, I created a WSDL and associated XSD Schema for a fictitious "Change Customer Information" HTTP SOAP web service. Then I created the Java Web Service (JWS) implementing a JAX-WS Provider interface, rather than using a strongly-typed JAX-WS Service Endpoint Interface (SEI). To test out the integration between the WebLogic's JAX-WS runtime and WebLogic's Security sub-system, I included a WS-Policy in my WSDL to force service consumer applications to provide a WS-Security UserToken (username/password) in the SOAP header for authentication.
My code for the Provider is shown below:
@WebServiceProvider( serviceName="CustomerInfoChangeService", targetNamespace="testns:custinfochngsvc", portName="CustomerInfoChangeServiceSOAP", wsdlLocation="/WEB-INF/wsdls/CustomerInfoChangeService.wsdl" ) @ServiceMode(value=Service.Mode.PAYLOAD) public class CustomerInfoChangeService implements Provider<Source> { private final static String XSD_NMSPC = "testns:custinfo"; @Resource private WebServiceContext context; public Source invoke(Source request) { try { // Check some security stuff System.out.println("Service invoked with principal: " + context.getUserPrincipal().getName()); System.out.println("Is in Administrators group? " + context.isUserInRole("Administrators")); // Process request Transformer transformer = TransformerFactory.newInstance().newTransformer(); StreamResult sysOutStream = new StreamResult(System.out); System.out.println("Changing following customer info:"); transformer.transform(request, sysOutStream); System.out.println(); // INVOKE REAL XML PROCESSING AND CUSTOMER DB UPDATE LOGIC HERE // Construct response String responseText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<CustomerInfoChangeAcknowledgement xmlns=\"" + XSD_NMSPC + "\">" + " <Ack>SUCCESS</Ack>" + " <Comment>Successfully processed change for customer</Comment>" + "</CustomerInfoChangeAcknowledgement>"; return new StreamSource(new StringReader(responseText)); } catch (Exception e) { throw new WebServiceException("Error in Provider JAX-WS service", e); } } }
I bundled this Provider JWS into a plain WAR archive and deployed to WebLogic. I then created the service consumer code as a standalone Java application. The code for this client, which uses the JAX-WS Dispatch API to locate and invoke the remote Web Service, is shown here:
public class CustomerInfoChangeClient { private final static String WSDL_URL_SUFFIX = "?WSDL"; private final static String WSDL_NMSP = "testns:custinfochngsvc"; private final static String WSDL_SRVC_PORT = "CustomerInfoChangeServiceSOAP"; private final static String WSDL_SRVC_NAME = "CustomerInfoChangeService"; private final static String XSD_NMSP = "testns:custinfo"; private final static String USERNAME = "weblogic"; private final static String PASSWORD = "weblogic"; public static void main(String[] args) { if (args.length <= 0) { throw new IllegalArgumentException("Must provide endpoint URL arg"); } try { new CustomerInfoChangeClient(args[0]); } catch (Exception e) { e.printStackTrace(); } } public CustomerInfoChangeClient(String endpointURL) throws IOException, SAXException, TransformerException, ParserConfigurationException { // Construct request String requestText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<CustomerInfo xmlns=\"" + XSD_NMSP + "\">" + " <Id>1</Id>" + " <Address1>6</Address1>" + " <PostCode>AB1 2YZ</PostCode>" + "</CustomerInfo>"; Source request = new StreamSource(new StringReader(requestText)); // Invoke service operation, adding appropriate credentials Service service = Service.create(new URL(endpointURL + WSDL_URL_SUFFIX), new QName(WSDL_NMSP, WSDL_SRVC_NAME)); Dispatch<Source> dispatcher = service.createDispatch(new QName( WSDL_NMSP, WSDL_SRVC_PORT), Source.class, Service.Mode.PAYLOAD); Map<Object, String> rc = ((BindingProvider) dispatcher). getRequestContext(); List<CredentialProvider> credProviders = new ArrayList<CredentialProvider>(); credProviders.add(new ClientUNTCredentialProvider(USERNAME.getBytes(), PASSWORD.getBytes())); rc.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders); //rc.put(BindingProvider.USERNAME_PROPERTY, USERNAME); //rc.put(BindingProvider.PASSWORD_PROPERTY, PASSWORD); Source response = dispatcher.invoke(request); // Process response Transformer transformer = TransformerFactory.newInstance(). newTransformer(); StreamResult sysOutStream = new StreamResult(System.out); System.out.println("Change customer service result:"); transformer.transform(response, sysOutStream); System.out.println(); } }
Notice that I have not used any generated XML-to-Java classes for the parameters and return values from within the client or in the service itself. Once compiled and run, the client application works completely as expected, and successfully authenticates with the remote web service using the specified username/password WS-Security credentials.
Here are my observations from the experiment:
- In the simple example I just used StreamSource for processing the XML request and responses at both ends. However, I could have used other APIs such as DOMSource, JAXBSource, SAXSource, StAXSource from the Java 1.6 standard 'javax.xml.transform' packages instead (and even mixed and matched these for the request and the response).
- I have used javax.xml.transform.Source for accessing the SOAP request and response messages, instead of javax.xml.soap.SOAPMessage. With Source I can only access the contents of the SOAP Body (refered to as the 'PAYLOAD'). With SOAPMessage, I can choose to access the XML elements of the SOAP Envelope (including SOAP headers) as well (refered to as the 'MESSAGE'). However using SOAPMessage restricts me to only being able to process XML using the W3C DOM API, therefore using Source appeals to me more. When using Source, if I need to access SOAP Headers, I'd probably just use JAX-WS Protocol Handlers anyway, to process these headers before or after my main Provider class is called.
- I don't need to use WebLogic's WSDLC, JWSC or ClientGen Ant tasks because no "build-time" generation of Java classes (using JAXB) or stubs/skeletons is required. For my service, I could have still optionally used JWSC to generate a deployable WAR file with the appropriate web.xml deployment descriptor auto-generated, but I chose to create these artefacts myself, in a way that I can control, using simple Ant build.xml tasks.
- To ensure that my JAX-WS service is detected properly by the WebLogic runtime, the key thing I needed to do was create a Servlet definition and mapping entry in my web.xml deployment descriptor for my JWS Provider class (even though a provider class does not actually implement javax.servlet.Servlet). During deployment, the WebLogic Web Service Container automatically detects that the web.xml declared servlet is infact a JWS class and automatically maps the URL specified to an internal WebLogic JAX-WS handling Servlet called "weblogic.wsee.jaxws.JAXWSWebAppServlet". As a result, my transport-protocol agnostic SOAP JWS class is now exposed over HTTP. My web.xml file includes the following:
<servlet> <servlet-name>CustomerInfoChangeService</servlet-name> <servlet-class>test.service.CustomerInfoChangeService</servlet-class> </servlet> <servlet-mapping> <servlet-name>CustomerInfoChangeService</servlet-name> <url-pattern>/CustomerInfoChangeService</url-pattern> </servlet-mapping>[UPDATE 19-Jun-09: Actually after some further testing, I discovered that if I omit the servlet definition/mapping from my web.xml, the JWS Provider web-app still deploys and runs correctly. WebLogic automatically maps the Provider it discovers on deployment, to a URL which is the Provider class's name (without package name prefix and without .class suffix). This is in-line with the JavaEE 1.5 - Servlet 2.5 spec, where deployment descriptors are now optional. However, it may still be desirable to create a servlet definition/mapping in web.xml to be able to better control the URL of the service).]
- I would have ideally liked to have included a @RolesAllowed() annotation in my Provider class to help declaratively restrict access to service operations based on role. However, the JAX-WS specification doesn't currently cater for this annotation and WebLogic's JAX-WS implementation does not process this annotation, if its included.
- In addition to testing authentication using message-level security (eg. a WS-Security user token) I also tested authentication via transport-level security using a client provided HTTP Basic Authentication token (see commented out lines of code in the client app above). In both cases, authentication worked properly, and in my Provider class, when I call context.getUserPrincipal() the proper authenticated principal user object is returned.
- However, when using context.isUserInRole("Administrators")) in my Provider class, "true" is only returned when using transport-level security, but not when using message-level security. This means that for message-level security, performing programmatic access control is currently limited to checking the user principal object only - the user's roles can't be queried. Here was the security role I defined in web.xml:
<security-role> <role-name>Administrators</role-name> </security-role>...and here is how I mapped the role to my WebLogic EmbeddedLdap 'Administrators' group in weblogic.xml:
<security-role-assignment> <role-name>Administrators</role-name> <principal-name>Administrators</principal-name> </security-role-assignment>
So to wrap up, how does JAX-WS in WebLogic 10.3 stack up against my 8 criteria?
Well pretty well actually. I would say 7.75 out of 8. A full score on the first 7 criteria in the list and on the 8th (integration with the host container's Security Framework), just a 1/4 point dropped. This is due to a lack of full flexibility in defining declarative or programmatic access control for a service, when using message-level authentication.
Song for today: Festival by Sigur Rós
Friday, October 10, 2008
Web Service Messaging Nirvana
Web Services and specifically SOAP has got a bad rap in recent years, believed to be yet another over-hyped remote procedure call (RPC) protocol, and not cool enough in light of more current hip approaches like REST. Some of this flak is justified and the SOAP community does itself no favours when it releases a newer version of a spec (SOAP 1.2) which goes out of its way to state that SOAP is no longer an acronym. What next? TAFKAS? (The Artist Formerly Know As SOAP)
Anyway, I digress. I blogged in the past about two main areas where SOAP can be used. As you might guess, the main area that interests me is Messaging.
Over the last few years, I've been on a quest to explore how a JavaEE architect and developer can better implement messaging based web services and service consumers in a more loosely coupled and less error prone way. My motivation has been driven by a reaction to the traditional RPC based Web Services programming model that many have used and still use today and all the problems that such a model brings.
Over time I have constructed a list of 8 key values or principles that I believe are necessary for achieving "Web Services Messaging Nirvana". In most cases, these principals are based more on architectural and development approach, than the specific technology or SOAP toolkit used. However, as always, the two can't be completely divorced from each other..
Here's my 8 key values:
In the past, with J2EE 1.2, 1.3 and 1.4 compatible application servers, these values have been very hard to achieve with the application server's built-in SOAP support (ie. JAX-RPC - oriented around the concept of RPC, skeletons, stubs, and generated Java types) or with a Third-Party SOAP Toolkit (eg Apache Axis - little integration with the container's underlying Security Framework).
As a result, on these platforms, I've struggled to be able to get anywhere near achieving my goal of hitting the 8 key values of my Web Service quest.
JavaEE 1.5 introduced the JAX-WS API which is the newer Web Services toolkit for JavaEE developers. The focus of this standard, in my opinion, is still largely based on RPC and generated Java types. However, it does offer a glimmer of hope in form of the option of using a 'dnyamic' server side API (Provider interface) and client-side API (Dispatcher interface).
To my eyes the Provider/Dispatcher facility could finally give me a chance of achieving the 8 key values in a real Web Services based solution.
Version 10.0 of WebLogic was the first version to introduce JAX-WS, but at the time lacked integration with WebLogic's Security Framework and WS-Security and SAML support, thus lessening its relevance to many solutions where securing web services was a key requirement. Many users continued to use WebLogic's JAX-RPC stack due to the need to leverage Weblogic security.
Things have now changed and the JAX-WS implementation in version 10.3 of WebLogic should address this. I hope to blog soon about my experiments with JAX-WS Providers/Dispatchers in WebLogic 10.3 and my quest to realise my 8 key values of Web Services Messaging Nirvana.
Song for today: Burn Baby by Mother Tongue
Anyway, I digress. I blogged in the past about two main areas where SOAP can be used. As you might guess, the main area that interests me is Messaging.
Over the last few years, I've been on a quest to explore how a JavaEE architect and developer can better implement messaging based web services and service consumers in a more loosely coupled and less error prone way. My motivation has been driven by a reaction to the traditional RPC based Web Services programming model that many have used and still use today and all the problems that such a model brings.
Over time I have constructed a list of 8 key values or principles that I believe are necessary for achieving "Web Services Messaging Nirvana". In most cases, these principals are based more on architectural and development approach, than the specific technology or SOAP toolkit used. However, as always, the two can't be completely divorced from each other..
Here's my 8 key values:
- Promote Interface/Contract-First Development
- “Implementation-First” leads to tight coupling between the code in the service provider and the code in the service consumer
- "Implementation First" leads to a strong dependency on the initial SOAP toolkit used for implementation, which is then difficult to migrate off and leads to the difficulties of vendor lock-in
- Enable a Message-Passing Programming Model
- RPC programming leads to lots of find grained 'chatty' services where brittle pairings exist between provider and consumer which are resistant to change
- RPC clients tend to assume endpoints are implementations when in reality, they may just be messaging intermediaries (eg. a service bus)
- De-couple “Service Interface Definition” from “Message Document Definition”
- In-lining XML type definitions inside a WSDLs prevents re-use of the message structure definitions across multiple web services and other components in the system as a whole (import external Schemas instead)
- The message document structures may already be pre-defined in the organisation (eg. industry-wide standard schemas), so the ability to share these definitions across many web services is required
- Promote Postel’s Law: “Be conservative in what you do; be liberal in what you accept from others”
- In other words, allow developers to create services with strongly defined interfaces, yet forgiving implementations
- Service intermediaries and end-points may only care about using part of the message content - they should not concern themselves about trying to validate other parts of a message
- Enable minor interface version additions without necessarily requiring an upgrade or change to the service provider or service consumer
- Avoid the need for manually generated static stubs and skeletons
- These are invariably an unnecessary time-consuming addition to the development and build process
- Interface modification always requires re-generation of stubs, skeletons and Java types, forcing service providers and consumers to need to always be corrected, re-compiled and re-deployed.
- A requirement for Skeletons and Stubs is unlikely when generated Java types are not being used in the implementation
- Separate data from the code that operates on it
- Object-oriented programming is great for service implementations but not for de-coupling disparate elements of the higher level distributed systems that are based on the principle of passing messages or events around
- Enable message data to be passed between systems without one system caring about or pre-empting how the other system may use and operate on the message’s content
- Provide the developer with a choice of XML Tools to use
- SOAP Toolkits which force messages to be marshalled into a strongly typed Java graph of objects, results in one and only one way that the programmer can operate on the data
- If only part of a message is required or performance is key, a developer should have the option to use a SAX parser, a Streaming parser or just an XPath based Java API to query and operate on the data
- If XQuery or XSLT offers some developers a better abstraction and quicker development process then don't prevent a developer from being able plug in this option
- Retain the choice of being able to generate strongly types Java objects for situations where the developer needs or prefers it, but enable the developer to choose the technology (eg. JAXB, XmlBeans)
- Integrate with the host container's Security Framework for Web Services Security
- For an application server based production environment, the server's Security Framework is already likely to be plugged into the organisation's larger security infrastructure (inc. LDAP, Kerberos, PKI and other elements) to provide full support for authentication, access control, single sign-on, identity propagation, encryption and signing. This infrastructure needs to be leveraged by the SOAP Toolkit, not ignored
- The SOAP Toolkit needs to delegate to, or at least share its security context with, the host container, especially for its support of WS-Security and SAML
In the past, with J2EE 1.2, 1.3 and 1.4 compatible application servers, these values have been very hard to achieve with the application server's built-in SOAP support (ie. JAX-RPC - oriented around the concept of RPC, skeletons, stubs, and generated Java types) or with a Third-Party SOAP Toolkit (eg Apache Axis - little integration with the container's underlying Security Framework).
As a result, on these platforms, I've struggled to be able to get anywhere near achieving my goal of hitting the 8 key values of my Web Service quest.
JavaEE 1.5 introduced the JAX-WS API which is the newer Web Services toolkit for JavaEE developers. The focus of this standard, in my opinion, is still largely based on RPC and generated Java types. However, it does offer a glimmer of hope in form of the option of using a 'dnyamic' server side API (Provider interface) and client-side API (Dispatcher interface).
To my eyes the Provider/Dispatcher facility could finally give me a chance of achieving the 8 key values in a real Web Services based solution.
Version 10.0 of WebLogic was the first version to introduce JAX-WS, but at the time lacked integration with WebLogic's Security Framework and WS-Security and SAML support, thus lessening its relevance to many solutions where securing web services was a key requirement. Many users continued to use WebLogic's JAX-RPC stack due to the need to leverage Weblogic security.
Things have now changed and the JAX-WS implementation in version 10.3 of WebLogic should address this. I hope to blog soon about my experiments with JAX-WS Providers/Dispatchers in WebLogic 10.3 and my quest to realise my 8 key values of Web Services Messaging Nirvana.
Song for today: Burn Baby by Mother Tongue
Subscribe to:
Posts (Atom)