Tuesday, April 1, 2014

New components in Camel 2.13.0

Camel 2.13.0 was out for about a week, I hope it's not too late to share the high lights of Camel 2.13.0 in my blog :)

There are about 7 new added components: camel-hdfs2, camel-infinispan, camel-jgroups, camel-kafka, camel-optaplanner, camel-splunk, camel-swf.

It is interesting that the most of these components are for Cloud or BigData. But I want to brief these new added component differently.

As main contributor of Apache Camel, it's amazing to see the power of community which drives us to know more and more interesting projects, camel-optaplanner, camel-splunk, camel-kafka are these components. It comes from community contribution and keeps shaping by the hands from the community. 

Now Apache Camel hosts more than 100 components. As Camel wants to give the user full control of integration choice, Camel even provides components of same functions which are implemented by different third party projects. camel-infinispan  is a memory cache component which is much like camel-hazelcast

Apache Camel cannot host some third part components due to the license issue, so we created camel-extra to give a home for these components. It's good to see more and more third part projects move to ASLv2, which means we can host these kind of components in Apache Camel. camel-jgroups is part of Apache Camel now.

We also did some bug fixing and enhancement, you can find more information in the release note and the JIRA report




Thursday, September 12, 2013

Apache Camel 2.12.0

Camel 2.12.0 was released this week. Now I just want to spend few minutes to introduce some high lights of this release.

First it is amazing that we added about 16 new components in Camel 2.12.0, and most of these components were contributed from the user who write these components for their daily work.

camel-disruptor is leveraging LMAX Disruptor to provide the SEDA behavior in Camel, you can treat it as the replacement of the camel-seda. The big difference between camel-disruptor and camel-seda is that camel-disruptor is using the disruptor's ring buffer to store the message and camel-seda is using JDK memory queue to to store the message. If you have lots of worker thread need to be coordinated with the message flow, you can consider to use camel-disruptor to save you lots of time.

Lots of camel user are interesting about integrating their application with the social network API, now we have camel-yammer, camel-facebook to help you interact with these social network system. If your boss wants you to use camel to write some integration code with salesforce, the camel-salesforce could be your first choice.

For the other components, one of them is supporting new version of third part library, such as camel-quartz2, some of them are supporting other protocol such as camel-rabbitmq, camel-stomp, camel-netty-http.

There are also some improvements on the camel-core side to make camel more easy to use

  • Reduced stack-frames in use during routing, that also makes Camel's stack traces being logged much less verbose. This also allows people to easier debug the internals of Camel as less AsyncCallback callbacks are in use during routing.
  • Easy to use Message History out of the box. And included message history as "route stack-trace" when exceptions logged by Error Handler to make it easier for end users to spot where the exception occurred.
  • Stream caching configuration become easier by using StreamCachingStrategy which allows spool directory per Camel Context instead of shared per JVM. And you can see the stream insight at run time by using JMX management.
  • Polling Consumers such as File, and FTP now supports using custom scheduler.Providing a new Quartz2, and Spring based out of the box, that allows to use CRON based scheduler.
  • New class org.apache.camel.util.toolbox.AggregationStrategies as a starting point to obtain commonly used Aggregation Strategies for Multicast, Splitter, Aggregator, etc. EIPs.
  • New FlexibleAggregationStrategy serving as a one-stop to perform typical aggregation strategy logic out-of-the-box: filtering results, storing them in properties, headers or bodies, as a list, casting results, etc.
  • Camel 2.12.0 also supports to setup the AggregationStrategy in POJO way.
  • Added support for XML Encryption 1.1 algorithms in the XMLSecurity data format. It is now possible to specify stronger digest algorithms when using RSA OAEP Key Transport algorithms.
If you want to go through the detail changes, you can find more information from the release note and change log.

Thursday, January 27, 2011

How to map the SOAP fault message with a custom exception?

I was working on some customer issues about throwing a SOAP fault back to the client in CXF recently. It made me think it's a common issue that I should blog about it.
First, what does the SOAP Fault message look like ?











