Some readers of this blog might have noticed that my posting frequency has been somewhat reduced during the past few months. Some of this is the result of working on several different projects, some of which isn't stuff I can talk about much.
Besides my usual .NET/BizTalk work, I've been increasingly spending time working on some Java stuff as well. I would say that I probably spend my time 50/50 between both technologies nowadays. There are good and bad things about this, but that's a topic for a different post.
One of the interesting things I've worked on lately on the Java side has been implementing custom Binding Components based on the Java Business Integration (JBI) specification. JBI isn't a new technology; it's been around for a while, but until now I had not had the opportunity of working with it.
Mostly, I've been working with Sun's OpenESB, which is actually not that bad, though I've also used JBoss/ServiceMix a bit.
It took me a little while to fully grok the core of the JBI model. There are many similarities in the concepts it uses to other messaging technologies, but the terminology used can be somewhat different, which can be confusing sometimes. In case you're not familiar with JBI, it defines two different kinds of components developers might wish to implement:
- Service Engines, which are just components that do some processing and send and/or receive messages.
- Binding Components, which are mostly transport-level adapters. These are the equivalent components in JBI to BizTalk adapters and WCF's transport channels.
I'm not going to do a comprehensive comparison of JBI to BizTalk or WCF, but did want to make a few observations about some aspects that I found interesting.
The JBI spec is a fairly low-level specification. Much of the spec is really concerned with how components interact with the JBI server and how class loading and deployment work, as opposed to defining a more higher-level messaging model.
Actually, maybe I should say that the JBI spec doesn't really define abstraction layers. It's all a single layer that addresses a number of different concerns.
Most of the JBI messaging model is really defined to match the WSDL model, and there are advantages and disadvantages to this. On the plus side, the WSDL model is generic enough to be useful in a broad set of scenarios, and it is fairly well known. It also makes a lot of sense considering the terminology used throughout the spec (once you get familiar with it).
On the bad side, it means that components also have to get intimate knowledge of the WSDL contract model and this forces some compromises I personally don't quite agree with.
For example, in WCF and BizTalk, if I'm writing a transport-level adapter/channel, I may need to be intimately aware of the contract definition being used by the client/server. But it's not really necessary most of the time, particularly when you're working with network-level transports. Mostly, you care about the Message Exchange Pattern (MEP) that the contract demands.
In JBI, however, you have to understand the entire contract. This might be fine for Service Engines, but it can be rather inconvenient for Binding Components, as now you have to figure out out how to map contract operations to your transport, and even how to marshal data back and forth based on the contract definition.
This leads me to my second gripe about JBI: Configuration.
Endpoint configuration in JBI is done through a combination of two things:
- The WSDL that defines the contract you'll want to receive or send messages to (extended with your binding component specific port/binding/operation configuration data)
- The deployment descriptors which tell your component if you want to receive or send messages for the corresponding WSDL file.
In reality, WSDL permeates the entire JBI development experience, including how messages are represented internally between the JBI runtime and binding components / service engines.
A huge downside of this, though is that the code needs to "understand" the contracts being used, so parsing the WSDL files and extracting your component's configuration data is your responsibility. Libraries like WSDL4J help, but it can still be a drag.
What does really irk me a bit about JBI though is not that you have to manually craft WSDL files (not that it's a lot of fun). It's that the JBI spec doesn't address the design time aspect of JBI components at all besides, you guessed it, manually crafting WSDL files and deployment descriptors.
So if you're creating JBI components and want a decent design time experience, then you need to target each different server/tooling specifically. For example, for OpenESB you'd craft a custom NetBeans module, while for another tool you'd do something different. It's just not nice.
What's worse is that some servers decided this model wasn't good enough either and added their own configuration models for components and contracts. For example, while ServiceMix supports the stuff mandated by the JBI spec, it also supports an alternative XML-based configuration syntax. While it's more compact, it's hard to argue it really is a significant improvement.
This is one aspect where I thought the JBI spec really blew it. As I said above, the JBI spec uses an XML representation for messages internally, that matches the WSDL message definition (parts and all).
There's no layering here that allows binding components to worry about sending and receiving messages without really caring about message contents. They have to care about the message contents and how to map that to however that message was defined in the contract WDSL definition. This might mean looking at which parts are defined and how to break the message down to them, or how to decode complex XSD types defined in the contract.
Instead of being delegated explicitly in the spec to separate components, it's all the responsibility of the binding components themselves. The obvious benefit of having this layered would've been more reusability of said encoding/decoding components, particularly if a minimum set of encoders were mandated by the spec.
Just to take one example: basic XML encoding/decoding is such a basic part of the system, that it's just really odd each component writer gets to redo it from scratch."
I think this is one aspect that BizTalk in particular gets very right. WCF does keep encoding/decoding an explicitly separate task, even if transport channels are responsible for using the encoders directly, but it is still a much better solution than what JBI came up with.