Skip to main content

Sending Messages Using JBI Technology

November 6, 2008

{cs.r.title}







Every day, software professionals look for solutions to address
integration problems in the business-to-business (B2B) and
enterprise application integration (EAI) fields. These solutions
are typically based on proprietary technologies, JMS platforms, or
web services. Lately, a new technology has appeared: Java
Business Integration (JBI)
. It offers a solution to the
integration problem by defining a standard architecture where
different components can be plugged in, in a cooperative context.
The current version of JBI, 1.0, is described in "http://jcp.org/en/jsr/detail?id=208">JSR 208.

In this article, we will explore the main features of this
technology, by developing a new component that can be plugged into
the JBI environment. This component exchanges information with an
external GSM modem to send a short text message. This is
potentially useful because nowadays, many of us use short message
service (SMS) to send and receive data like news, alerts, event
notifications, and so on.

Before we start coding our component, we must first understand
how JBI works.

JBI Overview

JBI provides an environment into which components can be plugged
in. In this environment, the components collaborate by exchanging
information in order to accomplish some tasks. The information is
exchanged using a message exchange model according to the web
service description language (WSDL) 2.0 or 1.1.

JBI Environment height="169" width="449" />

Figure 1. JBI environment

JBI components can be divided in two different types:

  • Service Engine (SE)
  • Binding Component (BC)

The Service Engine provides business logic and
transformation services to other components and can consume
services, too (for example, a service engine can be a XSLT
engine).

A Binding Component provides connectivity to the
world outside the JBI environment, supporting specific protocols.
For example, a binding component can implement HTTP protocol and so
on.

Even if we make this distinction between these two component
types, in the JBI environment, from the developing point of view,
they are the same. An SE and a BC can act as service provider,
service consumer, or both at the same time.

The key concept that stands behind JBI is that the components
don't exchange messages directly but instead use an internal
component that is part of the JBI environment called Normalized
Message Router
or simply NMR. The NMR component acts as
an internal router, forwarding messages to the right component; in
this way it enables components (SEs and BCs) to work together. JBI
is based on the normalized message concept, meaning that
JBI internally uses a message structure that is technologically
independent and conforms to the WSDL abstract message
definition.

A normalized message is built by three different
parts:

  • The bare message: An XML document following the WDSL abstract
    message specification
  • The metadata: Extra data associated to the message used by the
    JBI environment to route messages
  • The attachments

All the components plugged into the JBI environment exchange
messages with the NMR component using a DeliveryChannel,
which is a bidirectional channel where SEs and BCs send and receive
messages. Figure 2 shows the JBI environment with some components.
The black connectors between components and the NMR represents the
delivery channel.

SE-BC "443" />

Figure 2. A service engine and binding component in the JBI
environment

One interesting feature of this environment is the capability to
combine together different BCs and SEs to create a Composite
Application
. In this way, using some basic services and binding
components, we can create a great variety of applications.

An important aspect we must consider while developing an SE or a BC
is the component lifecycle. The lives of all components deployed
are managed by the JBI environment. JBI manages component lives
using a set of JMX management beans (MBeans); the most important
administration tasks are:

  • Installation of a new JBI component
  • Lifecycle component administration
  • Component deploy

The component lifecycle is built by several states, shown in
Figure 3.

Component Life Cycle width="346" height="456" />

Figure 3. Component lifecycle

In order to be managed, a component must implement some
interfaces that enable the component to be plugged in the JBI
Environment. These interfaces are defined in the
javax.jbi.component package. We analyze these interfaces
below:

  • InstallationContext: This interface contains information
    used by the JBI component to perform installation and
    uninstallation tasks.

  • Bootstrap: This interface is called by the JBI
    environment during the installation or uninstallation phase. During
    the bootstrap phase, the component can create a directory or
    database table necessary to work properly. This interface
    contains several methods but we focus our attention to the
    init. As parameters, the init method accepts the
    InstallationContext used by the component to access JBI
    environment information (i.e component name and so on).

  • ComponentContext: This interface is used by the component
    to query the JBI environment where it is plugged in. Moreover, this
    interface is used by the component to activate its services and make
    them available to other components.

  • ComponentLifeCycle: This interface is used to manage its
    lifecycle. The methods reflect the different component states
    (stop, start, shutdown). The component life starts when the
    init() method is called by the JBI engine. As a parameter,
    the init() method accepts the ComponentContext
    interface. Once the component is done with the init phase, the JBI
    engine calls the start() method. During this phase we have
    to provide the business logic that it is necessary to start the
    component. In the same way, we have to provide the logic in the
    stop() method called by the JBI engine when the component is
    about being stopped. Finally, in the shutdown() method we
    have to release all the resource used by the component during its
    life.

  • ServiceUnitManager: This interface defines some component
    methods to manage the service unit deployment.

  • Component: This interface is called by the JBI
    environment to query the component for various pieces of information, such as
    the component lifecycle interface and the component service unit
    manager. In this interface are defined several methods, but the most
    important are getLifeCycle(), which must return a valid
    implementation of the ComponentLifeCycle interface, and
    getServiceUnitManager(), which must return an implementation
    of the ServiceUnitManager interface.