Just like the SOAP message, the SOAP fault has a generic message structure,  it consists of faultcode, faultstring and detail elements.

How can SOAP fault message turn into a custom Exception that you can you can use in the Java world? The key is the child element of the detail element.
From the upper example, you can see there an UnknownPersonFault element in the detail element, and this Fault message will be mapped to the UnknownPersonFault exception as we want when  the CXF client receives this message.

Let's take a look at the UnknowPersonFault Java code to see how this part works.

package org.apache.camel.wsdl_first;

import javax.xml.ws.WebFault;
@WebFault(name = "UnknownPersonFault", targetNamespace = "http://camel.apache.org/wsdl-first/types")
public class UnknownPersonFault extends Exception {
    public static final long serialVersionUID = 20110126200613L;
    
    private org.apache.camel.wsdl_first.types.UnknownPersonFault unknownPersonFault;

    public UnknownPersonFault() {
        super();
    }
    
    public UnknownPersonFault(String message) {
        super(message);
    }
    
    public UnknownPersonFault(String message, Throwable cause) {
        super(message, cause);
    }

    public UnknownPersonFault(String message, org.apache.camel.wsdl_first.types.UnknownPersonFault unknownPersonFault) {
        super(message);
        this.unknownPersonFault = unknownPersonFault;
    }

    public UnknownPersonFault(String message, org.apache.camel.wsdl_first.types.UnknownPersonFault unknownPersonFault, Throwable cause) {
        super(message, cause);
        this.unknownPersonFault = unknownPersonFault;
    }

    public org.apache.camel.wsdl_first.types.UnknownPersonFault getFaultInfo() {
        return this.unknownPersonFault;
    }
}

Wait a minute, why there is another UnknownPersonFault? Let's dig into the new found one.
package org.apache.camel.wsdl_first.types;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="personId" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "personId"
})
@XmlRootElement(name = "UnknownPersonFault")
public class UnknownPersonFault {

    @XmlElement(required = true)
    protected String personId;

