Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Warning
titleWarning

This component has been deprecated in favor to servicemix-lwcontainer component.
See also POJO Support.

Introduction

Developing services and component for use in a JBI (Java Business Integration) environment can seem a little complex at first and, since the JBI (JSR-208) specification is very open-ended, it can be difficult to get started sometimes. The purpose of the ServiceMix Spring Client Toolkit (SSCT) is to allow you to get up and running quickly with either with new components or services, or maybe simply by JBI-enabling your existing Java code, so that you can use it in a JBI environment.

...

You should see the Maven start-up, and then be prompted for the name of your new component. As a good starting point, please use 'myFirstComponent'. Maven will then create the required directory structure underneath the /work directory.

No Format
 __  __
|  \/  |__ _Apache__ ___
| |\/| / _` \ V / -_) ' \  ~ intelligent projects ~
|_|  |_\__,_|\_/\___|_||_|  v. 1.0.2

Enter the name for your new JBI project:
myFirstComponent
build:start:

jbi:createArchetype:
    [mkdir] Created dir: C:\work\myFirstComponent\src\main\java
    [mkdir] Created dir: C:\work\myFirstComponent\src\main\test
    [mkdir] Created dir: C:\work\myFirstComponent\src\main\merge
    [mkdir] Created dir: C:\work\myFirstComponent\src\main\jbi\META-INF
    [copy] Copying 1 file to C:\work\myFirstComponent
    [copy] Copying 1 file to C:\work\myFirstComponent\src\main\jbi\META-INF
    [copy] Copying 1 file to C:\work\myFirstComponent\src\main\merge
BUILD SUCCESSFUL
Total time: 53 seconds
Finished at: Thu Aug 18 16:05:01 EDT 2005

...

  • Services/Components have life-cycles, most commonly initialization, start and stop. There is a bit more to life-cycles, but in order to get started on building code for a JBI environment, you can start here.
  • Services/Components communicate to other Services/Components via EndPoints. Therefore, in order to talk to another service, you need to refer specifically to its Service Name.
  • Services/Components can have interfaces, which means a service can route a message to a different piece of code, and you can have a service that exposes more than one interface.
  • All Service Names and Interface names are Qualified Names, so you should declare namespaces.

How Does

...

this Map to the ServiceMix Spring Client Toolkit?

The SSCT is provided to try and simplify the appraoch to building for JBI and to make it easier for you to write these components, though – as with all things that hide some of technology's complexity – the SSCT also hides some of the more advanced functionality.

...

You should end up with a class looking much like the following:

Code Block
java
java

package org.servicemix.tutorial;

import javax.jbi.JBIException;

import org.servicemix.client.ServiceContext;

import org.servicemix.client.ServiceLifeCycleImplementation;

/**
 * A simple Timer based component
 * 
 * @author <a hrefxhref="mailto:pdodds@unity-systems.com">Philip Dodds </a>
 */
public class TimerComponent implements ServiceLifeCycleImplementation {

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#init(org.servicemix.client.ServiceContext)
	 */
	public void init(ServiceContext serviceContext) throws JBIException {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#start()
	 */
	public void start() throws JBIException {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#stop()
	 */
	public void stop() throws JBIException {
		// TODO Auto-generated method stub

	}

}

Now, you are going to create a simple basic Timer. The SSCT actually simplifies this for you as you are only extending the TimerTask and creating a Timer, in the init method. In the start and stop, you will basically set the timer operations to schedule the timer to run every 5000ms and to cancel it if stopped.

Code Block
java
java
package org.servicemix.tutorial;

import java.util.Timer;
import java.util.TimerTask;

import javax.jbi.JBIException;

import org.servicemix.client.ServiceContext;
import org.servicemix.client.ServiceLifeCycleImplementation;

/**
 * A simple Timer-based component
 * 
 * @author <a hrefxhref="mailto:pdodds@unity-systems.com">Philip Dodds </a>
 */
public class TimerComponent extends TimerTask implements
		ServiceLifeCycleImplementation {

	private Timer timer;
	private ServiceContext serviceContext;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#init(org.servicemix.client.ServiceContext)
	 */
	public void init(ServiceContext serviceContext) throws JBIException {
		this.serviceContext = serviceContext;
		timer = new Timer();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#start()
	 */
	public void start() throws JBIException {
		timer.schedule(this, 5000);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.servicemix.client.ServiceLifeCycleImplementation#stop()
	 */
	public void stop() throws JBIException {
		timer.cancel();

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.TimerTask#run()
	 */
	public void run() {

	}

}

...

Below, you can see how easy it is to create an InOnly exchange and how to populate the message.

NOTE: With the ServiceContext helper method, you must also refer to the name of the interface to which the message will be sent. You will see this interface mapping to a service name later in the services.xml.

Code Block
java
java
/*
 * (non-Javadoc)
 * 
 * @see java.util.TimerTask#run()
 */
public void run() {
	try {
        InOnly inOnly = serviceContext.createInOnly(new QName(
				"http://tempuri.org/logger", "log"));
		NormalizedMessage message = inOnly.createMessage();
		message.setContent(new StreamSource(new StringReader(
				"<hello>world</hello>")));
		serviceContext.done(inOnly);
	} catch (MessagingException e) {
		e.printStackTrace();
	}
}

Thats That's it for building your first component's code. Now, you need to do the wiring for the JBI, i.e., you will need to make sure that when you publish to the interface, that it maps to a specific service name. Since you are still writing the first component, you will have to make up the name of the second component as a placeholder. However, keep this name in mind since you will be writing a second component to receive these messages shortly. To do the JBI wiring, look to the /src/main/merge/services.xml file. You should be able to prepare the file as shown below:

Code Block
xml
xml
<services binding-component="false"	
	xmlns:logger="http://tempuri.org/logger">
	<consumes interface-name="logger:log"
		service-name="logger:myLogger" />
</services>

NOTE: The interface name is described as a consumes, which in JBI-speak means that this component will be sending its exchange to the servicename 'logger:myLogger'. You haven't written this service yet, but as you can see, it won't take you long to create this service so that you can use its services.xml to expose the service-name and interface name. The SSCT lets you work through the interface name, though you still have the ability to publish to any of the available endpoints EndPoints that are defined in the services.xml.

Next, you need to tell the Spring Component that an instance of the TimerComponent is required, this . This is done in the Spring configuration file found in /src/main/jbi/META-INF/jbi-spring.xml, as can be seen below:

Code Block
xml
xml
<beans>
	<!--  This is going to be where we declare the beans that we want the
		   SpringComponent container to build -->

	<bean id="myTimer"
		class="org.servicemix.tutorial.TimerComponent">	
	</bean> 
</beans>

The final step in building the JBI component is actually creating the component, this can be done using the Maven JBI plugin by running the following command from your myFirstComponent directory:

...

Congratulations! You have just created your first JBI component!

Creating a

...

Component to

...

Receive the

...

Exchange

Of course, creating single JBI The one problem with JBI is that a single component is pretty useless, much like being the only person at the party there is very little to do. So we can , the next step is for you to return to the parent directory and repeat the process above, using our Maven JBI plugin and the maven jbi:createArchetype, to create a second component called aptely , which you will call mySecondComponent.

Once you have created the project, and also the eclipse Eclipse files, you can create a new class in the package org.servicemix.tutorial called LoggerComponent, this . This time we you will implement be implementing the ServiceInterfaceImplementation interface, and we you will fill in the getInterface method with the name of the interface we you used in building the first component., as shown below:

Code Block
java
java
package org.servicemix;

import javax.jbi.messaging.MessageExchange;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.servicemix.client.ServiceContext;
import org.servicemix.client.ServiceInterfaceImplementation;

/**
 * A simple Logger based component
 * 
 * @author <a hrefxhref="mailto:pdodds@unity-systems.com">Philip Dodds </a>
 */
public class LoggerComponent implements ServiceInterfaceImplementation {
	
	private static final Log log = LogFactory.getLog(LoggerComponent.class
			.getName());

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceInterfaceImplementation#getInterfaceName()
	 */
	public QName getInterfaceName() {
		return new QName(
				"http://tempuri.org/timer", "notification");
	}

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceImplementation#setServiceContext(org.servicemix.client.ServiceContext)
	 */
	public void setServiceContext(ServiceContext arg0) {
		
	}

	/* (non-Javadoc)
	 * @see org.servicemix.client.ServiceImplementation#onMessage(javax.jbi.messaging.MessageExchange)
	 */
	public void onMessage(MessageExchange exchange) {
		log.info("I got my exchange "+exchange);
	}

}

The Spring Client Toolkit will make sure SSCT will ensure that exchanges for this service and that interface its interfaces will be passed to this the ServiceInterfaceImplementation.

Next we , you will need to set up the services.xml for this component, since . Since this is such a simple example we are able to , you can simply reverse the logic from the first component, so that this this component provides the interface on for itself.

Code Block
xml
xml
<!-- This is where we are able to declare the ins and outs of the Service
 	  as it consumes and provides elements,  the service-names and endpointsEndPoints
 	  will be used to activate the JBI endpointsEndPoints,  and weyou can use the 
 	  interface-name to determine which one weyou want to call and also which
 	  bean is going to receive the actual JBI exchange -->
<services binding-component="false"
	xmlns:timer="http://tempuri.org/timer"
	xmlns:logger="http://tempuri.org/logger">
	<provides interface-name="timer:notification"
		service-name="logger:write" />
</services>

And once Once again we you need to configure the spring Spring container to create an instance of our your bean in the src/main/jbi/META-INF/jbi-spring.xml file, shown below:

Code Block
xml
xml
<beans>
	<!--  This is going to be where we declare the beans that we want the
		   SpringComponent container to build -->
	<bean id="myLogger"
		class="org.servicemix.tutorial.LoggerComponent">		
	</bean> 
</beans>

And that This now completes the writing of a recieving component, and as the receiving component's code. As with the first component we , you need to build this component the receiving component so that it is ready for deployment using the maven jbi:generateInstaller goal to onto a JBI server (in our case the wonderful ServiceMix).

Deploying

...

Your Components onto ServiceMix

Once One of the key differences between the ServiceMix Spring Client Toolkit and the standard ServiceMix client libraries is that the Spring Client Toolkit SSCT is designed to generate standard JBI components and service units that can run in any JBI-compliant container, this . This means that you are able to build installable zip ZIP files that can be deployed into onto the server , in itself. In this example we , you are going to deploy to a stand-alone servicemix ServiceMix server, however you could also deploy to a Geronimo and JBoss instance running servicemix ServiceMix embedded, as well.

First up you will need a copy of ServiceMix, so download and unzip this on To deploy your JBI components, you must first download and un-ZIP ServiceMix to your your machine.

Then you should find Next, under $SERVICEMIX_HOME (the location you unzipped it), you should find an install directory. You need to copy both of your the JBI installers that you created for your components into this directory. If you have been working in '/work' then these files should be appear as follows:

/work/myFirstComponent/target/myFirstComponent-1.0-jbi-installer.zip and /work/mySecondComponent/target/mySecondComponent-1.0-jbi-installer.zip.

Once you have installed the new components, you can just start servicemix ServiceMix - to do so goto $SERVICE_HOME/bin and run servicemix

You should see your components deploy and then, every 5 secs you should see the logger recieve receive the exchange from the timer component.

No Format
ServiceMix ESB: null

Loading ServiceMix from servicemix.xml on the CLASSPATH
Aug 19, 2005 11:13:13 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader 
loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [servicemix.xml]
Aug 19, 2005 11:13:13 AM org.springframework.context.support.AbstractRefreshableApplicationContext 
refreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.
ClassPathXmlApplicationContext;hashCode=14737862]: org.springframework.beans.factory.support.
DefaultListableBeanFactory defining beans [transactionManager,jmsFactory,jbi]; root of BeanFactory hierarchy
Aug 19, 2005 11:13:14 AM org.springframework.context.support.AbstractApplicationContext 
refresh
..........
Aug 19, 2005 11:13:15 AM org.springframework.beans.factory.support.DefaultListableBeanFactory 
preInstantiateSingletons
INFO: Pre-instantiating singletons in factory [org.springframework.beans.factory.support.
DefaultListableBeanFactory defining beans [myLogger]; root of BeanFactory hierarchy]
Aug 19, 2005 11:13:15 AM org.springframework.beans.factory.support.AbstractBeanFactory getBean
INFO: Creating shared instance of singleton bean 'myLogger'
Aug 19, 2005 11:13:15 AM org.servicemix.jbi.framework.ComponentContextImpl activateEndpoint
INFO: Component: mySecondComponent activated endpoint: {http://tempuri.org/logger}write : default
Aug 19, 2005 11:13:15 AM org.servicemix.jbi.framework.AutoDeploymentService$1 run
INFO: Directory: install: Finished installation of archive:  mySecondComponent-1.0-jbi-installer.zip
Aug 19, 2005 11:13:20 AM org.servicemix.tutorial.LoggerComponent onMessage
INFO: I got my exchange org.servicemix.jbi.messaging.InOnlyImpl@15ad5c6

...

*Aug 19, 2005 11:13:20 AM org.servicemix.tutorial.LoggerComponent onMessage
INFO: I got my exchange org.servicemix.jbi.messaging.InOnlyImpl@15ad5c6*

There you go! Success, you You have just written your first JBI components and , hooked them up, and deployed them successfully!