Once we have coded our component, if we want to deploy it we must
describe it using an XML artifact where we specify our
implementation of the Bootstrap and the Component
interfaces. We will see later how to do this.

We've described the main aspects of JBI, and now we can develop a
component that can help us to understand more deeply how this all
works.

SMS Library

Before starting coding the SMS-sending component described in
the introduction to this article, we need to focus briefly on the
way we can exchange information with an external modem. To do that,
we develop a simple library based on the "http://java.sun.com/products/javacomm/">Java Communications
(javax.comm)
API. For a modem, we can use a simple mobile
phone connected through a USB cable or Bluetooth. With either
approach, we interface with the device using a COM port, so we can
use javax.comm. Figure 4 shows the library's UML class
diagram.

<br "Class diagram" height="373" width="450" />

Figure 4. Class diagram (click the image for a larger version)

We focus our attention the on the SerialConnection
class. This class uses ConnectionParams to receive the
configuration parameters. The first step, therefore, is to open the
COM port and set the right parameters. The code below shows how to
do it:


try {
    System.out.println("Open port ["+param.getPortId()+"]");
    portId = CommPortIdentifier.getPortIdentifier(param.getPortId());
}          
catch (NoSuchPortException ex) {
    Logger.getLogger(SerialConnection.class.getName()).
    log(Level.SEVERE, null, ex);
 throw new ModemConnectionException(ex);
} 
// Open the serial port with 20 sec timeout
try {
    port = (SerialPort) portId.open("SMSServer", 20000);
}
catch (PortInUseException ex) {
    Logger.getLogger(SerialConnection.class.getName()).
    log(Level.SEVERE, null, ex);
        throw new ModemConnectionException(ex.getMessage());
} 
// Enable Break signal notification
port.notifyOnBreakInterrupt(true); 
// Enable Carier Detect notification
port.notifyOnCarrierDetect(true); 
// Enable Data Available notification
port.notifyOnDataAvailable(true); 

To send a short message through a GSM modem, we have to use
AT commands. The SMSSender class takes
care that job, using the following command sequence:


ATZ 
AT+CMGF=1
AT+CSCA="Service Message center number"
AT+AT+CMGS="Destination mobile number"
&gt;Message Text   

Note that this command sequence may vary depending on your
mobile phone.

For each command sent, we have to wait for the modem response
before send the next command. The response can either be
OK, in which case we continue with the next sequence
step, or an error, which requires us to reset the modem using
CTRL + Z and start again.

Creating the Component

As described earlier, to develop a component we need to
implement several interfaces: Bootstrap,
ComponentLifeCycle, Component, and
ServiceUnitManager. The UML class diagram in Figure 5
describes the classes used to build our component.

"/images/2008/11/component_cd_sm.jpg" alt="Component class diagram" height=
"271" width="550" />

Figure 5. Component class diagram (click the image for a larger version)

required by the interface with an empty body, because we don't need
to do any special work at bootstrap phase.
SMSComponentLifeCycle is the heart of this component.
In the start() method, we register our service endpoint
and we start the MessageReceiver thread to listen to
incoming messages, so that we can handle them. The code below shows
how to do this:


