martes, abril 29, 2008

... and all he captures is endless rain.


At last entry i wrote about developing a Taget Adapter for SpringIntegration Module. In thi sentry i will talk about developing a SourceAdapter.
As my last entry, Jabber server will be used, and Smack API for connecting and receiving messages.
From previous entry server configuration, and some classes will be used, so strictly, only SourceAdapter and its configuration are going to be explain.
Firstly, but, a little explanation about two possible kind of communication for source adapters:
  • Poll: which means that every period of time the program are checking if new content is available. For example FTP Source Adapter is an example because ftp server doesn't throw an interruption when another user upload a file.
  • Driven-Event: which means that an asynchronous event is thrown and can be captured. Our IM Adapter is an example.

Each SourceAdapter must implements SourceAdapter interface. But as TargetAdapter, there are some classes that help developers in writting an Adapter. At least two classes are provided for developing a SourceAdapter that, of course, implements SourceAdapter interface:
  • AbstractSourceAdapter: A base class providing common behavior for source adapters. It has some methods for sending messages to a channel, set message mappers, ...
  • PollingSourceAdapter: A base class for polling if new message is available to be sent. It has some methods like period between polls, initial delay, ...

Our case requires extending AbstractSourceAdapter.
IMSourceAdapter extends AbstractSourceAdapter implements
InitializingBean

IMMessage is a class that represents a message sent through channel. IMMessage is a self developed class and its explanation can be found on previous post.
Because of event communication, Smack API requires that you subscribe to an event implementing an interface, so each time an event occurs, that interface is executed. This initialization is developed in initialize() Spring method and next piece of code is the business logic.


final XMPPConnection connection = new XMPPConnection(this.server); (1)
try {
connection.connect();
connection.login(this.user, this.password);
} catch (final XMPPException e) {
throw new MessageHandlingException("Error starting", e);
}

final PacketFilter packetFilter = new MessageTypeFilter(
Message.Type.chat);
connection.createPacketCollector(packetFilter); (2)

final PacketListener packetListener = new PacketListener() { (3)

@Override
public void processPacket(Packet arg0) {
String msn = ((Message) arg0).getBody(); (4)
SimpleIMMessage simpleIMMessage = new SimpleIMMessage();
simpleIMMessage.setText(msn); (5)
IMSourceAdapter.this.sendToChannel(simpleIMMessage); (6)
}
};
connection.addPacketListener(packetListener, packetFilter); (7)

(1) Uses Smack XMPPConnection for connecting to server.
(2) Creats a filter for throwing only events when a new chat message is received.
(3) Creats the business logic that must be executed each time a message is received.
(4) Gets the body of the message. (What the other user has written).
(5) Creats an IMMessage for sending through channel.
(6) Send the message through MessageChannel.
(7) Register the event.
As can be seen, the only important call is sendToChannel that sends the message to spring integration structure, the other logic may vary depending on source adapter that are going to be developed.
XML configuration file is so easy:
<?xml version="1.0" encoding="UTF-8"?>
<
beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

<message-bus />
<annotation-driven />

<channel id="inMessage"></channel>
<beans:bean id="sourceIM" class="test.spring.integration.im.IMSourceAdapter">
<beans:property name="user" value="logger">
</beans:property>
<beans:property name="password" value="logger">
</beans:property>
<beans:property name="server" value="localhost">
</beans:property>
<beans:property name="channel" ref="inMessage">
</beans:property>
<beans:property name="messageMapper">
<beans:bean class="test.spring.integration.im.TextIMMessageMapper">
</beans:bean>
</beans:property>
</beans:bean>

<file-target directory="/temp" channel="inMessage"/>
</beans:beans>

For running the example, start the Jabber Server (OpenFire), start a client Spark, and talk to logger user. Each message will be saved one file.
SpringIntegration 1.0M3 has been used for developing the TargetAdapter.


3 comentarios:

iwein dijo...

Would you be interested in helping out to get an xmpp adapter into the Spring Integration Adapters project?

http://www.springsource.org/extensions/se-sia you can create a feature request there and contribute if you like.

Anónimo dijo...
Este comentario ha sido eliminado por un administrador del blog.
Anónimo dijo...
Este comentario ha sido eliminado por un administrador del blog.