Thursday, August 30, 2012

ServiceMix on the bleeding edge

Why stable dependencies are cool

ServiceMix (and Fuse ESB as well) are supposed to work with a specific version of Camel. For example ServiceMix 4.4.2 comes with a pre-configured Camel 2.8.5 features repository.
karaf@root> features:listurl | grep camel
  true    mvn:org.apache.camel.karaf/apache-camel/2.8.5/xml/features
The same rule is applied to the ActiveMQ and CXF dedicated for every release of the ServiceMix.

This is pretty cool approach since it guarantees you that sticking to the given version of Camel (ActiveMQ, CXF, ...) will result in a stable ServiceMix installation. ServiceMix team invested pretty lots of effort to make sure that Camel in version X works nicely on ServiceMix in version Y. Fuse ESB is tested even more, to guarantee the highest level of the product.


Why stable dependencies are NOT cool

The downside of such stable versioning strategy is that you need to wait a long time before updating to the latest version of Camel (or CXF or whatever).

For example, if I committed Spring Batch component to the Camel and it has been released in Camel 2.10, then I'll need to wait for ServiceMix to use the higher version of Camel and Karaf. In this particular example Karaf 2.2.4 included in the latest stable version of ServiceMix (i.e. 4.4.2) doesn't support Camel 2.10.
karaf@root> features:install camel-spring-batch/2.10.0
Error executing command: Can not resolve feature:
Unsatisfied requirement(s):
---------------------------
   package:(&(package=jline.console.completer)(version>=2.7.0)(!(version>=3.0.0)))
      camel-karaf-commands

Bleeding edge ServiceMix

What to do if you really need to work with the latest version of the ServiceMix stack? Download the latest version of Apache Karaf and manually add Camel (CXF, ActiveMQ, etc) support into it.

For example to use the latest Camel (i.e. 2.10) I can download the latest Karaf (i.e. 2.2.9) and arm it with the Camel 2.10 features repository.
karaf@root> features:addUrl mvn:org.apache.camel.karaf/apache-camel/2.10.0/xml/features
Then I enable feature responsible for bootstrapping Camel modules backed by Spring.
karaf@root> features:install camel-spring
At last but not least I enjoy the brand new Camel modules.
karaf@root> features:install camel-spring-batch/2.10.0
Now I can drop my integration solution using the latest Camel 2.10 into my hand-made bleeding edge ServiceMix. :)

Monday, August 27, 2012

Poster Firefox plugin - creating custom HTTP requests


The best tool I know for testing restful web services is the firefox Poster plugin.

It provides dead simple form to generate arbitrary HTTP request. You specify target URL and HTTP method you want to use (GET, POST, PUT and so forth). Of course you can also provide additional HTTP headers, parameters and request content. Good, simple tool.


Wednesday, August 22, 2012

Java API for today: ConcurrentModificationException vs CopyOnWriteArrayList

You often iterate over the collection and you rarely add something to it. This sounds like a typical scenario for the Observer design pattern.

List<Listener> listeners = new LinkedList<Listener>();
...
for(Listener listener : listeners) {
  listener.notify("Event");
}
...
public void addListener(Listener listener){
  listeners.add(listener);
}

If you interrupt iterating over the listeners by registering the new one, you will encounter the ConcurrentModificationException thrown by the iterator.

The solution is to use java.util.concurrent.CopyOnWriteArrayList.
List<Listener> listeners = new CopyOnWriteArrayList<Listener>();

In the rare cases when you modify the list of listeners, iterator will work on the snapshot of the original list (created before the modification). Listener's addition will be performed on the copy of the list, that will be eventually merged with the original one.

From now on, stop yelling about the ConcurrentModificationException thrown by your iterators.

Tuesday, August 14, 2012

Good Camel message is the immutable one

A good way to introduce a problem into your Camel-based messaging solution, is to keep mutable data in the messages you exchange.

Whenever you read that Camel creates a copy of the message (for example during the Multicast), keep in mind that we're talking about the shallow copy. Creation of the deep copy of the object in Java is complex due to the performance and logical issues. Due to these issues, Camel copies only references to the body and headers of the original messages.

// Given - multicast will copy incoming message.
from("direct:xero").multicast().to("mock:copy1").to("mock:copy2");

// When - messages has been copied
sendBody("direct:xero", "Copy me!");
Object copy1 = getMockEndpoint("mock:copy1").getExchanges().get(0).getIn();
Object copy2 = getMockEndpoint("mock:copy2").getExchanges().get(0).getIn();

// Then - messages are not the same
assertNotSame(copy1, copy2);
// But bodies of the messages are.
assertSame(copy1.getBody(), copy2.getBody());


It is easy then to create the copy of the message that logically is not a copy, since it reference the same mutable structure as the original message from which it was created.

In messaging systems payloads should be unaware of the JVM they live in. Shared Java references introduce implicit knowledge about the JVM memory model to the messages. Camel tip for today is - stick to the immutable messages whenever you can.

Friday, August 10, 2012

Failure management


When you want to improve your team, you're obviously interested in the Change Managemment. What is not so clear, is that you should be interested in the Failure Management as well.

When you're changing the team, you will fail from time to time. You will propose and try to apply some misconceived ideas. We like to see change, but don't want to admit the failure. The failure however is often the sign of the change happening.

Do you talk about the failures with your team? Do you explicitly discuss the correlation between your failures and your progress as a team?