public void start() throws JBIException {
  logger.info("--- Starting component ["+ctx.getComponentName()+"]");
  // Activate endpoint
  QName qServiceName = new QName(EndPointDesc.NS, EndPointDesc.SERVICE_NAME);
  serviceEndpoint = ctx.activateEndpoint(qServiceName, EndPointDesc.SERVICE_EP);
  logger.info("\t--- Activated endpoint [" + serviceEndpoint + "]");
  // Starting message receiver
  msgRcv = new MessageReceiver(channel);
  (new Thread(msgRcv)).start();
  logger.info("--- Component ["+ctx.getComponentName()+"] started.");
}       

As we said during the JBI description, the Normalized Message
Router (NMR) through the DeliveryChannel exchanges
information with our component using normalized messages. In the
MessageReceiver class, we handle the incoming message
and then we convert it into AT commands to send a short message.
This class is a thread that continuously listens for messages. The
first step in the run() method is to accept messages:


MessageExchange mExchange = channel.accept(TIME_TO_WAIT); 

where channel is an instance of
DeliveryChannel.

When the component receives the message, it extracts the
normalized message and then the XML source so that it can analyze
the content.


NormalizedMessage msgNor = msg.getInMessage();
Source inSource = msgNor.getContent(); 

The next step is to extract the content. Our XML message
structure is really simple, looking like the clipping shown
below:


&lt;sms:smsData xmlns:sms="http://xml.netbeans.org/schema/smsSchema"&gt;
   &lt;sms:msisdn&gt;recipient_phone_number&lt;/sms:msisdn&gt;
   &lt;sms:body&gt;message_body&lt;/sms:body&gt;
&lt;/sms:smsData&gt;    

For more information on the message structure, please refer to
smsSchema.xsd. in the sample code. Of course, we can add
other tags to better describe our message, but this is enough for this
example.

From the XML message, we need to extract the msisdn and
the body. We can do this using the following piece of
code:


NormalizedMessage outMsg = msg.createMessage();
StringBuffer inBuff = XMLHelper.readFromSource(inSource);
Document outDoc = XMLHelper.
                  buildDOMDocument(new StringReader(inBuff.toString()));
// By now outDoc is equal to the input document
String msisdn = XMLHelper.extractData(outDoc, "msisdn");
String body = XMLHelper.extractData(outDoc, "body"); 

And finally we send the message using our library:


// We have to set the right COM port where the modem is connected
SMSSender sender = new SMSSender("COM6"); 
SMSMessage message = new SMSMessage();
message.setMsisdn(msisdn); // MSISDN is destination number
message.setBody(body); // Message Body
sender.sendMessage(message); 

Installation Phase

Once we have developed our component, we need to describe it so
that it can be plugged into the JBI environment. We have to create
a XML file descriptor called jbi.xml. In the descriptor, we
give a name to our component, and specify the libraries and the .jar
name. To make things simple, we'll develop a Service Engine
component. It might be more interesting to create a binding
component that connects to the GSM modem and a service engine that
uses this binding component. In such a case, the service engine
could perform some test on the message content and keep track of
the messages sent or save the incoming short messages somewhere.
This is out of the scope of this article. For now, we
collapse everything in one simple component.


&lt;jbi version="1.0" xmlns="http://java.sun.com/xml/ns/jbi"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  &lt;component type="service-engine"&gt;
    &lt;identification&gt;
      &lt;name&gt;SMSService&lt;/name&gt;
      &lt;description&gt;Component to send SMS&lt;/description&gt;
    &lt;/identification&gt;
    &lt;component-class-name&gt;azzola.jbi.sms.SMSComponentImpl&lt;/component-class-name&gt;
    &lt;component-class-path&gt;
     &lt;path-element&gt;SMSComponent.jar&lt;/path-element&gt;
     &lt;path-element&gt;Simple_Modem_Library.jar&lt;/path-element&gt;
     &lt;path-element&gt;comm.jar&lt;/path-element&gt;
    &lt;/component-class-path&gt;
    &lt;bootstrap-class-name&gt;azzola.jbi.sms.SMSBootstrap&lt;/bootstrap-class-name&gt;
    &lt;bootstrap-class-path&gt;
     &lt;path-element&gt;SMSComponent.jar&lt;/path-element&gt; 
    &lt;/bootstrap-class-path&gt;
  &lt;/component&gt;
&lt;/jbi&gt; 

Notice that the classes we developed before are referenced in
the component file descriptor.

