Writing the bean class
We now have to write the bean class to handle incoming message exchanges.
Creating the bean class
Preparing an Eclipse project
In order to ease the development we will now make use of Mavens ability to create Eclipse projects. From the http-handler-su main folder run the following comand:
mvn eclipse:clean eclipse:eclipse
This will cleanup any existing Eclipse config (eclipse:clean) and create a new eclipse project (eclipse:eclipse).
When done it should post something like:
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Wed Nov 28 12:21:12 CET 2007
[INFO] Final Memory: 14M/78M
[INFO] ------------------------------------------------------------------------
Importing the project into Eclipse
Now it's time to start up Eclipse workbench. Choose File > Import > Existing Projects into Workspace.
Then select the projects root directory and press OK. A project named http-handler-su should now be visible inside the Import window's projects list. Make sure it's checkbox is selected and press finish.
The project should now appear in your Package Explorer view.
Be sure you have specified the M2_REPO classpath variable to point on your local Maven repository which is located in your home folder.
For example: /home/lhe/.m2/repository
If you don't know how to specify this variable refer to the Eclipse documentation or Google it.
Create the bean class file
Next thing to do is creation the bean class. For this select the src/main/java folder in your project. Now delete everything inside this folder.
Now select File > New > Class. In the dialog enter the following:
Package: org.apache.servicemix.jbi
Name: HandlerBean
Interfaces: org.apache.servicemix.MessageExchangeListener
Then hit Finish to create the class. Eclipse will also implement the interface's only method for you:
public void onMessageExchange(MessageExchange arg0) throws MessagingException
{...}
This method is responsible for handling incoming messages.
Handling incoming messages
We assume (and do not further check) that each incoming message exchange is of type InOut MEP. Feel free to improve this and check for the correct Message Exchange Pattern.
We extract the first attachment of the message by name. The name is equal to the filename. After this we have the original filename in the
fileName variable and the file content in the content variable (as DataHandler object).
For the sake of simplicity we just write the contents into a temporary file and use this file for sending it back to the http-consumer-su.
fileName = it.next().toString();
content = in.getAttachment(fileName);
File f = File.createTempFile("tmp_", fileName);
FileOutputStream fos = new FileOutputStream(f);
content.writeTo(fos);
fos.flush();
fos.close();
NormalizedMessage out = exchange.createMessage();
out.setContent(new StringSource("<payload/>"));
FileDataSource fds = new FileDataSource(f);
InputStream is = fds.getInputStream();
DataHandler dh = new DataHandler(new StreamDataSource(is, fds.getContentType()));
out.addAttachment(fileName, dh);
exchange.setMessage(out, "out");
channel.send(exchange);
f.deleteOnExit();
This is of course a stupid example, so just imagine you convert this file into another format and send the result back.
You can do such a logic if you want. For this you can refer for example to OpenOffice running in headless mode in combination with the JODConverter of "Arts of Solving". This will enable you to convert for example a .odt document into a .pdf document. But this is really out of scope now.
The finished class
package org.apache.servicemix.jbi;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Set;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.jbi.messaging.DeliveryChannel;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;
import javax.jbi.messaging.MessageExchange.Role;
import org.apache.log4j.Logger;
import org.apache.servicemix.MessageExchangeListener;
import org.apache.servicemix.jbi.jaxp.StringSource;
import org.apache.servicemix.jbi.util.StreamDataSource;
public class HandlerBean implements MessageExchangeListener
{
private static final Logger logger = Logger.getLogger(HandlerBean.class);
@Resource
private DeliveryChannel channel;
/*
* (non-Javadoc)
* @see org.apache.servicemix.MessageExchangeListener#onMessageExchange(javax.jbi.messaging.MessageExchange)
*/
public void onMessageExchange(MessageExchange exchange) throws MessagingException
{
if (exchange == null)
{
return;
}
if (exchange.getRole() == Role.CONSUMER)
{
onConsumerExchange(exchange);
}
else if (exchange.getRole() == MessageExchange.Role.PROVIDER)
{
onProviderExchange(exchange);
}
else
{
throw new MessagingException("HandlerBean.onMessageExchange(): Unknown role: " + exchange.getRole());
}
}
/**
* handles the incoming consumer messages
*
* @param exchange
* @throws MessagingException
*/
private void onConsumerExchange(MessageExchange exchange) throws MessagingException
{
if (exchange.getMessage("out") != null)
{
exchange.setStatus(ExchangeStatus.DONE);
channel.send(exchange);
}
else if (exchange.getFault() != null)
{
exchange.setStatus(ExchangeStatus.DONE);
channel.send(exchange);
}
else
{
throw new MessagingException("HandlerBean.onConsumerExchange(): Consumer exchange is ACTIVE, but no out or fault is provided");
}
}
/**
* handles the incoming provider messages
*
* @param exchange
* @throws MessagingException
*/
private void onProviderExchange(MessageExchange exchange) throws MessagingException
{
if (exchange.getStatus() == ExchangeStatus.DONE)
{
return;
}
else if (exchange.getStatus() == ExchangeStatus.ERROR)
{
return;
}
else if (exchange.getFault() != null)
{
exchange.setStatus(ExchangeStatus.DONE);
channel.send(exchange);
}
else
{
NormalizedMessage in = exchange.getMessage("in");
if (in == null)
{
throw new MessagingException("HandlerBean.onProviderExchange(): Exchange has no IN message");
}
else
{
String fileName = null;
DataHandler content = null;
Set attNames = in.getAttachmentNames();
Iterator it = attNames.iterator();
if (attNames.size()==1)
{
if (it.hasNext())
{
try
{
File file = new File(it.next().toString());
fileName = file.getName();
content = in.getAttachment(fileName);
File f = File.createTempFile("tmp_", fileName);
FileOutputStream fos = new FileOutputStream(f);
content.writeTo(fos);
fos.flush();
fos.close();
NormalizedMessage out = exchange.createMessage();
out.setContent(new StringSource("<payload/>"));
FileDataSource fds = new FileDataSource(f);
InputStream is = fds.getInputStream();
DataHandler dh = new DataHandler(new StreamDataSource(is, fds.getContentType()));
out.addAttachment(fileName, dh);
exchange.setMessage(out, "out");
channel.send(exchange);
f.deleteOnExit();
}
catch (IOException ex)
{
throw new MessagingException("HandlerBean.onProviderExchange(): " + ex.getLocalizedMessage());
}
}
}
else
{
throw new MessagingException("HandlerBean.onProviderExchange(): Wrong message format (invalid attachment count)");
}
}
}
}
}
Feel free to play around with this class after you ran it once sucessfully. There is enough room for improvements.
Now the handler SU is ready for work. Let's move on to creating the service assembly.