2012-06-20

Locking down JMX naming now easier with Camel 2.10

The Apache Camel 2.10 is on the way. In fact this morning a RC has been cut. So expect 2.10 to be released soon.


This is a blog post I have had on my todo pad for a while meant to be written sooner. Anyway I got a bit of breather this morning, and wanted to get this done before the 2.10 is released.

Background

So the issue people may have is when they run many Camel applications in the same JVM, such as in Apache ServiceMix, Apache Karaf, Fuse ESB, Fuse ESB Enterprise, Fuse Fabric, and the classic web and JEE servers such as Apache Tomcat, Jetty, JBoss, et all. Its the JMX naming.


So in the JMV we have a default JMX server in which we enlist Camel MBeans, allowing you to manage and monitor Camel apps using JMX. As there is one JMX server, and multiple Camel applications, then we need to ensure the MBeans have unique ObjectName's so they dont clash. 


Apache Camel has out of the box a liberal strategy to cater for this, and in case of a clash, it will by default, auto remedy this by computing a unique name, using a counter based approach. 


For example this may give you ObjectNames with names that contains the counter in the name such as:
...camel-1/...
...camel-2/...
...camel-3/...


The default naming strategy is to use the CamelContext id (eg name) and apply the counter in case of clash. So if you use unique CamelContext id in your Camel applications, then you already have unique ObjectName's in the JMX, and thus no clashes.


The default strategy in OSGi containers is a bit different, as the naming is prepended with the bundle id, which gives us out of the box names such as

...76-camel-1/...
...77-camel-1/...
...78-camel-1/...


And in case you have multiple Camel applications in the *same* bundle, then the naming will use the counter, like for non OSGi environments

...76-camel-1/...
...76-camel-2/...
...76-camel-3/...
...77-camel-1/...
...78-camel-1/...



Okay you have read so far, this is good. So lets get to the point where things have improved in Camel 2.10, and what you can do in previous Camel releases.


The issues is that in OSGi containers, the bundle-id would by default always be prepended, so controlling the naming was a bit harder. What you can do to remedy this in previous Camel releases is to use a custom org.apache.camel.spi.ManagementNamingStrategy, allowing you full control of the namings of the ObjectName's. The problem is that you would then need to implement this interface and code an implementation. So what we have done in Camel 2.10 is to let you configure the naming using a pattern style, much more easily.


To see this in action, lets walk through an use-case.

Walking through an example

This example is created by using the Camel Maven archetype to create a new OSGi Blueprint project, using the camel-archetype-blueprint. This is a simple example that can easily be deployed in an OSGi container such as Apache Karaf. When the project is created, I can compile and build the artifact using mvn install.


I have a vanilla Apache Karaf 2.2.7 extracted, and start it using bin/karaf.

davsclaus:/opt/apache-karaf-2.2.7$ bin/karaf
        __ __                  ____      
       / //_/____ __________ _/ __/      
      / ,<  / __ `/ ___/ __ `/ /_        
     / /| |/ /_/ / /  / /_/ / __/        
    /_/ |_|\__,_/_/   \__,_/_/         


  Apache Karaf (2.2.7)


Hit '' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '' or 'osgi:shutdown' to shutdown Karaf.


Installing Apache Camel in Karaf is now easier using the new chooseurl command as shown below:


karaf@root> features:chooseurl camel 2.10.0
adding feature url mvn:org.apache.camel.karaf/apache-camel/2.10.0/xml/features
karaf@root> features:install camel
karaf@root> 


After installing Camel I can install my application using:


karaf@root> osgi:install mvn:com.mycompany/blue/1.0
Bundle ID: 75


And then I can start the bundle by its id


karaf@root> osgi:start 75


And list the installed bundles


karaf@root> list
START LEVEL 100 , List Threshold: 50
   ID   State         Blueprint      Spring    Level  Name
[  64] [Active     ] [            ] [       ] [   50] camel-core (2.10.0)
[  65] [Active     ] [Created     ] [       ] [   50] camel-karaf-commands (2.10.0)
[  72] [Active     ] [            ] [       ] [   50] geronimo-jta_1.1_spec (1.1.1)
[  73] [Active     ] [            ] [       ] [   50] camel-spring (2.10.0)
[  74] [Active     ] [Created     ] [       ] [   50] camel-blueprint (2.10.0)
[  75] [Active     ] [Created     ] [       ] [   80] A Camel Blueprint Route (1.0.0)

