The other week someone in jdev was asking about writing transports in Java and I've been meaning to write up some example code here, the
Jabber/XMPP transport code was written using the
Marbles framework. The
SMS code ( which seems to generate more interest than the XMPP side of things ) simply uses $EMPLOYER's SOAP gateway, this means that theres actually very little code in the transport itself - its pretty much just glue.
At the heard of a Marbles based transport is the ComponentConnection class and ComponentConnectionEventListener interface, when your application starts you connect to a jabber server by connecting to the server and attaching our listener:
ComponentConnectionInfo connect_info = new ComponentConnectionInfo(
APPLICATION_NAME,
"localhost", // Hostname of Jabber Server
"secret", // Secret/password to connect to server
"jabber:component:" + APPLICATION_NAME,
8002, // Port to connect to
true);
ComponentConnection connection = new ComponentConnection(new MyTransportHandler(), connect_info);
The MyTransportHandler class implements a somewhat basic interface that simply routes DOM Elements:
public interface ComponentConnectionEventListener {
void onActive();
void onConfig(Element element);
void onPacket(Element element);
}
A simple implementation of onPacket() to print incoming messages to the console works as follows:
public void onPacket(Element element) {
// We're very simple here, we only handle messages, not chats
if ( element.getNodeName().equals("message") ) {
// We're also only interested in non-error messages
if (element.getAttribute("type") == null || (!element.getAttribute("type").equals("error"))) {
try {
String from = element.getAttribute("from");
String to = element.getAttribute("to");
// Loop children of the message and look for the body
NodeList childList = element.getChildNodes();
String body = "";
for ( int i = 0; i < childList.getLength(); i++ ) {
Node node = childList.item(i);
if ( node.getNodeName().equals("body")) {
body = node.getChildNodes().item(0).getNodeValue();
}
}
System.out.println("Jabber message from " + from + " to " + to + ": " + body);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
So the code doesn't do much, but once you've got XMPP messages coming into your code, you're free to bounce it into what ever other layer you want to implement, in the case of using $EMPLOYERS SMS gateway, all I did was:
// Find SMS Gateway WebService
BulletinServerProxy proxy = BulletinServerProxyLocator.getBulletinServerProxy();
BulletinMessage message = getMessageFromElement(element);
proxy.send(BulletinConnectComponent.APPLICATION_NAME, 1, message );
// Store message in database
recordMessageHistory(from, message);
Now that we have this funky java based XMPP transport running we need a Jabber server to connect to, under jabberd 1.4 two entries in jabber.xml are required, the first inside the sessions service element:
<service type="sms" jid="sms.yourhost" name="Some Descriptive name">
<ns>jabber:iq:gateway</ns>
<ns>jabber:iq:register</ns>
</service>
and the second in its own <service> element:
<service id="bcjab">
<host>sms.yourhost</host>
<accept>
<ip>127.0.0.1</ip>
<port>8002</port>
<secret>secret</secret>
</accept>
</service>
Simply match up the
APPLICATION_NAME to the service id, ip, port, and secret with the ComponentConnectionInfo in the transport and you're away laughing, or at least away debugging.
links: digg this del.icio.us technorati reddit