Thursday, April 12, 2012

Using Chainsaw to view Servicemix logs

Chainsaw is an open-source GUI-based log viewer. If you’ve ever wanted to utilize chainsaw to view Servicemix log file then this post is for you!
I use FuseSource distribution of Servicemix (aka Fuse ESB.
You can download Fuse ESB here:
I was able to visualize the Servicemix logs inside the Chainsaw GUI using the following steps:
1)      Install Chainsaw.
Download the latest distribution of chainsaw.
I downloaded the “Unix/Dos standalone version”
Extract to location of choice.
2)      Configure Chainsaw to listen for logging events on a given port.
Into the directory where I extracted chainsaw, I created a file “chainsaw-config.xml” with the following contents.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration >
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
    <plugin name="SocketReceiver"
class="org.apache.log4j.net.SocketReceiver">
       <param name="Port" value="4445"/>
    </plugin>
   <root>
      <level value="debug"/>
   </root>
</log4j:configuration>

The above configures chainsaw with a SocketReceiver that will listen on port 4445 to receive logging events.

3)      Configure Servicemix to send logging events.

Now to configure Servicemix to send logging event to this port you will update the Servicemix configuration. Edit the config file ‘org.ops4j.pax.logging.cfg’. Use the following as a guide for editing this file:

# the below line is an ‘edit’ of exising line – added a Chainsaw appender

log4j.rootLogger = INFO, sift, Chainsaw, osgi:VmLogAppender


# the below are completely new lines to configure the Chainsaw appender

log4j.appender.Chainsaw = org.apache.log4j.net.SocketAppender

log4j.appender.Chainsaw.remoteHost = localhost

log4j.appender.Chainsaw.port = 4560

Make sure the “remoteHost” is the IP for the machine where you are running Chainsaw (or localhost) if you plan to run Chainsaw GUI on same box as Servicemix. Once you save this file the changes will take effect immediately, should be no need to restart Servicemix.
You may see Servicemix complain about not being able to find a receiver for its events. That’s because you don’t have Chainsaw up yet. Don’t worry Servicemix will retry again once you stand up the Chainsaw GUI.
4)      Bring up Chainsaw
From the directory where you installed chainsaw, run the file ‘chainsaw.bat’.
When you start first time it will give you a warning about not having Receivers defined. You can select “Let me use a simple Receiver:” and select “SocketReceiver” on port “4560 (Default SocketAppender port.)”
5)      View the logs in Chainsaw
Since we are experimenting, you may want to turn up the logs in Servicemix to prove all the logs are reaching Chainsaw.

From the Servicemix console type:
log:set DEBUG root

This will turn up the logging to highest level.

Once Servicemix sends an event. You will eventually see a tab pop up in Chainsaw that contains the logs it receives from the Servicemix instance. You should see quite a bit of logging being displayed in Chainsaw.




To turn off the excessive logging in Servicemix and return Servicmix to the default logging level, from the Servicemix console type:

log:set INFO root

I'm not totally convinced yet whether this will be a useful capability. I'm open to suggestions on how this might be used, or whether people are using this sort of thing at all. I'm a little disappointed in the overall model, that is Servicemix must be configured to send logs to Chainsaw.



Monday, March 12, 2012

A Generic Pass-Through Route to solve a variety of Integration Challenges

Have you have ever needed to write a proxy (pass-through) route? This scenario applies to situations where you receive an HTTP request from a client, and simply need to redirect that HTTP request to another back-end server, returning the response from back end to the original client.

You might want to add some custom processing  or transformation to the message (or not) before sending to the back end service. Camel makes it easy to add such custom processing. I’ve seen cases where the simple ability to log and provide a “point of record” was enough to warrant the use of a pass-through route.  Another use for a pass-through would be to “fix” a request message  (so that it contains expected payload) before sending it on to the server – or manipulating a response into a suitable format for the client.  You can imagine a pass-through route that doesn’t touch requests coming from newer clients, but that can update requests (on the fly) that come from legacy clients so that those messages adhere to newer version, and eliminate need to maintain older back end server. 

So now that we’ve established the usefulness of a pass-through pattern – I will show you an easy way to implement this pattern. Apache Camel makes it very easy to write a route that implements the pass-through pattern. Here I will descried the steps of to create such a pass-through route is just a matter of minutes. You can create a new FUSE Project using the FUSE IDE. You can download FUSE IDE from here:

Once installed, FUSE IDE will allow you to easily create any type of route.

Below is the spring configuration that implements the proxy route.



<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:camel="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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



       <camelContext xmlns="http://camel.apache.org/schema/spring">

              <route>

                     <from uri="jetty:http://0.0.0.0:5012/proxy/incoming" />

                     <to uri="log:com.fusesource.proxytest?level=DEBUG&amp;showAll=true&amp;multiline=true&amp;showBody=true" />

                     <removeHeaders pattern="CamelHttp*"/>

                     <removeHeader headerName="Host"/>

       

                     <to uri="jetty:http://localhostt:3000/myservice/send" />

              </route>

       </camelContext>



</beans>

From the example, you can see the incoming component is the camel jetty. The Outgoing is also camel jetty.

The reason for the “removeHeaders” is basically to remove all the CamelHttp* headers that get populated by the incoming camel jetty consumer. Because certain headers get automatically populated and retained as the exchange passes through the route, the existence of these headers could potentially confuse and impact the behavior of the outgoing camel jetty producer. When certain headers are not removed, The outgoing jetty producer component (that sends requests to back end) gets confused, potentially over-riding the value configured for destination URL,  and you can end up with unexpected value for actual endpoint destination URL used by consumer component. Take care with these CamelHttp* headers and my advice is remove them in routes that go from jetty consumer to  jetty producer.  The basic idea is explained here:


You may be tempted to use the Camel HTTP component (camel-http) rather than 'jetty' for calling the back end in your pass-through route. The 'jetty' producer component has better performance under load, so it is almost always the right choice for this pattern.

The Jetty HTTP client endpoint uses the Jetty library to implement a HTTP client. In particular, the Jetty HTTP client features support for HttpClient thread pool and non-blocking request/response.  See more info on benefits of the Camel 'jetty' producer component in the FUSE documentation for writing a pass-through route .

I’m attaching a working example. If you want to play with working code - you can download it from here.
The the following sub-projects:
proxytest - A maven project that implements the route. To build run 'mvn install'. To run the route in standalone mode you can type 'mvn camel:run'.

mockservice - A simple mock server that mimics a real back end service. Your pass-through route can use this to redirect requests to in the absence of a real back end service. To build type 'mvn install'. To run the mock service in standalone mode you can type 'mvn camel:run'.

Included, is a sample SOAP UI client project (see proxytest\proxy-test-soapui-project.xml) that you can import into SOAP UI, and use to send HTTP request into the route. The route will receive the request on port 5012, redirect to the mock service listening on port 3000. The mock service will simply echo back the request. The route will then return the response back to the original SOAP UI client.  You can use SOAP UI to perform load tests on your new proxy service!