    /**
     * Gets the value of the personId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getPersonId() {
        return personId;
    }

    /**
     * Sets the value of the personId property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setPersonId(String value) {
        this.personId = value;
    }

}

Oh, this one is the real UnknownPersonFault which can be used by JAXB to marshal and unmarshal the message. And it is wrapped by an exception which is annotated with @WebFault. This @WebFault will be helpful when CXF wants to create a custom exception from a SOAP fault message. Because CXF can look up the detail child element QName for it.

And when CXF tries to marshal this custom exception, it can easily write the detail child element by marshaling the exception.getFaultInfo().So when we throw the exception from the SEI , we should use the wrapped exception instead of the JAXB annotated class which is not a real exception, and you also need to pass the JAXB fault class instance into the exception to fill the detail element like this.
org.apache.camel.wsdl_first.types.UnknownPersonFault faultDetail = new org.apache.camel.wsdl_first.types.UnknownPersonFault();
                        faultDetail.setPersonId("");
                        UnknownPersonFault fault = new UnknownPersonFault("Get the null value of person name", faultDetail);
                        throw fault;
    
If the detail element has no child element, the CXF client will just create a common  SOAPFaultExceptionbecause it has no idea about how to map the SOAP Fault message into a custom exception.

Wednesday, October 13, 2010

The Book review of OSGi in Action

After finished the technical proofreading of Camel in Action, I finally got some time to write a review of OSGi in Action.

Just like the Camel in Action, Manning invited the committers of Apache project to write the OSGi book. As you know Apache Felix is an OSGi specification implementation, so the writers have the first-hand real world experience of the technology. They tell you not only what you can do with OSGi but also why the OSGi was designed as it is.

The first chapter of this book is free for download, with it you can have brief overview what is OSGi, and see the simple example with it.

If you take a look at the Chapter2, you can get the a deep understand for the OSGi modularity. Why the modularity is so important to software development, what's the shortcoming of the Java package, and how OSGi make a great improvement by creating a bundle with the metadata. With this fundamental knowledge you will grasp the sprit of OSGi modularity.

In Chapter3, the writer give us a whole lifecycle picture of the bundle which is another key part of OSGi. By leveraging this lifecycle API, your bundle isn't a set of classes, they can interact with each other by using the services at the runtime. In Chapter4, you can know how OSGi dynamically works to bring all the services work together.

I highly recommend you to go through the first 4 chapters of the OSGi in Action even if you have some working experience of the OSGi. The writer draws a whole picture of the OSGi technology by give a good explanation from three perspective of OSGi, modularity, lifecycle and services. These information can guide you a right direction when you feel lost in OSGi world.

If you need to build a bundle yourself, or you need to fix the weird exceptions of bundles, please take a good look at the Chapter5 and 6. They can tell you how the bundle metadata works, and what the fragment bundles are and what they can do.

Testing and debugging are a daily part of development, but OSGi has some unique characteristics that makes these tasks more difficult using your normal java development experience. There are some tools and framework can help to do it better. Chapter7 and 8 can definitely give you the handy testing and debugging experiences.

When you deploy the bundle into OSGi platform, there are still some tips you should know about. Chapter 9, 10 can tell you how to manage the bundles and application. By knowing these information, you will have confidences to export to the OSGi jungle and successfully battle the OSGi runtime monster.

If you want to know how to design or architect your OSGi application, there are some general ideas of of the component orientation things you should know in Chapter11, and you can make the best usage of the OSGi by applying the component orientation principles.

I really love the first 10 chapters, they help me greatly in understanding more about the OSGi. The other part of this book covered some advance topics, such as the Blueprint, iPOJO, launching and embedding an OSGi Framework, security, web application etc. They are the interesting topics, but they are too complexed to be covered with just few sections. OSGi Enterprise specifications are also working on these areas, you can get some basic idea about these topics by reading the chapter 12,13,14,15.

If you want to visit the OSGi world and have some success there, OSGi in Action could be a good choice for you :)

Thursday, September 30, 2010

CXF Continuation API Enhancement

From Web 2.0, there are more and more long time connections are used by client to access the back end system, and they will consume lots of thread if the server is working on per thread per request mode. Jetty 6 introduced the Continuation API to resolve the this problem.

Few years ago CXF provides the same kind of continuation API to let the user have a chance to release the request thread if the response is not ready. This feature is very important if you want to keep your application with a good performance and good scalability.


As we did some house clean up from Camel 2.4.0 to make sure the Camel component has the best usage of the Camel Async Route Engine, I did some work on camel-cxf recently. I just found current CXF continuation which suspending is implemented by throw the runtime exception. This implementation has a shortcoming which cannot call the other framework's async API after continuation suspend is called as Jetty7 does. This will introduce a situation that continuation resume will be called before the continuation suspend is called.
To avoid this bad situation which will make suspended continuation never resumed, I had to write my Camel code like this

private Object asyncInvoke(Exchange cxfExchange, final Continuation continuation) {
synchronized (continuation) {
if (continuation.isNew()) {
final org.apache.camel.Exchange camelExchange = perpareCamelExchange(cxfExchange);

// use the asynchronous API to process the exchange
boolean sync = getAsyncProcessor().process(camelExchange, new AsyncCallback() {
public void done(boolean doneSync) {
// make sure the continuation resume will not be called before the suspend method in other thread
synchronized (continuation) {
if (LOG.isTraceEnabled()) {
LOG.trace("Resuming continuation of exchangeId: "
+ camelExchange.getExchangeId());
}
// resume processing after both, sync and async callbacks
continuation.setObject(camelExchange);
continuation.resume();
}
}
});
// just need to avoid the continuation.resume is called
// before the continuation.suspend is called
if (continuation.getObject() != camelExchange && !sync) {
// Now we don't set up the timeout value
if (LOG.isTraceEnabled()) {
LOG.trace("Suspending continuation of exchangeId: "
+ camelExchange.getExchangeId());
}
// The continuation could be called before the suspend
// is called
continuation.suspend(0);
} else {
// just set the response back, as the invoking thread is
// not changed
if (LOG.isTraceEnabled()) {
LOG.trace("Processed the Exchange : " + camelExchange.getExchangeId());
}
setResponseBack(cxfExchange, camelExchange);
}

}
if (continuation.isResumed()) {
org.apache.camel.Exchange camelExchange = (org.apache.camel.Exchange)continuation
.getObject();
setResponseBack(cxfExchange, camelExchange);

}
}
return null;
}



As you know CXF has lot of interceptor which can chained together as a SOAP stack and doing the WS* work, if we can suspend the interceptor chain, it will be easy for us to resume it from other thread. You can find a handy example from OneWayProcessorInterceptor.
My enhancement on CXF continuation API by introducing a suspend status into CXF PhaseInterceptorChain. The implementation of the CXF continuation API set the status of PhaseInterceptorChain, then the interceptor calling thread will be broke out after the interceptor handle method returns. Now my Camel code would be more easy to understand

private Object asyncInvoke(Exchange cxfExchange, final Continuation continuation) {
if (continuation.isNew()) {
final org.apache.camel.Exchange camelExchange = perpareCamelExchange(cxfExchange);
// Now we don't set up the timeout value
if (LOG.isTraceEnabled()) {
LOG.trace("Suspending continuation of exchangeId: "
+ camelExchange.getExchangeId());
}
// now we could call the suspend here
continuation.suspend(0);

// use the asynchronous API to process the exchange
getAsyncProcessor().process(camelExchange, new AsyncCallback() {
public void done(boolean doneSync) {
if (LOG.isTraceEnabled()) {
LOG.trace("Resuming continuation of exchangeId: "
+ camelExchange.getExchangeId());
}
// resume processing after both, sync and async callbacks
continuation.setObject(camelExchange);
continuation.resume();
}
});

}
if (continuation.isResumed()) {
org.apache.camel.Exchange camelExchange = (org.apache.camel.Exchange)continuation
.getObject();
setResponseBack(cxfExchange, camelExchange);

}
return null;
}

The enhanced CXF continuation API patch is committed into CXF trunk and it is part of Fuse Service FrameWork 2.3.0 now.

Monday, February 15, 2010

Configure the camel-cxf endpoint advance features from URI

As you know CXF provides the advance configuration on the CXF endpoints, such as interceptors, features etc.

In camel-cxf we leverage the CXF configuration which is based on the Spring to provide the same thing as CXF does, but in Camel we have the classical URI configuration which means you can configure the endpoint's by using the URI parameters. URI is easy way for the user as it support the DSL and Spring configuration smoothly, and you can deal with the URI as string to add your customer properties.

How can we configure the interceptor or the features on the camel-cxf endpoints by just setting few option parameters?
The key of the answer is you can set the bus of the camel-cxf endpoint by using the URI option bus.
You can set the features or interceptor on the bus as CXF bus configuration does and then set the camel-cxf endpoint URI like this "cxf://Address?Bus=#cxf&...".

Sunday, May 3, 2009

Better OSGi integration test support In Camel

Two weeks ago, James did a great work by adding an OSGi integration test module which was based on Pax Exam.

Then, I did some enhancements for this test module this week.

1. You can use the camel features to install the bundles for you test.
Instead of adding the camel-xxx module dependency in the POM for the Pax Exam plugin to setup the bundles list, we can leverage the camel features to setup the bundles that we may use in the integration test.

Here is a code example

// using the features to install the camel components
scanFeatures(mavenBundle().groupId("org.apache.camel.karaf"). artifactId("features").versionAsInProject().type("xml/features"),
"camel-core", "camel-osgi", "camel-spring", "camel-test"),


You can keep on adding the features that you need such as "camel-jms", "camel-jetty", and don't need to any modification on the module's pom.xml.

2. I added the OSGi version of the Camel TestSupport classes, so you could write the test more easily. If you are using the traditional Java DSL to setup the route rule, you just extend the OSGiIntegrationTestSupport; if you are big fan of Spring, you can extend the OSGIIntegrationSpringTestSupport, and it will take care of creating the application context in the OSGi plateform.