Then I start JConsole to see the JMX tree
JMX name is 75-blueprintContext
My Camel application has been given bundle id 75, which mean out of the box the JMX ObjectName is pre-pended with 75.


Now the issue for some users, is that they may uninstall their applications, and then at a later time install the application again. So lets uninstall our application


karaf@root> osgi:uninstall 75

And then at a later time we install it again. Now the OSGi container will assign the bundle a new bundle id (as it will never re-use a previous bundle id). 


Notice: You can update/refresh your existing application, and keep the bundle id. Its only when you uninstall the bundle, that the bundle id, is discarded, and not used again.



karaf@root> osgi:install mvn:com.mycompany/blue/1.0
Bundle ID: 76
karaf@root> osgi:start 76


And if we see in JConsole we can see the Camel application now has a different JMX ObjectName.


JMX name is now 76-blueprintContext
So how can we control this JMX naming? Well in Camel 2.10 this is now much easier, ad we can define a naming pattern in our CamelContext directly.


There is a new managementNamePattern attribute in the as shown in the screenshot below. This pattern supports a number of tokens which we will cover in a second.
Camel 2.10 using the new managementNamePattern attribute
In this example we just want to use the CamelContext id as the JMX name, so we can use a token in the pattern, as shown using the #name# value. The following tokens is supported


  • #camelId# = the CamelContext id (eg the name)
  • #name# = same as #camelId#
  • #counter# = an incrementing counter
  • #bundleId# = the OSGi bundle id (only for OSGi environments)
  • #symbolicName# = the OSGi symbolic name (only for OSGi environments)
  • #version# = the OSGi bundle version (only for OSGi environments)


Besides the tokens you can use literals, so for example you can do managementNamePattern="foo-#symbolicName#" to have foo- as pre-prended value.

I then rebuild the project using mvn install, and from Karaf I update my application using:
karaf@root> osgi:update 76


And when I look in JConsole now, I can see the JMX naming is no longer having the bundleId prefixed.
JMX name is no longer having bundleId prefixed
The JMX naming is now locked down. This allows me for example to have any JMX capable monitoring tooling be configured once with the JMX ObjectName, and then be able to monitor my application in OSGi containers, regardless which bundle Id my application have been assigned.
Locked down JMX ObjectName
You can find some more details about JMX and Camel at the Apache documentation.


Runtime insight to Camel applications

My application is now running in Apache Karaf, and I can use the Camel Karaf commands to give me some details about my application, such as the context-info command telling me a bit about the uptime, and number of messages (is called exchanges) processed by Camel:

karaf@root> camel:context-info blueprintContext 
Camel Context blueprintContext
Name: blueprintContext
Version: 2.10.0
Status: Started
Uptime: 3 minutes
Exchanges Total: 39
Exchanges Completed: 39
Exchanges Failed: 0
Min Processing Time: 1ms
Max Processing Time: 366ms
Mean Processing Time: 11ms
Total Processing Time: 442ms
Last Processing Time: 3ms
Load Avg: 0.00, 0.00, 0.00
First Exchange Date: 2012-06-20 09:53:11
Last Exchange Completed Date: 2012-06-20 09:56:21



This is all text based, and using a tool such as Fuse IDE I can see all this in real time and visualized using EIP icons as shown below
Fuse IDE with real time visual insight of my running Camel applications in any JVM
Fuse IDE also allows me to see the installed bundles running in Apache Karaf. The bundles can be managed, for example I have stopped my blue application, indicated by the orange ball, which mean the bundle is not started, but in resolved state.
Fuse IDE can manage bundles running in the OSGi container


And know that I talk about Fuse IDE, then it has a nice terminal built-in. This is something that Windows users may struggle with normally, as they would need to use cygwin or something alike to SSH into remote machines. The terminal in Fuse IDE can connect to any remote box, or local running instances such as Apache Karaf.


Fuse IDE with SSH terminal to access Apache Karaf
Okay that's it for all the screenshot galore. Its time to go back to work. Have a nice day. And remember Apache Camel 2.10 is soon to be released, and its a killer release.

No comments: