Scenario 4: Stand-alone server applications
This chapter describes the development of two sample stand-alone server applications that respond to requests published by the mobile application described in Chapter 6, “Scenarios overview” on page 175. These server applications demonstrate direct communications between mobile applications and a back-end server application, where both types of applications interface to the IBM MessageSight appliance.
The two server applications have exactly the same functionality:
They respond to requests issued by the mobile application.
They both use asynchronous reception of request messages.
The two server applications are both written in Java, but use different types of messaging application programming interfaces (APIs):
One application is implemented using the Java API for MQTT. This set of Java classes is distributed with the standard WebSphere MQ distribution.
The second application is implemented using the Java Message Service (JMS) classes implemented for the IBM MessageSight appliance.
10.1 A stand-alone server application implemented with MQTT Java
This section explains the development of a stand-alone server application that is implemented using the MQTT Java classes. The example illustrates how applications can communicate directly with the IBM MessageSight appliance without using any intermediate middleware, such as WebSphere MQ.
This can be necessary in situations where there is a high messaging load, or relatively low latency is required. It also alleviates the need to implement, administer, manage, and maintain intermediate middleware components.
The MQTT Java classes are provided in the MQTT software development kit (SDK) with WebSphere MQ. Note that the classes used in this sample server application are the org.eclipse.paho.client.mqttv3 Java classes, which are also provided in a WebSphere MQ distribution.
This sample server application uses a properties file for configuration information. The server application demonstrates an alternative approach, in place of the use of WebSphere Message Broker or IBM Integration Bus, to processing requests from mobile applications.
This server application receives requests from, and sends responses to, the mobile application described in Chapter 6, “Scenarios overview” on page 175.
The sample server application carries out the following steps:
1. Parse the command-line interface (CLI) arguments and process the properties file.
2. Create an MQTT client. This demonstrates how additional security can be used through the use of a user name and password. The application also shows how to set a Last Will and Testament, which is an MQTT feature that generates an alert if there is an unexpected break in the connection between the MQTT server (appliance) and the MQTT client (application).
3. This server application uses callbacks for the following functions:
 – Arrival of a request message
 – Indication of complete delivery when a response message has been published to the required response Topic
 – When a connection to the MQTT server (appliance) is lost
4. Create a connection to the MQTT server (the IBM MessageSight appliance).
5. Create a subscription for the required request Topic. This request Topic uses a wildcard, because requests can be received from multiple different requesting mobile applications.
6. When a request message is received, identify the source of the message, the message type and send the required response to the requesting application.
The application continues running perpetually, and must be stopped with the Ctrl+C keys. This is for demonstration purposes only. A conventional, production-quality application needs to stop as dictated by the business usage and associated functional requirements.
Example 10-1 shows the configuration file (properties file) for this sample server application.
Example 10-1 Sample configuration file
#
# IBM MessageSight sample MQTT server application
# Configuration file
#
ima.servers=192.168.121.135
ima.port=16102
client.id=ITSOSVR01
req.topic=itso/driver/assistance/#
resp.topic=itso/driver/response/
#
# Last Will and Testament
lwt.topic=ITSO/LWT/SVR/ITSOSVR01
lwt.retain=true
#
# The following time is in milliseconds
sleep.time=60
#
clean.session=false
qos=2
#
# Username and Password are used for additional security
#
#user.name=testuser
#user.passwd=testpassword
Note a few of the items in the configuration file:
The MQTT client identifier used by this server application. As specified by the MQTT V3.1 specification, the MQTT Client Identifier has these attributes:
 – Must be between 1 and 23 characters
 – Must uniquely identify the client to the MQTT server
 – Must be unique across all clients connecting to the same MQTT server