Now we package everything we created, building a .zip file
containing the .jar component file, the libraries, and the jbi.xml
file in the META-INF directory. We call this .zip file
SMSComponent.zip. Now we can deploy it using NetBeans and
GlassFish as the application server and start the component. If we
prefer, we can use the GlassFish web interface to do the same
tasks. Figure 6 below shows the component installation using the
NetBeans interface integrated with GlassFish.

<br "GlassFish installation" height="142" width="285" />

Figure 6. Glassfish installation

Creating an SU and an SA

Once we have installed our component and started it, it is time we
exploit it. Before doing this we need to create two XML artifacts: a
Service Unit (SU) and the Service Assembly (SA). The
Service Unit can't be deployed directly, but it is a part of
the Service Assembly. An SU is something like a
configuration packaging of a component. A component doesn't do
anything until it is configured, and to tell what it should do we
need to configure it. Before we described our service using the WSDL
language. We can use NetBeans to do it and the file should look like
the one one in Figure 7:

WSDL file "352" />

Figure 7. WSDL file

The JBI file descriptor contains information extracted from the
WSDL file and looks like this:


&lt;?xml version='1.0' encoding="UTF-8" standalone="yes" ?&gt;
&lt;jbi version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xmlns="http://java.sun.com/xml/ns/jbi" 
                        xmlns:sms="http://it.azzola/sms"&gt;
 &lt;services binding-component="true"&gt;
   &lt;consumes service-name="sms:smsService" 
             interface-name="sms:smsWSDLOperation" 
             endpoint-name="smsPort"&gt;
   &lt;/consumes&gt; 
  &lt;/services&gt;
&lt;/jbi&gt; 

In the jbi.xml file, we specify the interface used to exchange
data. This file is a part of the ServiceUnit.

The next step is to create a directory structure like the one in
the figure and then create a new .zip file with the name
SMSSU.zip, containing the files shown in Figure 8.

SU structure "190" />
Figure 8. SU structure

Now we can create the service assembly that can be deployed
directly in the JBI environment. A service assembly is an
aggregation of one or more SU. To do that, we have to create another
XML artifact where we specify that we use an HTTP binding component;
that is, the interface to our component. A piece of the XML file
descriptor is shown here:


&lt;service-unit&gt;
  &lt;identification&gt;
    &lt;name&gt;Hello_SoapBC_TestSU1&lt;/name&gt;
        &lt;description&gt;
           This service unit enables soap inbound endpoint for a service
        &lt;/description&gt;
  &lt;/identification&gt;
  &lt;target&gt;
    &lt;artifacts-zip&gt;SMSSU.zip&lt;/artifacts-zip&gt;
    &lt;component-name&gt;sun-http-binding&lt;/component-name&gt;
  &lt;/target&gt;
 &lt;/service-unit&gt; 

Notice that we refer to the "font-style: italic;">SMSSU.zip we created before, and we
use sun-http-binding to enable the SOAP interface. Now
we have to create a directory structure like the one in Figure 9,
and finally we create SMSSA.ZIP.

Service Assembly structure height="74" width="154" />
Figure 9. Service Assembly structure

Deploy it and start the application assembly.

Testing the Application

We can test our application. To do so, we can develop a simple
web service client to send messages to our application. As an input
file we can use a XML file like the one shown below:


&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;soapenv:Envelope 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:sms="http://xml.netbeans.org/schema/smsSchema"&gt;
    &lt;soapenv:Body&gt;
          &lt;sms:smsData&gt;
            &lt;sms:msisdn&gt;destination number&lt;/sms:msisdn&gt;
            &lt;sms:body&gt;test&lt;/sms:body&gt;
          &lt;/sms:smsData&gt; 
   &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;         

When you run the test class, your mobile phone should ring and
notify that you've received a new short message!

Conclusion

In this article, we explored some concepts about the JBI
technology and we analyzed how to create a simple component that
can be plugged in the JBI environment. We explored the basic steps
we need to follow to develop a component and the artifacts that
must be created in order to configure a service assembly. Now we
have our component up and running in the JBI environment we can use
it in any way we like. For example, we could develop an
application that exploits this component to send messages when a
file is inserted under a specific directory. In this case, we could
use a File Binding component to achieve this goal.

Resources


width="1" height="1" border="0" alt=" " />
Francesco Azzola is an electronic engineer with more than ten years' experience in architecting and developing EE applications.
Related Topics >> Programming   |