Red Hat Training

A Red Hat training course is available for Red Hat Fuse

Chapter 12. File Marshalers

Abstract

When using file component endpoints, you may want to customize how messages are processed as they pass in and out of the ESB. The Red Hat JBoss Fuse file binding component allows you to write custom marshalers for your file component endpoints.
Important
The Java Business Integration components of Red Hat JBoss Fuse are considered deprecated. You should consider migrating any JBI applications to OSGi.

Overview

File component endpoints use a marshaler for processing messages. Poller endpoints rely on the marshaler for reading data off of the file system and normalizing it so it can be passed to the NMR. Sender endpoints rely on the marshaler for determining the name of the file to be written and for converting the normalized messages into the format to be written to the file system.
The default marshaler used by file component endpoints reads and writes valid XML files. It queries the message exchange, and the message, received from the NMR for the name of the outgoing message. The default marshaler expects the file name to be stored in a property called org.apache.servicemix.file.name.
If your application requires different functionality from the marshaler, you can provide a custom marshaler by implementing the org.apache.servicemix.components.util.FileMarshaler interface. You can easily configure your endpoints to use your custom marshaler instead of the default one.

Provided file marshalers

In addition to the default file marshaler, Red Hat JBoss Fuse provides two other file marshalers that file component endpoints can use:
Binary File Marshaler
The binary file marshaler is provided by the class org.apache.servicemix.components.util.BinaryFileMarshaler. It reads in binary data and adds the data to the normalized message as an attachment. You can set the name of the attachment and specify a content type for the attachment using the properties shown in Table 12.1, “Properties for configuring the binary file marshaler”.

Table 12.1. Properties for configuring the binary file marshaler

NameDescriptionDefault
attachment Specifies the name of the attachment added to the normalized message.content
contentType Specifies the content type of the binary data being used. Content types are specified using MIME types. MIME types are specified by RFC 2045. 
Flat File Marshaler
The flat file marshaler is provided by the class org.apache.servicemix.components.util.SimpleFlatFileMarshaler. It reads in flat text files and converts them into XML messages.
By default, the file is wrapped in a File element. Each line in the file is wrapped in a Line element with a number attribute that represents the position of the line in the original file.
You can control some aspects of the generated XML file using the properties described in Table 12.2, “Properties used to control the flat file marshaler”.

Table 12.2. Properties used to control the flat file marshaler

NameDescriptionDefault
docElementname Specifies the name of the root element generated by a file.File
lineElementname Specifies the name of the element generated for each line of the file.Line
insertLineNumbers Specifies if the elements corresponding to a line will use the number attribute.true

Implementing a file marshaler

To develop a custom file marshaler, you need to implement the org.apache.servicemix.components.util.FileMarshaler interface. Example 12.1, “The file marshaler interface” shows the interface.

Example 12.1. The file marshaler interface

package org.apache.servicemix.components.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.jbi.JBIException;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;

public interface FileMarshaler
{
  void readMessage(MessageExchange exchange, NormalizedMessage message, InputStream in, String path) throws IOException, JBIException;

  String getOutputName(MessageExchange exchange, NormalizedMessage message) throws MessagingException;

  void writeMessage(MessageExchange exchange, NormalizedMessage message, OutputStream out, String path) throws IOException, JBIException;
}
The FileMarshaler interface has three methods that need to be implemented:
readMessage()
The readMessage() method is responsible for reading a file from the file system and converting the data into a normalized message. Table 12.3, “Parameters for reading messages from the file system” describes the parameters used by the method.

Table 12.3. Parameters for reading messages from the file system

NameDescription
exchangeContains the MessageExchange object that is going to be passed to the NMR.
messageContains the NormalizedMessage object that is going to be passed to the NMR.
inContains the BufferedInputStream which points to the file in the file system.
pathContains the full path to the file on the file system as determined by the Java getCanonicalPath() method.
getOutputName()
The getOutputName() method returns the name of the file to be written to the file system. The message exchange and the message received by the sender endpoint are passed to the method.
Important
The returned file name does not contain a directory path. The sender endpoint uses the directory it was configured to use.
writeMessage()
The writeMessage() method is responsible for writing messages received from the NMR to the file system as files. Table 12.4, “Parameters for writing messages to the file system” describes the parameters used by the method.

Table 12.4. Parameters for writing messages to the file system

NameDescription
exchangeContains the MessageExchange object received from the ESB.
messageContains the NormalizedMessage object received from the ESB.
outContains the BufferedOutputStream which points to the file in the file system.
pathContains the path to the file are returned from the getOutputName() method.
Example 12.2, “Simple file marshaler” shows a simple file mashaler.

Example 12.2. Simple file marshaler

package org.apache.servicemix.demos;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import javax.jbi.JBIException;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;

public class myFileMarshaler implements FileMarshaler
{

  public void readMessage(MessageExchange exchange, NormalizedMessage message, 
                                                 InputStream in, String path)
  throws IOException, JBIException
  {
    message.setContent(new StreamSource(in, path));
  }

  public String getOutputName(MessageExchange exchange, NormalizedMessage message)
  throws MessagingException
  {
    return "fred.xml";
  }

  public void writeMessage(MessageExchange exchange, NormalizedMessage message, 
                                                 OutputStream out, String path)
  throws IOException, JBIException
  {
    Source src = message.getContent();
    if (src == null)
    {
      throw new NoMessageContentAvailableException(exchange);
    }
    try
    {
      ObjectOutputStream objectOut = new ObjectOutputStream(out);
      objectOut.writeObject(src);
    }
  }
}

Configuring an endpoint to use a file marshaler

You configure a file component endpoint to use a file marshaler using its marshaler attribute. The marshaler attribute's value is a reference to a bean element specifying the class of the file filter implementation.
Example 12.3, “Poller endpoint using a file marshaler” shows configuration for a poller endpoint that uses the file marshaler implemented in Example 12.2, “Simple file marshaler”.

Example 12.3. Poller endpoint using a file marshaler

<beans xmlns:file="http://servicemix.apache.org/file/1.0"
	       xmlns:foo="http://servicemix.org/demo/">

  <file:poller service="foo:filePoller"
               endpoint="filePoller"
               targetService="foo:fileSender" 
               file="inbox"
               marshaler="#myMarshaler" />

  <bean id="myMarshaler" class="org.apache.servicemix.demo.myFileMarshaler" />
Note
You can also configure a file component endpoint to use a file marshaler by adding a child marshaler element to the endpoint's configuration. The marshaler element simply wraps the bean element that configures the file marshaler.