The use of a wildcard, number sign (#), in the request topic.
The topic to be used for the Last Will and Testament for this application.
The MQTT messaging quality of service (QoS) that is used for both request and response messages.
Example 10-2 shows the required Java imports for this sample server application.
Example 10-2 The server application Java imports
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.Date;
import java.text.SimpleDateFormat;
 
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttCallback
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
Example 10-3 depicts the creation of an MQTT client. It also shows the optional use of additional security credentials, such as the username and password, and the configuration of the “Last Will and Testament” feature. The Server and Port, required identifiers and necessary topic names are passed into the application using the properties file.
In this code snippet, the application subscribes to the request message topic using a wildcard. Note the configuration of the asynchronous callbacks.
Example 10-3 Initial MQTT setup of the server application
try {
client = new MqttClient(URL, clientID, null);
CallBack callback = new CallBack(clientID);
client.setCallback(callback);
MqttConnectOptions conOptions = new MqttConnectOptions();
 
// NOTE: cleansession is being set to 'true'
// We should use a parameter to control this
conOptions.setCleanSession(true);
// Other connectOptions that can be set are:
// username and password
// Last Will and Testament (LWT)
if (userPass != null)
{
conOptions.setUserName(userName);
conOptions.setPassword(userPass.toCharArray());
}
if (lwtTopicName != null) {
MqttTopic lwtTopic = client.getTopic(lwtTopicName);
String lwtMsg = "MY LWT";
conOptions.setWill(lwtTopic, lwtMsg.getBytes(), LWTQOS, lwtRetain);
}
 
// Connect to the server
client.connect(conOptions);
 
// Subscribe to Request Topic
System.out.println("Subscribing to topic "" + reqTopicName
+ "" for client instance "" + client.getClientId()
+ "" using QoS " + QoS + ". Clean session is true");
client.subscribe(reqTopicName, QoS);
This server application uses cleansession=true, because the application does not want the MQTT server to retain any information about it when the application is not connected. When the server application connects, its session is “clean”, meaning that the MQTT server has not retained any information from any previous sessions with this client.
This can occur if publications that matched the application’s subscriptions were received by the MQTT server while the application was no longer connected to the MQTT server. If cleansession=false, the MQTT server retains the published messages awaiting the application to reconnect to the MQTT server.
The Last Will and Testament message is published using the topic specified by the application when a connection between the application and MQTT server is unexpectedly broken (an unplanned loss of connection). For example, a monitoring application can subscribe to these Last Will and Testament messages and report on, or take any other required actions for, the detection of broken connections.
Example 10-4 depicts the implementation of the asynchronous callback methods. These are implemented in a separate Java class.
Example 10-4 Callback methods
/*
* Callback.java
*
* This file contains the callback classes for asynchronous
* behaviour of the MQTT application.
*
* The required methods are:
* - connectionLost
* - messageArrived
* - deliveryComplete
*
*/
package com.ibm.itso;
 
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
 
public class CallBack implements MqttCallback
{
public int deliveryConf = 0;
public int respRcvd = 0;
private String instanceData = "";
public CallBack(String instance) {
instanceData = instance;
}
@Override
public void connectionLost(Throwable cause)
{
System.out.println("Connection lost on instance "" + instanceData
+ "" with cause "" + cause.getMessage() + "" Reason code "
+ ((MqttException)cause).getReasonCode() + "" Cause ""
+ ((MqttException)cause).getCause() + """);
cause.printStackTrace();
}
@Override
public void deliveryComplete(IMqttDeliveryToken arg0)
{
try
{
//System.out.println("Delivery token "" + token.hashCode()
// + "" received by instance "" + instanceData + """);
deliveryConf++;
} catch (Exception e) {
e.printStackTrace();
}
}
 
/*
* (non-Javadoc)
* @see org.eclipse.paho.client.mqttv3.MqttCallback#messageArrived(java.lang.String, org.eclipse.paho.client.mqttv3.MqttMessage)
*
* This method receives the request, calculates the Response Topic, and calls
* the publishResp method to process and send the response.
*
* For the ITSO Transport sample, the expected request topic structure is:
* /itso/driver/assistance/ACMalfunction/<TruckNumber>
* /itso/driver/assistance/FlatTire/<TruckNumber>
* /itso/driver/assistance/Accident/<TruckNumber>
*
* Request payload is "DriverID+TruckNumber+Longitude+Latitude+hh:mm:ss+Date+<ACMalfunction|FlatTire|Accident>+Text"
*
* Request Topic Elements:
* Element[3] - Incident tyoe
* Element[4] - Truck Number
*
* Payload Elements:
* Element[0] - Driver ID
* Element[1] - Truck ID
* Element[6] - Incident Type
*
*/
@Override
public void messageArrived(String topicName, MqttMessage msg) throws Exception
{
try
{
if (topicName.contains("/"))
{
// Split it.
String[] topElements = topicName.split("/");
String reqPayload = msg.toString();
String myRspTopic = ITSOMQTTServer.rspTopicName + topElements[4];
         // Add the Truck Number to the Response Topic
System.out.println("MsgArr: Req Topic: "+topicName+" payload          "+reqPayload+" Resp Topic "+myRspTopic);
         ITSOMQTTServer.publishResp(myRspTopic, reqPayload);
} else {
throw new IllegalArgumentException("Received topic name " +             topicName + " does not contain /");
}
respRcvd++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
The messageArrived method is where the request message is received and parsed, and the request type and origins of the request are identified. The required response Topic is constructed, and the response processing method
is started.
In this sample, no special processing is done in the connectionLost method to reestablish the connection to the MQTT server. For an example of reestablishing this connection, see 3.3.4, “A sample JMS publisher” on page 63, and 3.3.5, “A sample JMS subscriber” on page 71.
The deliveryComplete method keeps a running total of the number of responses that have been published by this server application.
Example 10-5 shows the response message processing, and the publication of an appropriate response message.
Example 10-5 Response message processing
// Send a response to the request
//
public static void publishResp(String rspTopic, String inMsg)
{
String respPayload = " ";
Date now;
SimpleDateFormat dtFormat = new SimpleDateFormat("E yyyy.MM.dd 'at' HH:mm:ss    zzz");
now = new Date();
String dtOut = dtFormat.format(now);
 
MqttTopic myTopic = client.getTopic(rspTopic);
MqttMessage rspMsg = new MqttMessage();
 
// If the request payload was "QUIT"
// then terminate this server app.
if (inMsg.compareToIgnoreCase("quit") == 0)
{
quitSvr = true;
return;
}
 
try {
// Parse the request payload
// Payload Elements:
// Element[0] - Driver ID
// Element[1] - Truck ID
// Element[6] - Incident Type
if (inMsg.contains("+"))
{
String[] msgElements = inMsg.split("\+");
if (msgElements[6].compareToIgnoreCase("ACMalfunction") == 0)
{
respPayload = msgElements[0]+", AC engineer dispatched to your             location. "+dtOut+" Dispatcher";
}
if (msgElements[6].compareToIgnoreCase("FlatTire") == 0)
{
respPayload = msgElements[0]+", Vehicle mechanic dispatched to your            location. "+dtOut+" Dispatcher";
}
if (msgElements[6].compareToIgnoreCase("Accident") == 0)
{
respPayload = msgElements[0]+", Emergency staff notified and             dispatched to your location. "+dtOut+" Dispatcher";
}
} else {
throw new IllegalArgumentException("Received request payload " +             inMsg + " does not contain a correct separator '+'");
}
System.out.println("*** publishResp RespTopic: "+rspTopic+" payload:       "+respPayload);
rspMsg.setPayload(respPayload.getBytes());
rspMsg.setQos(QoS);
myTopic.publish(rspMsg);
// The following code is just for the convenience of sample purposes
// Find a more efficient way to do this processing in a real app
myTopic = null;
rspMsg = null;
} catch (MqttException e) {
e.printStackTrace();
}
}
This publishResp method identifies the request type, and constructs a suitable response payload. Three different request message types are used in this sample:
An accident involving the truck.
A flat tire on the truck.
An air conditioning malfunction in the truck’s cargo bay. This might lead to the loss of perishable goods that require an air-conditioned environment.
A temporary response topic and MQTT message are created, used, and deleted each time that a response must be sent. We realize that this is not an efficient or elegant way of implementing this, and it should not be used in real applications. It has been used for sample purposes only.
10.2 A stand-alone server application implemented using IBM MessageSight JMS classes
This section explains the development of a stand-alone server application that is implemented using the IBM MessageSight JMS classes. In a similar manner to the prior example, this sample server application illustrates how applications can communicate directly with the IBM MessageSight appliance without using any intermediate middleware, such as WebSphere MQ.
The required JMS classes can be obtained as previously explained in section 3.3.2 (IBM MessageSight JMS Client Pack).
This sample application, implemented using JMS, demonstrates that messages can be exchanged with applications using MQTT APIs. The JMS application uses JMS BytesMessage objects as the message format for message exchange with MQTT applications.
This JMS application also uses a MessageListener to asynchronously accept request messages. Because this application exchanges messages with an MQTT application, it uses the JMS publish/subscribe paradigm.
This server application receives requests from, and sends responses to, the mobile application described in Chapter 5 (MQTT with mobile applications).
The sample server application carries out the following steps:
1. Parse the command-line arguments and process the properties file.
2. Create a connection to the JMS server, the IBM MessageSight appliance.
3. Create a subscription for the required request Topic. This request Topic uses a wildcard, because requests can be received from multiple different requesting mobile applications.
4. Establish a MessageListener for the MessageConsumer for the request Topic.
5. For demonstration purposes only, the server application creates three MessageProducers for responding to the mobile applications. The identities of these three message producers are configurable using the properties file.
6. Establishes an ExceptionListener on the connection. If a break in the connection to the JMS server is detected, the application will attempt to re-establish a connection to the JMS server.
7. All request and response processing is done in the MessageListener.
8. The server application is capable of processing both JMS TextMessage and BytesMessage messages.
Example 10-6 shows the configuration file (properties file) for this sample JMS server application.
Example 10-6 The JMS server application configuration file
#
# IBM MessageSight sample JMS Server app
# Configuration file
#
ima.servers=192.168.121.135
ima.port=16102
client.id=ITSOJMSSVR01
req.topic=itso/driver/assistance/#
resp.topic=itso/driver/response/
#
# JMS Delivery Mode - true=persistent false=non-persistent
delivery.mode=true
#
# The following time is in millisecs
sleep.time=100
#
# Username and Password are used for additional security
#
#user.name=testuser
#user.passwd=testpassword
#
# Up to 3 possible Truck Identifiers
#
dest1=ITSOTRUCK01
dest2=ITSOTRUCK02
dest3=ITSOTRUCK03
Example 10-7 shows the required JMS imports for this sample JMS server application.
Example 10-7 JMS imports
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.MessageConsumer;
import javax.jms.Topic;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.BytesMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ExceptionListener;
 
import java.io.*; // Standard Java imports
import java.text.SimpleDateFormat;
import java.util.*;
 
import com.ibm.ima.jms.ImaJmsException;
import com.ibm.ima.jms.ImaJmsFactory;
import com.ibm.ima.jms.ImaJmsObject;
import com.ibm.ima.jms.ImaProperties;
Example 10-8 depicts the creation of a JMS connection, session, and the required Topics. A single MessageConsumer and three MessageProducers are also created. It also shows optional use of additional security credentials, such as the username and password. The Server and Port, required identifiers, and necessary topic names are passed into the application using the properties file.
In this code snippet, the application subscribes to the request message topic using a wildcard. Note the configuration of the asynchronous MessageListener for the MessageConsumer. Also note the creation of an ExceptionListener for the connection.
Example 10-8 JMS object creation
Topic respDest1 = null;
Topic respDest2 = null;
Topic respDest3 = null;
 
// Parse the arguments
parseArgs(args);
 
/*
* Connect to server
*/
boolean connected = doConnect();
 
if (!connected)
throw new RuntimeException("Failed to connect!");
// Create a session.
sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic reqTopic = getTopic(reqTopicName);
if (duraSubsName != null)
{
// Create a Durable Subscriber
cons = sess.createDurableSubscriber(reqTopic, duraSubsName);
System.out.println("Created a Durable Subscription named "+duraSubsName);
} else {
// Create a standard message consumer
cons = sess.createConsumer(reqTopic);
}
// Create some sample responders - up to 3
respDest1 = getTopic(rspTopicPref+dest1Id);
respDest2 = getTopic(rspTopicPref+dest2Id);
respDest3 = getTopic(rspTopicPref+dest3Id);
responder1 = sess.createProducer(respDest1);
responder2 = sess.createProducer(respDest2);
responder3 = sess.createProducer(respDest3);
 
// Create Consumer objects
// Using a wildcard on the request topic for subscription
try
{
rqstListener msgListener = new rqstListener();
cons.setMessageListener(msgListener);
} catch (JMSException je) {
System.err.println("Error setting MsgListener" + je.getMessage());
System.err.println(je);
}
// Do not forget to start the connection
conn.start();
//System.out.println("Consumer Session started OK! Using Topic: "+consDest);
 
// Create the keyboard reader, so that we can get user input
BufferedReader in = new BufferedReader( new InputStreamReader(System.in ));
 
char answer = '';
System.out.println("*** To end program, enter Q or q, then <return>");
while (!((answer == 'q') || (answer == 'Q')))
{
Thread.sleep(SLEEP_TIME*1000); // Has to be in milliseconds
try {
answer = (char) in.read();
} catch (IOException e) {
System.err.println("I/O exception: " + e.toString());
}
}
 
// We must remember to call the close() method on all the objects we
// have used, to ensure a clean tidy-up of all resources held
cons.close(); // Close the consumer
responder1.close();
responder2.close();
responder3.close();
 
sess.close();
conn.close();
//respSession.close();
//respConn.close();
System.out.println("*** IMAJMSServer terminated!");
Example 10-9 shows the creation of the required Java Naming and Directory Interface (JNDI)-administered objects (the ConnectionFactory and the required request and response Topics).
Example 10-9 JNDI-administered object creation
/**
* Get connection factory administered object.
*
* @return ConnectionFactory object.
*
* Note: In production applications, this method would retrieve a
* ConnectionFactory object from a JNDI repository.
*/
public static ConnectionFactory getCF() throws JMSException {
ConnectionFactory cf = ImaJmsFactory.createConnectionFactory();
/*
* NOTE: For high availability configurations, the serverList
* must contain the list of IBM MessageSight server host names or IP addresses
* so that the clientcan attempt to connect to alternate hosts if connection
* (or reconnection)to the primary fails.
*/
((ImaProperties) cf).put("Server", serverList);
((ImaProperties) cf).put("Port", serverPort);
if (disableACK)
{
((ImaProperties) cf).put("DisableACK", true);
System.err.println("ACKs disabled in ConnectionFactory!");
}
 
/*
* After setting properties on an administered object, it is a best practice to
* run the validate() method to assure all specified properties are recognized
* by the IBM MessageSight JMS client.
*/
ImaJmsException errors[] = ((ImaProperties) cf).validate(true);
if (errors != null)
throw new RuntimeException("Invalid properties provided for the connection    factory.");
return cf;
}
 
/**
* Create topic administered object.
*
* @return Topic object.
*
* Note: In production applications, this method would retrieve a
* Topic object from a JNDI repository.
*/
public static Topic getTopic(String topicName) throws JMSException {
//System.out.println("getTopic: "+topicName);
Topic dest = ImaJmsFactory.createTopic(topicName);
return dest;
}
Example 10-10 shows the initial JMS connection establishment. Note the creation of an ExceptionListener in the connect method. Connection re-establishment is attempted here after a connection with the JMS server has been broken.
Example 10-10 Connection and re-connection methods
/**
* Establish a connection to the server. Connection attempts are retried until
* successful or until the specified timeout for retries is exceeded.
*/
public static boolean doConnect()
{
int connattempts = 1;
boolean connected = false;
long starttime = System.currentTimeMillis();
long currenttime = starttime;
 
/*
* Try for up to connectTimeout milliseconds to connect.
*/
while (!connected && ((currenttime - starttime) < connectTimeout))
{
try { Thread.sleep(5000); } catch (InterruptedException iex) {}
if (debug)
System.out.println("Attempting to connect to server (attempt " +                           connattempts + ").");
connected = connect();
connattempts++;
currenttime = System.currentTimeMillis();
}
return connected;
}
 
/**
* Connect to the server
*
* @return Success (true) or failure (false) of the attempt to connect.
*/
public static boolean connect()
{
/*
* Create connection factory and connection
*/
try
{
fact = getCF();
// If username AND user password have been defined in the
// config file, then set these as additional connection security.
if (userPass != null)
conn = fact.createConnection(userName, userPass);
else
conn = fact.createConnection();
// Set the Client Identifier for the connection
conn.setClientID(clientID);
// Set an Exception Listener
// for the connection.
conn.setExceptionListener(new ExceptionListener()
{
public void onException(JMSException jmse)
{
System.err.println("An exception received through the                                 ExceptionListener");
if (isConnClosed())
{
// Attempt to reconnect
System.err.println("*** Connection is closed. Attempting to                                   reconnect and continue.");
boolean reconnected = doConnect();
 
if (reconnected)
{
// Simply continue
System.out.println("*** Reconnected OK! Continuing!");;
} else {
System.err.println("*** Failed to reconnect. Exiting!");
System.exit(0);
}
} else {
System.err.println("*** Not a closed connection. Exiting!");
jmse.printStackTrace();
System.exit(0);
}
}
});
 
/*
* Check that we are using IBM MessageSight JMS administered objects
      * before calling * provider specific check on property values.
*/
if (fact instanceof ImaProperties)
{
/*
* For high availability, the connection factory stores the list of
* IBM MessageSight server
* host names or IP addresses. When connected, the connection object
* contains only the host name or IP
* to which the connection is established.
*/
System.out.println("Connected to " +          ((ImaProperties)conn).getString("Server"));
}
/*
* Connection has succeeded. Return true.
*/
return true;
} catch (JMSException jmse) {
System.err.println(jmse.getMessage());
/*
* Connection has failed. Return false.
*/
return false;
}
}
 
/**
* Check to see if connection is closed.
*
* When the IBM MessageSight JMS client detects that the connection to the
 * server has been * broken, it marks the connection object closed.
*
* @return True if connection is closed or if the connection object is null,
 * false otherwise.
*/
public static boolean isConnClosed()
{
if (conn != null)
{
/*
* Check the IBM MessageSight JMS isClosed connection property
* to determine whether the connection state is closed.
* This mechanism for checking whether the connection is closed
* is a provider-specific feature of the IBM MessageSight
  * JMS client. So check first that the IBM MessageSight JMS
* client is being used.
*/
if (conn instanceof ImaProperties)
{
return ((ImaProperties) conn).getBoolean("isClosed", false);
} else {
// It cannot be determined whether the connection is closed so
           // return false.
return false;
}
} else {
return true;
}
}
Example 10-11 shows the request and response processing in the MessageListener. Note that both JMS TextMessage and BytesMessage objects are handled. BytesMessage messages are used when message exchanges take place between JMS applications and MQTT applications.
Example 10-11 MessageListener request and response processing
public static class rqstListener implements MessageListener
{
public void onMessage(Message message)
{
String reqTopic = "";
String respTopic = "";
String reqMsgId = "";
String reqCorrelId = "";
String respTruck = "";// The Truck Id that originated the request message
String reqPayload = "";
String respPayload = " ";
String driverID = "";
String incidentType = "";
int plLgt = 0;// Payload length (size)
Message respMessage = null;
 
try {
reqTopic = ((Topic)message.getJMSDestination()).getTopicName();
         // Get the request message's            Message ID
reqMsgId = message.getJMSMessageID();
         // Get the request message's Correlation ID
reqCorrelId = message.getJMSCorrelationID();
} catch (JMSException je) {
je.printStackTrace();
}
 
if (reqTopic.contains("/")) {
// Split it.
String[] topElements = reqTopic.split("/");
respTruck = topElements[4]; // Get the Truck Number
// Get the message payload
try {
if (message instanceof TextMessage)
{
reqPayload = ((TextMessage) message).getText();
} else if (message instanceof BytesMessage)
{
byte[] msgBytes = new byte[128];;
plLgt = ((BytesMessage)                                       message).readBytes(msgBytes);
reqPayload = new String(msgBytes);
reqPayload = reqPayload.trim(); // Trim whitespace
//System.out.println("--- Length: "+plLgt+"                               Payload: "+reqPayload);
}
} catch (JMSException je)
{
je.printStackTrace();
}
if (reqPayload.contains("+")) {
String[] msgElements = reqPayload.split("\+");
incidentType = msgElements[6];
driverID = msgElements[0];
} else {
throw new IllegalArgumentException("Received request                       payload " + reqPayload + " does not contain a correct                       separator '+'");
}
Date now = new Date();
SimpleDateFormat dtFormat = new SimpleDateFormat("E yyyy.MM.dd 'at'           HH:mm:ss zzz");
String dtOut = dtFormat.format(now);
 
if (incidentType.compareToIgnoreCase("ACMalfunction") == 0) {
respPayload = driverID+", AC engineer dispatched to your                  location. "+dtOut+" Dispatcher";
}
if (incidentType.compareToIgnoreCase("FlatTire") == 0) {
respPayload = driverID+", Vehicle mechanic dispatched to your                  location. "+dtOut+" Dispatcher";
}
if (incidentType.compareToIgnoreCase("Accident") == 0) {
respPayload = driverID+", Emergency staff notified and dispatched                 to your location. "+dtOut+" Dispatcher";
}
} else {
throw new IllegalArgumentException("Received topic name " +                 reqTopic + " does not contain /");
}
 
System.out.println("MsgArr: Req Topic: "+reqTopic+" payload          "+reqPayload+" from TruckID "+respTruck);
//System.out.println("*** Message ID: " + reqMsgId+" Correl ID: " +         reqCorrelId);
 
if (message instanceof TextMessage)
{
try {
respMessage = sess.createTextMessage();
// Set the response payload
((TextMessage) respMessage).setText(respPayload);
} catch (JMSException je) {
je.printStackTrace();
}
} else if (message instanceof BytesMessage) {
// Probably a message from a MQTT client
try {
respMessage = sess.createBytesMessage();
// Set the response payload
((BytesMessage)                     respMessage).writeBytes(respPayload.getBytes());
} catch (JMSException je) {
je.printStackTrace();
}
}
try {
// Set the required response delivery mode
if (respDelMode)
{
respMessage.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
} else {
respMessage.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
}
// Set the response Correlation ID = request Message ID
respMessage.setJMSCorrelationID(reqMsgId);
 
// We decide on which Topic to send the response
// based on the ClientID (i.e TruckId) in the
// incoming request message.
 
if (respTruck.equalsIgnoreCase(dest1Id))
responder1.send(respMessage);
else if (respTruck.equalsIgnoreCase(dest2Id))
responder2.send(respMessage);
else if (respTruck.equalsIgnoreCase(dest3Id))
responder3.send(respMessage);
} catch (JMSException je) {
System.err.println("Error processing the Response" +                je.getMessage());
System.err.println(je);
}
}
}
10.3 Conclusion
The intent of this chapter was to demonstrate how mobile applications can communicate directly with back-end server applications using IBM MessageSight. The two types of applications, mobile and back-end, can use any mix of MQTT and JMS (MessageSight classes) messaging systems.
 
Remember: JMS is an API, not a messaging protocol.
The mobile applications can use any suitable implementation language, such as Java, JavaScript, Objective-C, and so on, if they can access the required messaging APIs. Similarly, the back-end applications can use any implementation language that provides access to the MQTT or JMS APIs.
Note that both MQTT and JMS messaging systems can use different sets of options when interacting with the IBM MessageSight server. The application developers must become familiar with the similarities and differences with the options of the two messaging APIs. MQTT is only for publish/subscribe, but JMS provides both publish/subscribe and queue-based messaging. The IBM MessageSight JMS classes implement both types of JMS messaging.
The back-end applications have a choice of using synchronous or asynchronous message reception, by using either the MQTT or JMS APIs.
For additional information, guidance, and examples, see the Mobile development topic on the IBM developerWorks website:
The following websites provide more information about JMS-related topics:
IBM MessageSight JMS client API reference:
Package javax.jms:
The following website provides information about programming MQTT for C, Java, and JavaScript:
 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.5.217