245 lines
13 KiB
XML
245 lines
13 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="xmpp"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>XMPP Support</title>
|
|
<para>
|
|
Spring Integration provides Channel Adapters for <ulink url="http://www.xmpp.org">XMPP</ulink>.
|
|
</para>
|
|
<section id="xmpp-intro">
|
|
<title>Introduction</title>
|
|
<para>
|
|
XMPP describes a way for multiple agents to communicate with each other in a distributed system.
|
|
The canonical use case is to send and receive chat messages, though XMPP can be, and is, used for far more
|
|
applications.
|
|
XMPP is used to describe a network of actors. Within that network, actors may address each other directly, as well
|
|
as broadcast status changes (e.g. "presence").
|
|
</para>
|
|
<para>
|
|
XMPP provides the messaging fabric that underlies some of the biggest Instant Messaging networks in the world,
|
|
including Google Talk (GTalk) - which is also available from within GMail - and Facebook Chat.
|
|
There are many good open-source XMPP servers available. Two popular implementations are
|
|
<ulink url="http://www.igniterealtime.org/projects/openfire/">
|
|
<citetitle>Openfire</citetitle>
|
|
</ulink>
|
|
and
|
|
<ulink url="http://www.ejabberd.im">
|
|
<citetitle>ejabberd</citetitle>
|
|
</ulink>
|
|
</para>
|
|
<para>
|
|
Spring integration provides support for XMPP via XMPP adapters which support sending and receiving both XMPP chat messages and
|
|
presence changes from other entries in your roster. As many other adapters, XMPP adapters come with a convenient namespace-based
|
|
configuration.
|
|
To configure XMPP namespace include the following elements into the headers of your XML configuration file:
|
|
|
|
<programlisting language="xml"><![CDATA[xmlns:xmpp="http://www.springframework.org/schema/integration/xmpp"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/integration/xmpp
|
|
http://www.springframework.org/schema/integration/xmpp/spring-integration-xmpp-2.0.xsd"]]></programlisting>
|
|
|
|
</para>
|
|
</section>
|
|
|
|
<section id="xmpp-connection">
|
|
<title>XMPP Connection</title>
|
|
<para>
|
|
Before using inbound or outbound XMPP adapters to participate in the XMPP network actor must establish XMPP connection. This
|
|
connection object could be shared by all XMPP adapters connected to a particular account. Typically this requires - at a minimum -
|
|
<code>user</code>, <code>password</code>, <code>host</code>.
|
|
|
|
To create a basic XMPP connection, you can utilize the convenience of the namespace.
|
|
|
|
<programlisting lang="xml"><![CDATA[<xmpp:xmpp-connection
|
|
id="myConnection"
|
|
user="user"
|
|
password="password"
|
|
host="host"
|
|
port="port"
|
|
resource="theNameOfTheResource"
|
|
subscription-mode="accept_all"/>
|
|
]]></programlisting>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="xmpp-messages">
|
|
<title>XMPP Messages</title>
|
|
<section id="xmpp-message-inbound-channel-adapter">
|
|
<title>Inbound Message Channel Adapter</title>
|
|
<para>The Spring Integration adapters support receiving chat messages from other users in the system. To do this, the
|
|
<emphasis>Inbound Message Channel Adapter</emphasis> "logs in" as a user on your behalf and receives the messages sent to that user. Those messages are then
|
|
forwarded to your Spring Integration client.
|
|
The payload of the inbound Spring Integration message may be of the raw type<classname>
|
|
org.jivesoftware.smack.packet.Message</classname>, or of the type
|
|
<classname>java.lang.String</classname> if you set <code>extract-payload</code> value attribute to 'true'
|
|
when configuring an adapter.
|
|
Configuration support for the XMPP <emphasis>Inbound Message Channel Adapter</emphasis> is provided via the <code>inbound-channel-adapter</code> element.
|
|
|
|
<programlisting language="xml"><![CDATA[<xmpp:inbound-channel-adapter id="xmppInboundAdapter"
|
|
channel="xmppInbound"
|
|
xmpp-connection="testConnection"
|
|
extract-payload="false"
|
|
auto-startup="true"/>]]></programlisting>
|
|
|
|
As you can see amongst the usual attributes this adapter also requires a reference to an XMPP Connection.
|
|
</para>
|
|
<para>
|
|
It is also important to mention that XMPP inbound adapter is an <emphasis>event driven adapter</emphasis> and a <classname>LifeCycle</classname> object.
|
|
When started it will register a <classname>PacketListener</classname> that will listen for the incoming XMPP Messages. It forwards those messages
|
|
to the underlying adapter which will convert them to Spring Integration Messages and send them to the <classname>channel</classname>. It will
|
|
unregister the <classname>PacketListener</classname> when it is stopped.
|
|
</para>
|
|
</section>
|
|
|
|
|
|
<section id="xmpp-message-outbound-channel-adapter">
|
|
<title>Outbound Message Channel Adapter</title>
|
|
|
|
<para>
|
|
You may also send chat messages to other users on XMPP using the <emphasis>Outbound Message Channel Adapter</emphasis>.
|
|
Configuration support for the XMPP <emphasis>Outbound Message Channel Adapter</emphasis> is provided via the <code>outbound-channel-adapter</code> element.
|
|
|
|
<programlisting language="xml"><![CDATA[<int-xmpp:outbound-channel-adapter id="outboundEventAdapter"
|
|
channel="outboundEventChannel"
|
|
xmpp-connection="testConnection"/>]]></programlisting>
|
|
|
|
The adapter expects as its input - at a minimum - a payload of type <classname>java.lang.String</classname>, and a header value
|
|
for <classname>XmppHeaders.CHAT_TO</classname> that specifies to which user the Message should be sent to. To
|
|
create a message you might use the following Java code:
|
|
|
|
<programlisting language="java"><![CDATA[Message<String> xmppOutboundMsg = MessageBuilder.withPayload("Hello, XMPP!" )
|
|
.setHeader(XmppHeaders.CHAT_TO, "userhandle")
|
|
.build();]]></programlisting>
|
|
|
|
Another mechanism of setting such header is by using the XMPP enricher support. Here is an example using the enricher.
|
|
|
|
<programlisting language="xml"><![CDATA[<int-xmpp:header-enricher input-channel="input" output-channel="output">
|
|
<int-xmpp:chat-to value="test1@example.org"/>
|
|
</int-xmpp:header-enricher>]]></programlisting>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
|
|
<section id="xmpp-presence">
|
|
<title>XMPP Presence</title>
|
|
|
|
<para>
|
|
|
|
XMPP also supports broadcasting state. You can use this capability to
|
|
let people who have you on their roster see your state changes. This happens all the time with your IM clients - you
|
|
change your away status, and then set an away message, and everybody who has you on their roster sees your icon or username change to reflect this new state, and
|
|
additionally might see your new "away" message.
|
|
|
|
|
|
If you would like to receive notification, or notify others, of state changes, you can use Spring Integration's "presence" adapters.
|
|
|
|
</para>
|
|
|
|
<section id="xmpp-roster-inbound-channel-adapter">
|
|
<title>Inbound Presence Message Channel Adapter</title>
|
|
<para>
|
|
Spring Integration provides an <emphasis>Inbound Presence Message Channel Adapter</emphasis> which supports receiving Presence (Roster)
|
|
events from other users in the system. To do this, the adapter "logs in" as a user
|
|
on your behalf, registers a <classname>RosterListener</classname> and forwards received Presence update events as Messages to the channel
|
|
identified by the <code>channel</code> attribute. The payload of the Message will be a <classname>org.jivesoftware.smack.packet.Presence</classname>
|
|
object (see http://www.igniterealtime.org/builds/smack/docs/3.1.0/javadoc/org/jivesoftware/smack/packet/Presence.html).
|
|
</para>
|
|
<para>
|
|
Configuration support for the XMPP <emphasis>Inbound Presence Message Channel Adapter</emphasis> is provided via
|
|
the <code>presence-inbound-channel-adapter</code> element.
|
|
<programlisting language="xml"><![CDATA[<int-xmpp:presence-inbound-channel-adapter channel="outChannel"
|
|
xmpp-connection="testConnection" auto-startup="false"/>]]></programlisting>
|
|
|
|
As you can see amongst the usual attributes this adapter also requires a reference to an XMPP Connection.
|
|
It is also important to mention that this adapter is an event driven adapter and a <classname>LifeCycle</classname> object.
|
|
It will register <classname>RosterListener</classname> when started and will unregister <classname>RosterListener</classname>
|
|
when stopped.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="xmpp-roster-outbound-channel-adapter">
|
|
<title>Outbound Presence Message Channel Adapter</title>
|
|
|
|
<para>
|
|
Spring Integration also supports sending Presence (Roster) events to be seen by other users in the network. When you send a Message
|
|
to the <emphasis>Outbound Presence Message Channel Adapter</emphasis> it extracts the payload which is expected to be of
|
|
type <classname>org.jivesoftware.smack.packet.Presence</classname>
|
|
(see http://www.igniterealtime.org/builds/smack/docs/3.1.0/javadoc/org/jivesoftware/smack/packet/Presence.html) and sends it to
|
|
the XMPP Connection, thus advertising your presence events to the rest of the network.
|
|
</para>
|
|
<para>
|
|
Configuration support for the XMPP <emphasis>Outbound Presence Message Channel Adapter</emphasis> is provided via
|
|
the <code>presence-outbound-channel-adapter</code> element.
|
|
|
|
<programlisting language="xml"><![CDATA[<int-xmpp:presence-outbound-channel-adapter id="eventOutboundPresenceChannel"
|
|
xmpp-connection="testConnection"/>]]></programlisting>
|
|
|
|
It can also be a <emphasis>polling consumer</emphasis> (if it receives Messages from the Polling Channel) in which case you would
|
|
need to register a Poller.
|
|
|
|
<programlisting language="xml"><![CDATA[<int-xmpp:presence-outbound-channel-adapter id="pollingOutboundPresenceAdapter"
|
|
xmpp-connection="testConnection"
|
|
channel="pollingChannel">
|
|
<int:poller fixed-rate="1000" max-messages-per-poll="1"/>
|
|
</int-xmpp:presence-outbound-channel-adapter>]]></programlisting>
|
|
|
|
Similar to its Inbound counterpart it requires a reference to an XMPP Connection.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="xmpp-appendices">
|
|
<title>Appendices</title>
|
|
|
|
<para>
|
|
Since Spring Integration XMPP support is based on Smack 3.1 API (http://www.igniterealtime.org/downloads/index.jsp), it is important
|
|
to know a few details related to more complex configuration of XMPP Connection object.
|
|
</para>
|
|
<para>
|
|
As it was said earlier the <code>xmpp-connection</code> namespace support is designed to simplify basic connection configuration and
|
|
only supports few configuration attributes. However, <classname>org.jivesoftware.smack.ConnectionConfiguration</classname> object defines about 20
|
|
attributes, and there is no real value of adding namespace support for all of them. So, for more complex connection configurations,
|
|
simply configure <classname>XmppConnectionFactoryBean</classname> as a regular bean injecting
|
|
<classname>org.jivesoftware.smack.ConnectionConfiguration</classname> as a constructor argument and configuring every property
|
|
you may need. This way SSL or any other attributes could be set directly in a consistent Spring way. Example:
|
|
|
|
<programlisting language="xml"><![CDATA[<bean id="xmppConnection" class="org.springframework.integration.xmpp.XmppConnectionFactoryBean">
|
|
<constructor-arg>
|
|
<bean class="org.jivesoftware.smack.ConnectionConfiguration">
|
|
<constructor-arg value="myServiceName"/>
|
|
<property name="truststorePath" value="..."/>
|
|
<property name="socketFactory" ref="..."/>
|
|
</bean>
|
|
</constructor-arg>
|
|
</bean>
|
|
<int:channel id="outboundEventChannel"/>
|
|
|
|
<int-xmpp:outbound-channel-adapter id="outboundEventAdapter"
|
|
channel="outboundEventChannel"
|
|
xmpp-connection="xmppConnection"/>]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Another important aspect of Smack API is static initializers. For more complex cases (e.g., registering SASL Mechanism) you may need
|
|
to execute certain static initializers. One of those static initializers is <classname>SASLAuthentication</classname> which allows
|
|
you to register supported SASL mechanisms. For that level of complexity we would recommend Spring Javaconfig-style of XMPP Connection
|
|
configuration where you can configure the entire component through Java code and execute all other necessary Java code including
|
|
static initializers.
|
|
|
|
<programlisting language="java"><![CDATA[@Configuration
|
|
public class CustomConnectionConfiguration {
|
|
@Bean
|
|
public XmppConnection knight() {
|
|
SASLAuthentication.supportSASLMechanism("EXTERNAL", 0); // static initializer
|
|
|
|
ConnectionConfiguration config = new ConnectionConfiguration("localhost", 5223);
|
|
config.setTrustorePath("path_to_truststore.jks");
|
|
config.setSecurityEnabled(true);
|
|
config.setSocketFactory(SSLSocketFactory.getDefault());
|
|
conn = new XMPPConnection(config);
|
|
}
|
|
}]]></programlisting>
|
|
For more information on Javaconfig style of Application Context configuration refere to the following section in Spring Reference Manual
|
|
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|