Axel Irriger, iteratec GmbH, http://www.iteratec.de
Apache ServiceMix is a runtime container for service-oriented architecture components, web services or legacy system connectivity services. It is one of the most mature, open-source implementations of an enterprise service bus and an Apache top-level project.
In this article we will take a look at what ServiceMix is and how it can be put to use.
Web Site: http://servicemix.apache.org
Version discussed: Apache ServiceMix 3.3, FUSE ESB 3.4
License & Pricing: Open Source with commercial support and packaging by FuseSource
Support: User mailing list, developer mailing list, Internet Relay Chat, FuseSource forums. Only the book "Open-Source ESBs in Action" by Manning is currently available.
Before directly starting to discuss what Apache ServiceMix can be used for, a general understanding of the enterprise service bus acronym should be given. Since it is not a framework suited for everyday usage like Spring, the general context of its application is important.
Enterprise Service Bus (ESB) principle
Apache ServiceMix is an implementation of an enterprise service bus in the Java programming language.
In a typical enterprise environment, there are several applications installed. Most probably they are from different vendors and offer very diverse interfaces. The corporate IT commonly faces two challenges these days:
- Exchange of data between different systems
- Creation of new functionality by combining existing function block from these applications
In the past, these issues were tackled by proprietary product suites, which often were highly specialized and not able to cover a wide range of corporations' needs.
The development and adoption of web service technology is thought to solve these issues, as a common transport and description format now exists. Nonetheless, this needs to be provided, implemented and supported by the applications. Also, a single call often is not sufficient, but routing and combination logic needs to be employed, as well. To simplify these tasks, Gartner came up with the idea of an infrastructure component, which uses a harmonized way of exchanging data (messages) and provided such reusable core functionality.
This component should not only exchange messages but also incorporate the ability to route messages from one component to another component. These requirements were bundled into the term "enterprise service bus" (ESB). In contrast to enterprise application integration (EAI), the ESB concept goes beyond the mere connectivity and data exchange principles and focuses on reuse. By exposing application functionality to an ESB, new applications can be built that leverage data and services already created. These are then called "composite applications", as they can be thought off as a meta-level, creating applications from applications, instead of components or frameworks. This functionality can also be leveraged without using an enterprise service bus, but for the typical everyday challenges, a bus greatly simplifies things, since it is prepackaged with components and standard functionality.
Java Business Integration (JBI)
To standardize the ESB concept, the Java Community Process (JCP) came up with the JBI standard, short for Java Business Integration. It describes all components, which can be found in the ESB concept, matched to Java terminology and interfaces.
Figure 1 Overview of Apache ServiceMix (from its homepage)
Apache ServiceMix is, among other implementations, one of the most mature and implemented ESB which adhere to the JBI standard.
Components and NormalizedMessages
The JBI standard only focuses on the basic infrastructure: it defines what a component is, what a message is and how these interact. By not reinventing the wheel, a lot of terminology and concepts have been taken from the web services world, such as the supported message exchange patterns.
If you are already familiar with web services development and are not afraid of terminology like "in-only" or "in-out", the basic ServiceMix messaging concepts will be quite familiar. Using the same terminology does not mean that ServiceMix delivers comparable functionality. In fact, itís different.
The general idea by JBI and ServiceMix is to connect external systems to the bus by converting everything consumed externally to a NormalizedMessage. This "container" holds the actual data, along with various properties, and the destination endpoint of the message. The job of the bus is to transport the message to its destination. There, if it shall leave the bus, it is converted back to what is understood by the target system.
Within ServiceMix, all components only operate on the NormalizedMessage, which typically contains some sort of XML data, but is not restricted to it. Nonetheless, it is possible to attach binary information to the message, too.
By this, software development gets more standardized and harmonized. Once the data is delivered to the bus, it doesn't matter where it came from as it is some sort of parseable content already. This sufficiently simplifies development of third party components, which can be hooked into the bus, as these only operate on a NormalizedMessage, too.
This very basic principle, extensibility by open standards, was first introduced by Sun with the J2EE specifications, focusing on the interfaces instead of actual implementations. In spite of J2EE, a substantial number of components already exist, which can be used by ServiceMix with very little effort.
The ServiceMix distribution contains several components. Besides the barebone JBI bus, ServiceMix already ships with a collection of connectivity and routing components. The most commonly used are:
- Integration with JMS, which is ActiveMQ by default, but can be any JMS compliant broker
- Integration for legacy Java Beans
- Implementation of routing functionality, by means of enterprise integration patterns (EIP)
- Support for accessing and exposing services via HTTP
- Support for consuming and exposing web services via SOAP-over-HTTP or SOAP-over-JMS
- Accessing file systems
- Using rule engines, like JBoss Rules
- Using scripting languages, like Groovy
All components for external connectivity ("binding components") come with prepackaged support for converting external data to and from XML. If this is not the desired behavior, you can customize it by implementing Java classes, which perform the conversion process. These are called marshaler and are an integral part of ServiceMix and JBI in general, too.
The principle idea of a marshaler is, that a JBI component performs a very specific task. To accomplish this, it is created and it operates only on a NormalizedMessage. To convert data to and from the NormalizedMessage, a specialized class is used, since that is no core functionality of the component and would limit its reusability.
Let's take the file binding component as an example. The core functionality is to read and write files, along with polling in intervals for new files to process. If a file is to be read, it is the function of the file binding component to lock the file, retrieve its content and send it to the bus, as a NormalizedMessage. The component does not need to know whether itís plain XML content or something binary in the file. To actually interpret the file content, a marshaler is used.
Along with these components, you can do systems integration and provide services by wiring together existing services. You can implement some standard data interchange with it, by consuming a file, for instance and sending its content to an HTTP URL. Or you can develop something entirely different, which is then published and exposed for usage within the bus itself. But before we come to that, let's first see how ServiceMix and stuff made with it is deployed.
If you want ServiceMix to work for you, the question arises, on how solutions are actually deployed.
There are three scenarios supported out of the box to deploy ServiceMix:
- Embedded within your application
- Packaged in a web archive for deployment into a web container, like Tomcat
- Used stand-alone
Besides deploying and running the container itself, it is also important to get your solutions deployed, too. For this, also two deployment models exist. The "official" deployment, defined by JBI, is the "service assembly model". A service assembly is an archive, which essentially contains everything you need to run your solution. This also is the option of choice in order to remain portable across JBI containers.
The "service assembly model" is comparable to the enterprise archive (EAR) or web archive (WAR) deployment model, already in use by J(2)EE compliant servers. It contains a descriptor of the components the service assembly is made up and, for each of these, how they are configured("service unit").
If this is too heavy-weight for your environment or need, you can perform a lightweight deployment, which is essentially only a XML descriptor in the standard XBean notation. For simple solutions, or in an embedded use case, this is for sure the easiest way to get up and running.
As explained above, the simplest way to deploy a ServiceMix solution is to use a XML descriptor. To get into this, we will now take a look at how ServiceMix is being configured.
Spring and XBean
The basic frameworks used by ServiceMix are Spring and XBean. Since at least Spring is well known these days, I will only cover XBean, with respect to ServiceMix, a bit.
The XBean framework was created by the Apache Geronimo project on top of Spring. The basic idea is to directly instantiate Java beans by defining XML tags. These tags are then mapped to Java beans by the framework and populated by Spring. By this, the XML configuration, typically used by Spring does not get that polluted with bean descriptors, but gets a cleaner and more readable syntax.
This whole magic works by delivering special files in the META-INF directory alongside your Java classes, which are processed at run time by the XBean platform. XBean leverages the Spring framework by providing its own ApplicationContext to enable resolution of these beans.
An example of a lightweight configuration may look like this:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:sm="http://servicemix.apache.org/config/1.0" xmlns:foo="http://servicemix.org/demo/"> <bean id="jndi" class="org.apache.xbean.spring.jndi.SpringInitialContextFactory" factory-method="makeInitialContext" singleton="true" /> <sm:container id="jbi" useMBeanServer="true" createMBeanServer="true"> <sm:activationSpecs> <sm:activationSpec> ... </sm:activationSpec> <sm:activationSpec componentName="filePoller" destinationService="foo:fileSender" service="foo:filePoller"> ... </sm:activationSpec> </sm:activationSpecs> </sm:container> </beans>
In the example above you see a typical Spring configuration file. At the root element, there are namespace declarations, followed by bean definitions. If you take a look at the definition in bold letters, there is an element specified, which is within the "sm" namespace. This is a XBean definition. The XML tag "sm:container" makes the XBean framework to look for meta-data information in a package servicemix/apache/org/config/1.0 for a file, in which the element "container" is resolved to a Java class. If it fails to look this up, the whole instantiation process will fail. Otherwise (the typical case), this definition is switched to the actual bean during creation of the ApplicationContext. This bean may have properties, which get set. This happens either by using XML attributes, such as "useMBeanServer", or by nesting elements. Either way does refer to setter-methods of the corresponding Java bean.
Within ServiceMix, both Spring and XBean are core frameworks for both the development and configuration of the platform. Therefore, you won't see any traditional bean definitions in ServiceMix, but you directly deal with somewhat "named beans".
Although this might look a bit strange at first it actually simplifies configuration, as it makes things more readable. You can still use the traditional Spring syntax, if you like.
Lightweight mode vs. Service Assembly (SA) mode
As described earlier, ServiceMix knows two deployment scenarios for solutions: one is the standard service assembly mode, the other one is the lightweight mode.
The biggest difference is the portability issues. With both approaches, you can develop services. With the lightweight mode, you directly wire together service components in a Spring-like fashion, which results in a tightly bound application at least from the perspective of the ApplicationContext. A configuration of this style does not support hot-deployment, for instance.
The JBI way of deployment configures each service component separately as a service unit. All necessary service units are then packaged as a service assembly. This archive is deployed using the ServiceMix deployment service. In this case ServiceMix is not another bean, but used as a runtime container.
In general, if you tend to use ServiceMix in integration-like scenarios, it's easier to use it the standard way. The deployment overhead seems to be bigger, but the manageability is simplified and you are not bound to a specific product.
Example "File to JMS to file"
To get you an idea of what can be done with ServiceMix, let's take a look at a simple EAI service. We will copy a file from directory A to directory B. To stress ServiceMix a bit more, we will put a JMS queue in-between.
Although this can be also performed with other frameworks like Apache Camel, it can also be done with ServiceMix. From the general ESB point of view, this implementation scenario is only a minor one. This gets far more interesting, if you connect legacy systems to the platform and start interacting with these. But to not overcomplicate the sample here, file copy is just fine. Just make sure you keep in mind that this could also be a coupling between Siebel and SAP or some Microsoft Dynamics and a third party web service!
To implement this in a lightweight mode, you would create a servicemix.xml file, which has the overall layout like the above sample and put your component definitions into that. Upon deployment, ServiceMix will start the components in the order they are declared in this file.
To implement this as service assemblies, you need to create a service-unit for the file component, a service-unit for the JMS component and a service assembly unit, which will bundle each of the artifacts together. For examplesí sake, I will not go into detail here on how to create each of these artifacts using Apache Maven, since this can be looked up easily on the ServiceMix home page, but will show you the XBean definition files for the service units.
The ServiceMix file component allows both the polling of files in directories as also the creation of files in a target directory. Therefore, we have both functionalities, which are configured in the following way:
<beans xmlns:file="http://servicemix.apache.org/file/1.0" xmlns:foo="http://methodsandtools.com/samples/smx/file-jms-mover/1.0"> <file:poller service="foo:filePoller" (1) endpoint="filePoller" (2) targetService="foo:JmsTarget" (3) file="file:inbox" (4) autoCreateDirectory="false"/> (5) <file:sender service="foo:fileSender" (6) endpoint="sender" (7) directory="outbox" /> (8) </beans>
This definition does the following:
(1)+(2) A file poller is created which has the service name "filePoller" and the endpoint name "filePoller" as well. If you have more than one filePoller in your service you should use the endpoint name to distinguish them.
(3) Everything processed by this component is sent to a service "JmsTarget". Since no endpoint is specified, which is not mandatory, the first endpoint found will receive the message.
(4) The component searches a directory "inbox" for any files
(5) If this directory does not exist, it also will not be created automatically
(6) We create a target instance of the file component, which is the "sender" endpoint.
(7) It also has an endpoint name, for definition sake
(8) Everything sent to this endpoint will be written to a directory "outbox".
This configuration file defines the basic input and output instances. Now, we need a JMS queue in between. For that, we create another XBean definition, which contains the JmsTarget endpoint. It sends messages to JMS and a JmsSource endpoint, which then reads messages from this queue, sends it to the fileSender endpoint:
<beans xmlns:jms="http://servicemix.apache.org/jms/1.0" xmlns:foo=" http://methodsandtools.com/samples/smx/file-jms-mover/1.0"> <jms:consumer service="foo:JmsSource" endpoint="jms" targetService="foo:fileSender" targetEndpoint="sender" destinationName="queue/FileJmsMover" connectionFactory="#connectionFactory" /> <jms:provider service="foo:JmsTarget" endpoint="jms" destinationName="queue/FileJmsMover" connectionFactory="#connectionFactory" /> <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:/XAQueueConnectionFactory"/> <property name="lookupOnStartup" value="true"/> </bean> </beans>
These two definitions are all what is needed to read a file from the file system, store its content in a JMS queue and send this then back to a different directory. This is no fancy stuff, for now, but it should clarify the general idea.
We have seen what ServiceMix is all about and how it can be configured and used. Now, I would like to focus on typical use-case scenarios, where ServiceMix can be put to work.
Enterprise Application Integration (EAI)
Systems integration is the oldest integration issue looking for a solution. In systems integration, you have different applications, which need to exchange data, but don't use a common interchange format.
ServiceMix is useful to bridge this gap. Since it already provides access to various backend architectures and can be extended to support what is not already available, it mostly comes down to routing and data transformation. Whereas routing is a key capability of an enterprise service bus, the transformation capability results from using XSLT, Java beans or various scripting languages. Also, by using marshalers, various backend formats can be created rather easily and reused (among those, CSV and fixed-length are very typical candidates).
In contrast to other frameworks, such as Apache Camel, the ServiceMix way looks a bit cumbersome, as it feels more heavyweight. This is due to the fact that simple integration issues are not the prime scenarios for ServiceMix. It is sound practice to use ServiceMix for these types of things, although these are better put off to Camel. There, you can create your solution which is then exposed into ServiceMix as a service to be reused by other services. Since Apache Camel is shipped with ServiceMix by default, there is a tight integration already.
Service Oriented Architectures (SOA)
A service-oriented architecture is on all tables now, though it has different definitions. Nevertheless, the concept of components with defined functionality and reusability is in most definitions.
Due to the nature of ServiceMix and JBI, reusability is a key concept of the bus. The ability to integrate a wide range of services makes ServiceMix the premier runtime environment to build a SOA on. They can then be used from within the bus itself, like web services, databases or, legacy systems.
Although it should be noted that the use of an enterprise service bus in itself is in constant and open discussion, for SOA being nothing technological, you can think of components like ServiceMix as infrastructure glue, in which you embed your legacy applications. This, in itself, has nothing to do with SOA, but enables SOA as you move towards a common platform to service-ify your landscape. Also, remember that SOA does not automatically and in itself means "web services".
Whereas often SOA is meant, when web services are used, they don't necessarily match. Nonetheless, the development of web services is not the easiest part, due to competing frameworks and APIs. ServiceMix greatly simplifies the development, exposure and consumption of web services.
The underlying web services stack, Apache CXF, mostly reduces the development effort to annotating a Java class or creating the SOAP request via an XSLT transformation, for example. The rest is handled by the service component itself.
If you don't need the full power of a web service stack, you may also simply rely on the HTTP and JMS components. Both are able to process SOAP requests, which is enough for simple expose and consume scenarios.
This does not primarily mean that you need, or should, develop web services on ServiceMix. It is a runtime container which can expose or consume web services. Here, too, the main focus is getting data into the bus to leverage its broader functionality.
We have seen in this short introduction what ServiceMix is about and what its basic architecture is. From how it can be deployed, to a sample of how it is configured, we visited some usage scenarios, like EAI and SOA.
At this point, you could see where an enterprise service bus could simplify your development efforts or daily challenges. If not, you should at least know that it is not that hard to integrate such a beast, if you need it.
This introduction only covered some of the components of ServiceMix. Nonetheless, you are not limited to using only these. In fact, a lot of third party components exist. They are provided by OpenESB or the directory of Open JBI components for example. If you don't find what you need there, simply develop your own components which suit your needs! As JBI is an open specification, you can continue to use them, even if you change the JBI implementation of choice, thus switching from ServiceMix to OpenESB is not that much of an issue.
If you take a careful look at what frameworks the open source community has to offer, ServiceMix for sure is not the first choice for application development, in terms of desktop software. But if you have to deal with more complex environments, where different applications are involved and need to interact with each other, an enterprise service bus can alleviate the burden of dealing with such systems to a great extent. The concept of a standardized message model and well defined exchange patterns, alongside the benefits of components for everyday tasks simply help you focus on what is to be done and let's you not bother with the traditional "noise" in software development.