How to use the Java Message Service (JMS)-Agent Gateway
Author: Edward Curry (ECRG, NUI, Galway)
Date: March 29, 2004
JmsAgentGateway version 0.5
Java platform: Sun JDK 1.4 Linux
JADE version 3.1
The Java Message Service (JMS)-Agent Gateway is a utility designed to allow
agents within a JADE platform to interact with a JMS provider. This tutorial
describes how to install and use the gateway to interact with a JMS provider,
using both the Point-to-Point and Publish/Subscribe messaging models. Users
should be familiar with the FIPA-Subscribe interaction protocol and the JADE
implementation of the protocol, see the JADE Programmers Guide for more information.
Please note this Gateway only works on JDK 1.4
Installation
In order to install the JMS-Agent Gateway the following steps must be performed:
- The JMS-Agent Gateway must be downloaded from the JADE add-ons download page.
- The latest version 0.5 is also available from http://ecrg.it.nuigalway.ie/downloads/jmsagentgateway-0.5.zip
- After downloading, extract the JMS-Agent Gateway package under the root
of your jade installation. You should have a hierarchy like jade/add-ons/jmsagentgateway
- The following table shows the required files needed to run the JMS-Agent
Gateway. The common support files are mandatory, they must be downloaded.
- You must also download the support libraries for the JMS provider you want
to run. (Note: The JMS-Agent Gateway does not currently fully-support
simultaneous JMS providers)
- Your JMS Provider must be setup correctly and you must create any destinations
you which to interact with, for more details on these issues please consult
your providers manual. (Note: Unlike the JMS-MTP, the JMS-Agent Gateway
will NOT create the required destinations on a JMS provider)
Common Support Libraries (Required) |
|
|
|
Location |
Library |
Available From |
Notes |
add-ons/jmsagentgateway/lib |
log4j-1.2.8.jar |
jakarta-log4j-1.2.8.zip |
Supports log4j-1.2.7 + |
add-ons/jmsagentgateway/lib |
beangenerator.jar |
beangeneratorAddon-3.1.zip |
|
|
|
|
|
OpenJMS Support Libraries (Optional) |
|
|
|
Location |
Library |
Available From |
Notes |
add-ons/jmsagentgateway/lib |
openjms-client-X..jar |
http://openjms.sourceforge.net/ |
Download OpenJMS provider, files located in /lib |
add-ons/jmsagentgateway/lib |
exolabcore-0.3.6.jar |
|
|
add-ons/jmsagentgateway/lib |
commons-logging-1.0.3.jar |
http://jakarta.apache.org/commons/logging |
|
|
|
|
|
JBossMQ Support Libraries (Optional) |
|
|
|
Location |
Library |
Available From |
Notes |
add-ons/jmsagentgateway/lib |
jbossall-client.jar |
http://www.jboss.org/ |
Download JBoss provider, files located in /client |
add-ons/jmsagentgateway/lib |
jbossjmx-ant.jar |
|
. |
|
|
|
|
SonicMQ Support Libraries (Optional) |
|
|
|
Location |
Library |
Available From |
Notes |
add-ons/jmsagentgateway/lib |
jmxri.jar |
http://www.sonicmq.com/ |
Download SonicMQ, files located in /lib |
add-ons/jmsagentgateway/lib |
jndi.jar |
|
|
add-ons/jmsagentgateway/lib |
mfcontext.jar |
|
|
add-ons/jmsagentgateway/lib |
mgmt_agent.jar |
|
|
add-ons/jmsagentgateway/lib |
mgmt_client.jar |
|
|
add-ons/jmsagentgateway/lib |
mgmt_config.jar |
|
|
add-ons/jmsagentgateway/lib |
sonic_Client.jar |
|
|
add-ons/jmsagentgateway/lib |
sonic_mgmt_client.jar |
|
|
add-ons/jmsagentgateway/lib |
sonic_mgmt.jar |
|
|
add-ons/jmsagentgateway/lib |
xercesImpl.jar |
|
Must be file from SonicMQ distribution |
add-ons/jmsagentgateway/lib |
xmlParserAPIs.jar |
|
Must be file from SonicMQ distribution |
Compiling
The Jade Makefile will not compile the JMS-Agent Gateway. To compile the JMS-Agent
Gateway you have to use the 'build.xml' ant-file located in the jmsagentgateway
directory. The following rules are available:
- ant compile - compiles the JMS-Agent Gateway classes
- ant lib - creates the jmsagentgateway.jar archive
- ant clean - removes the compiled classes and the .jar archive
- ant doc - creates javadoc for the JMS-Agent Gateway
- execute_jmsagentgateway - starts a JADE container with a JMS-Agent Gateway
- execute_clientA - runs client A
- execute_clientB - runs client B
- execute_clientC - runs client C
- execute_pingAgent - runs the PingAgent
- execute_pingClient - runs the PingClient
Usage
Important OpenJMS and JBossMQ Note:
When activating a JMS-Agent Gateway that uses a OpenJMS/JBossMQ provider you will
need to change the port JADE runs on (1099) as this is the same port number
used by the OpenJMS/JBoss JNDI service. To specify a port for JADE to run on,
simple use the -port switch on startup.
In order to use the JMS-Agent Gateway, the jmsagentgateway.jar and jmsagentgateway.properties
file must be on the classpath when starting( either by including it into the
$CLASSPATH environment variable - %CLASSPATH% under windows or by specifying
it on the command line ).
Activating the jmsagentgateway Agent
To activate the JMS-Agent Gateway utility simply create a new agent of type
"ie.nuigalway.ecrg.jade.jmsagentgateway.JMS-Agent Gateway" on the
JADE platform
Configuration
JMS-Agent Gateway Ontology Class Hierarchy
In order to interact with the JMS-Agent Gateway you need to use the ontology defined
below, the following sections provide practical examples of using the ontology.
Interacting with the JMS-Agent Gateway
This section provides a brief overview of the main interactions with the JMS-Agent Gateway.
Locating the JmsProxyAgent
The JMS-Agent Gateway registers itself an Agent proxy in the DF as type "JmsProxyAgent".
This type may be set in the agents configuration file.
Utility Methods
In order to simplify the process of interacting with the JMS-Agent Gateway the
following utility class has been supplied
public class Util {
/**
* Utility method for creating provider information
*
* @param providerURL URL of the provider
* @param providerICF Initial Connection Factory Class
* @param destType Queue or Topic Destination
* @return Returns a provider information object
*/
public static ProviderInfo createProviderInfo(boolean destType, String providerURL, String providerICF);
/**
* Utility method for creating a message
*
* @param destination destination of message
* @param payload The messages payload
(Any Serializable Java Object)
* @param deliveryMode Persistent setting of the message
* @return Newly created Jms Message
* @exception Exception Error creating the message
*/
public static JmsMessage createMessage(String destination, java.io.Serializable payload, Boolean deliveryMode) throws Exception;
/**
* Utility method to create a Subscription
*
* @param destination Topic or Queue to subscribe to
* @param durable Subsctiptions durability setting
* @return Newley created subscription info
*/
public static Subscription createSubscription(String destination, Boolean durable);
/**
* Convert a BASE64 string payload to a serializable object
*
* @param payload BASE64 message payload string
* @return Serialized payload
* @exception Exception Error during conversion
*/
public static java.io.Serializable convertStringToObject(String payload) throws Exception;
/**
* Convert an object to a BASE64 string
*
* @param obj Payload object
* @return Payload object converted to a BASE64 string
* @exception Exception Error during object to string conversion
*/
public static String convertObjectToString(java.io.Serializable obj) throws Exception;
}
|
Publishing a Message
- Create a PublishMessage AgentAction.
- Set the ProviderInfo of the Action, specifying the destination type
(Util.QUEUE | Util.TOPIC), providers URL and the providers initial
context factory.
- Set the Message, specifying the destination, the payload (any serializable
Java object) and the delivery mode (Util.PERSISTENT | Util.NON_PERSISTENT).
- Send the message to the JMS-Agent Gateway
- (Note: The message payload object is serialized and converted to a BASE64
string for transportation, the utility object contains methods to convert
serializeable objects to and from this encoding)
/**
* Utility method to publish a message
*
* @param payload Payload of the message to be published
*/
private void publishMessage(String payload) {
PublishMessage pm = new PublishMessage();
// Using a connection with the openJMS provider
pm.setProviderInfo(Util.createProviderInfo(Util.QUEUE, "rmi://localhost:1099/", "org.exolab.jms.jndi.InitialContextFactory"));
try {
// Set Destination to "queue1"
pm.setMessage(Util.createMessage("queue1", payload, Util.PERSISTENT));
} catch (Exception e) {
System.out.println("Error creating message:" + e.toString());
}
System.out.println("Sending message: " + payload);
sendMessage(ACLMessage.REQUEST, PM);
}
/**
* Utility method for sending a message
*
* @param performative Performative for the message
* @param action The AgentAction of the message to be sent
*/
private void sendMessage(int performative, AgentAction action) {
ACLMessage msg = new ACLMessage(performative);
msg.setLanguage(codec.getName());
msg.setOntology(ontology.getName());
try {
getContentManager().fillContent(MSG, new Action(JMS-Agent Gateway, action));
msg.addReceiver(JMS-Agent Gateway);
send(MSG);
} catch (Exception e) {
System.out.println("Error sending message:" + e.toString());
}
}
|
Subscribing to a Destination
- Create a Subscribe AgentAction.
- Set the ProviderInfo of the Action, specifying the destination type
(Util.QUEUE | Util.TOPIC), providers URL and the providers initial
context factory.
- Set the Subscription, specifying the destination and the subscriptions
durability (Util.DURABLE | Util.NON_DURABLE).
- Add a new JmsSubscriptionInitiator passing in the above subscription
message
- Notifications are sent to the handleInform(ACLMessage inform) method
of the Initiator. Notifications can be accessed by extracting a OnMessage
AgentAction from the inform message. The OnMessage Action contains
a JmsMessage.
- (Note: The message payload object is serialized and converted to a BASE64
string for transportation, the utility object contains methods to convert
serializeable objects to and from this encoding)
addBehaviour(new JmsSubscriptionInitiator(this, getSubscriptionMsg()));
/**
* Create a subscription message
*
* @return The subscriptionMsg value
*/
private ACLMessage getSubscriptionMsg() {
Subscribe sub = new Subscribe();
// Using a queue
connection with the openJMS provider
sub.setProviderInfo(Util.createProviderInfo(Util.QUEUE, "rmi://localhost:1099/", "org.exolab.jms.jndi.InitialContextFactory"));
// Create a subscription to the destination "pingAgent/ping"
sub.setSubscription(Util.createSubscription("pingAgent/ping", Util.NON_DURABLE));
ACLMessage MSG = new ACLMessage(ACLMessage.SUBSCRIBE);
msg.setLanguage(codec.getName());
msg.setOntology(ontology.getName());
try {
getContentManager().fillContent(MSG, new Action(JMS-Agent Gateway, sub));
msg.addReceiver(JMS-Agent Gateway);
} catch (Exception e) {
System.out.println("Error populating subscription message:" + e.toString());
e.printStackTrace();
}
return MSG;
}
/**
* Implementation of the SubscriptionInitiator interface
*
* @author Edward Curry
* @version 0.5 12 January 2004
*/
class JmsSubscriptionInitiator extends SubscriptionInitiator {
private int counter = 0;
Agent agent;
/**
* Constructor for the JmsSubscriptionInitiator object
*
* @param a Agent involved in this interaction
* @param MSG Subscription message to send
*/
JmsSubscriptionInitiator(Agent a, ACLMessage MSG) {
super(a, msg);
agent = a;
}
/**
* Method called when a Agree message is received
*
* @param agree Agree message received
*/
protected void handleAgree(ACLMessage agree) {
System.out.println("Handle Agree");
}
/**
* Method called when a Refuse message is received
*
* @param refuse Refuse message received
*/
protected void handleRefuse(ACLMessage refuse) {
System.out.println("Handle Refuse");
}
/**
* Method called when a NotUnderstood message is recceived
*
* @param notUnderstood NotUnderstood message received
*/
protected void handleNotUnderstood(ACLMessage notUnderstood) {
System.out.println("Handle not understood");
}
/**
* Method called when a Inform message is received
*
* @param inform Inform message received
*/
protected void handleInform(ACLMessage inform) {
System.out.println("Handle Inform");
try {
ContentElement content = getContentManager().extractContent(inform);
OnMessage om = (OnMessage) ((Action) content).getAction();
JmsMessage jmsMsg = om.getMessage();
counter++;
System.out.println("Message Received: Payload:" + ((String) Util.convertStringToObject(jmsMsg.getPayload())));
// Send pong message
publishPong("Pong" + counter);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Method called when a Failure message is received
*
* @param failure Failure message received
*/
protected void handleFailure(ACLMessage failure) {
System.out.println("Handle Failure");
}
}
|
Description of JMS-Agent Gateway Example
Name: Client Agent - ie.nuigalway.ecrg.jade.jmsagentgateway.examples.ClientAgent
Purpose: Demonstrates the sending and receiving of messages from a JADE
--> JMS --> JADE interaction.
Description: This JADE Agent listens to a destination and then sends
a defined (default 10) number of messages to that destination.
Name: Ping Agent - ie.nuigalway.ecrg.jade.jmsagentgateway.examples.PingAgent
Purpose: Demonstrates a JADE Agent interacting with a Queue and Topic.
Description: This agent listens a queue "pingAgent/ping" and
replies to any "ping" messages by publishing a message to the "pingAgent/pong"
topic. To run this example you must setup the"pingAgent/ping" queue
and the "pingAgent/pong" topic.
Name: Ping Client - ie.nuigalway.ecrg.jade.jmsagentgateway.examples.PingClient
Purpose: Illustrates how a regular Java object can interact with a JADE
agent using the JMS-Agent Gateway.
Description: This regular Java class sends a ping to the "pingAgent/ping"
queue and listens to the "pingAgent/pong" topic for a response. To
run this example you must setup the"pingAgent/ping" queue and the
"pingAgent/pong" topic.
Configuration File
The JMS-Agent Gateway is configurable by altering its jmsagentgateway.properties file.
From this file it is possible to enable the Agents GUI, set the Agents Type
and the Agents Owner.
jmsagentgateway.properties
### JMS-Agent GatewayConfiguration
#############################################
### Default Settings
############################
ie.nuigalway.ecrg.jade.jmsagentgateway.gui=false
ie.nuigalway.ecrg.jade.jmsagentgateway.agentType=JmsProxyAgent
ie.nuigalway.ecrg.jade.jmsagentgateway.agentOwner=ecrg.it.nuigalway.ie
Known Issues
- The current release of the JMS-Agent Gateway only supports JMS messages in
the form of TextMessage and ObjectMessage.
- Only string message properties are supported.
JADE is a
trademark of CSELT.
SonicMQ is a trademark
of Sonic Software.
JBoss and
JBoss Group are a registered trademark and servicemark of Marc Fleury under
operation by The JBoss Group, LLC.
JADE has been developed jointly by CSELT and the Computer Engineering Group of the University of Parma.
The jmsagentgateway Agent was developed in the Enterprise Computing Research Group (ECRG)
at the National University of Ireland,
Galway by Edward Curry.
The support of the Informatics Research Initiative of Enterprise Ireland is gratefully
acknowledged.
Copyright 2002/2003/2004 Enterprise Computing Research Group.