[[xmpp]]
= XMPP Support

Spring Integration provides channel adapters for https://www.xmpp.org[XMPP].
XMPP stands for "`Extensible Messaging and Presence Protocol`".

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 other kinds of applications.
XMPP describes a network of actors.
Within that network, actors may address each other directly and broadcast status changes (such as "`presence`").

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.
Many good open-source XMPP servers are available.
Two popular implementations are https://www.igniterealtime.org/projects/openfire/[Openfire] and https://www.ejabberd.im[ejabberd].

Spring integration provides support for XMPP by providing XMPP adapters, which support sending and receiving both XMPP chat messages and presence changes from other entries in a client's roster.

You need to include this dependency into your project:

[tabs]
======
Maven::
+
[source, xml, subs="normal", role="primary"]
----
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-xmpp</artifactId>
    <version>{project-version}</version>
</dependency>
----

Gradle::
+
[source, groovy, subs="normal", role="secondary"]
----
compile "org.springframework.integration:spring-integration-xmpp:{project-version}"
----
======

As with other adapters, the XMPP adapters come with support for a convenient namespace-based configuration.
To configure the XMPP namespace, include the following elements in the headers of your XML configuration file:

[source,xml]
----
xmlns:int-xmpp="http://www.springframework.org/schema/integration/xmpp"
xsi:schemaLocation="http://www.springframework.org/schema/integration/xmpp
	https://www.springframework.org/schema/integration/xmpp/spring-integration-xmpp.xsd"
----

[[xmpp-connection]]
== XMPP Connection

Before using inbound or outbound XMPP adapters to participate in the XMPP network, an actor must establish its XMPP connection.
All XMPP adapters connected to a particular account can share this connection object.
Typically, this requires (at a minimum) `user`, `password`, and `host`.
To create a basic XMPP connection, you can use the convenience of the namespace, as the following example shows:

[source,xml]
----
<int-xmpp:xmpp-connection
    id="myConnection"
    user="user"
    password="password"
    host="host"
    port="port"
    resource="theNameOfTheResource"
    subscription-mode="accept_all"/>
----

NOTE: For added convenience, you can rely on the default naming convention and omit the `id` attribute.
The default name (`xmppConnection`) is used for this connection bean.

If the XMPP connection goes stale, reconnection attempts are made with an automatic login as long as the previous connection state was logged (authenticated).
We also register a `ConnectionListener`, which logs connection events if the `DEBUG` logging level is enabled.

The `subscription-mode` attribute initiates the roster listener to deal with incoming subscriptions from other users.
This functionality is not always available for the target XMPP servers.
For example, Google Cloud Messaging (GCM) and Firebase Cloud Messaging (FCM) fully disable it.
To switch off the roster listener for subscriptions, you can configure it with an empty string when using XML configuration (`subscription-mode=""`) or with `XmppConnectionFactoryBean.setSubscriptionMode(null)` when using Java Configuration.
Doing so disables the roster at the login phase as well.
See https://download.igniterealtime.org/smack/docs/latest/javadoc/org/jivesoftware/smack/roster/Roster.html#setRosterLoadedAtLogin-boolean-[`Roster.setRosterLoadedAtLogin(boolean)`] for more information.

[[xmpp-messages]]
== XMPP Messages

Spring Integration provides support for sending and receiving XMPP messages.
For receiving them, it offers an inbound message channel adapter.
For sending them, it offers an outbound message channel adapter.

[[xmpp-message-inbound-channel-adapter]]
=== Inbound Message Channel Adapter

The Spring Integration adapters support receiving chat messages from other users in the system.
To do so, the inbound message channel adapter "`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 `inbound-channel-adapter` element provides Configuration support for the XMPP inbound message channel adapter.
The following example shows how to configure it:

[source,xml]
----
<int-xmpp:inbound-channel-adapter id="xmppInboundAdapter"
	channel="xmppInbound"
	xmpp-connection="testConnection"
	payload-expression="getExtension('google:mobile:data').json"
	stanza-filter="stanzaFilter"
	auto-startup="true"/>
----

Along with the usual attributes (for a message channel adapter), this adapter also requires a reference to an XMPP Connection.

The XMPP inbound adapter is event-driven and a `Lifecycle` implementation.
When started, it registers a `PacketListener` that listens for incoming XMPP chat messages.
It forwards any received messages to the underlying adapter, which converts them to Spring Integration messages and sends them to the specified `channel`.
When stopped, it unregisters the `PacketListener`.

Starting with version 4.3, the `ChatMessageListeningEndpoint` (and its `<int-xmpp:inbound-channel-adapter>`) supports the injection of a `org.jivesoftware.smack.filter.StanzaFilter` to be registered on the provided `XMPPConnection`, together with an internal `StanzaListener` implementation.
See the https://www.igniterealtime.org/builds/smack/docs/latest/javadoc/org/jivesoftware/smack/XMPPConnection.html#addAsyncStanzaListener%28org.jivesoftware.smack.StanzaListener,%20org.jivesoftware.smack.filter.StanzaFilter%29[Javadoc] for more information.

Version 4.3 introduced the `payload-expression` attribute for the `ChatMessageListeningEndpoint`.
The incoming `org.jivesoftware.smack.packet.Message` represents a root object for the evaluation context.
This option is useful when you use xref:xmpp.adoc#xmpp-extensions[XMPP extensions].
For example, for the GCM protocol we can extract the body by using the following expression:

[source,xml]
----
payload-expression="getExtension('google:mobile:data').json"
----

The following example extracts the body for the XHTML protocol:

[source,xml]
----
payload-expression="getExtension(T(org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension).NAMESPACE).bodies[0]"
----

To simplify access to the extension in the XMPP Message, the `extension` variable is added into the `EvaluationContext`.
Note that it is added when only one extension is present in the message.
The preceding examples that show the `namespace` manipulations can be simplified to the following example:

[source,xml]
----
payload-expression="#extension.json"
payload-expression="#extension.bodies[0]"
----

[[xmpp-message-outbound-channel-adapter]]
=== Outbound Message Channel Adapter

You can also send chat messages to other users on XMPP by using the outbound message channel adapter.
The `outbound-channel-adapter` element provides configuration support for the XMPP outbound message channel adapter.

[source,xml]
----
<int-xmpp:outbound-channel-adapter id="outboundEventAdapter"
						channel="outboundEventChannel"
						xmpp-connection="testConnection"/>
----

The adapter expects its input to be (at a minimum) a payload of type `java.lang.String` and a header value for `XmppHeaders.CHAT_TO` that specifies to which user the message should be sent.
To create a message, you can use Java code similar to the following:

[source,java]
----
Message<String> xmppOutboundMsg = MessageBuilder.withPayload("Hello, XMPP!" )
						.setHeader(XmppHeaders.CHAT_TO, "userhandle")
						.build();
----

You can also set the header by using the XMPP header-enricher support, as the following example shows:

[source,xml]
----
<int-xmpp:header-enricher input-channel="input" output-channel="output">
	<int-xmpp:chat-to value="test1@example.org"/>
</int-xmpp:header-enricher>
----

Starting with version 4.3, the packet extension support has been added to the `ChatMessageSendingMessageHandler` (the `<int-xmpp:outbound-channel-adapter>` in XML configuration).
Along with the regular `String` and `org.jivesoftware.smack.packet.Message` payload, now you can send a message with a payload of `org.jivesoftware.smack.packet.XmlElement` (which is populated to the `org.jivesoftware.smack.packet.Message.addExtension()`) instead of `setBody()`.
For convenience, we added an `extension-provider` option for the `ChatMessageSendingMessageHandler`.
It lets you inject `org.jivesoftware.smack.provider.ExtensionElementProvider`, which builds an `XmlElement` against the payload at runtime.
For this case, the payload must be a string in JSON or XML format, depending on the XEP protocol.

[[xmpp-presence]]
== XMPP Presence

XMPP also supports broadcasting state.
You can use this ability 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 set an away message, and everybody who has you on their roster sees your icon or username change to reflect this new state and might see your new "`away`" message.
If you would like to receive notifications or notify others of state changes, you can use Spring Integration's "`presence`" adapters.

[[xmpp-roster-inbound-channel-adapter]]
=== Inbound Presence Message Channel Adapter

Spring Integration provides an inbound presence message channel adapter, which supports receiving presence events from other users in the system who are on your roster.
To do this, the adapter "`logs in`" as a user on your behalf, registers a `RosterListener`, and forwards received presence update events as messages to the channel identified by the `channel` attribute.
The payload of the message is a `org.jivesoftware.smack.packet.Presence` object (see https://www.igniterealtime.org/builds/smack/docs/latest/javadoc/org/jivesoftware/smack/packet/Presence.html).

The `presence-inbound-channel-adapter` element provides configuration support for the XMPP inbound presence message channel adapter.
The following example configures an inbound presence message channel adapter:

[source,xml]
----
<int-xmpp:presence-inbound-channel-adapter channel="outChannel"
		xmpp-connection="testConnection" auto-startup="false"/>
----

Along with the usual attributes, this adapter requires a reference to an XMPP Connection.
This adapter is event-driven and a `Lifecycle` implementation.
It registers a `RosterListener` when started and unregisters that `RosterListener` when stopped.

[[xmpp-roster-outbound-channel-adapter]]
=== Outbound Presence Message Channel Adapter

Spring Integration also supports sending presence events to be seen by other users in the network who happen to have you on their roster.
When you send a message to the outbound presence message channel adapter, it extracts the payload (which is expected to be of type `org.jivesoftware.smack.packet.Presence`) and sends it to the XMPP Connection, thus advertising your presence events to the rest of the network.

The `presence-outbound-channel-adapter` element provides configuration support for the XMPP outbound presence message channel adapter.
The following example shows how to configure an outbound presence message channel adapter:

[source,xml]
----
<int-xmpp:presence-outbound-channel-adapter id="eventOutboundPresenceChannel"
	xmpp-connection="testConnection"/>
----

It can also be a polling consumer (if it receives messages from a pollable channel) in which case you would need to register a poller.
The following example shows how to do so:

[source,xml]
----
<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>
----

Like its inbound counterpart, it requires a reference to an XMPP Connection.

NOTE: If you rely on the default naming convention for an XMPP Connection bean (xref:xmpp.adoc#xmpp-connection[described earlier]) and you have only one XMPP Connection bean configured in your application context, you can omit the `xmpp-connection` attribute.
In that case, the bean with named `xmppConnection` is located and injected into the adapter.

[[xmpp-advanced]]
== Advanced Configuration

Spring Integration's XMPP support is based on the Smack 4.0 API (https://www.igniterealtime.org/projects/smack/), which allows more complex configuration of the XMPP Connection object.

As xref:xmpp.adoc#xmpp-connection[stated earlier], the `xmpp-connection` namespace support is designed to simplify basic connection configuration and supports only a few common configuration attributes.
However, the `org.jivesoftware.smack.ConnectionConfiguration` object defines about 20 attributes, and adding namespace support for all of them offers no real value.
So, for more complex connection configurations, you can configure an instance of our `XmppConnectionFactoryBean` as a regular bean and inject a `org.jivesoftware.smack.ConnectionConfiguration` as a constructor argument to that `FactoryBean`.
You can specify every property you need directly on that `ConnectionConfiguration` instance.
(A bean definition with the 'p' namespace would work well.)
This way, you can directly set SSL (or any other attributes).
The following example shows how to do so:

[source,xml]
----
<bean id="xmppConnection" class="o.s.i.xmpp.XmppConnectionFactoryBean">
    <constructor-arg>
        <bean class="org.jivesoftware.smack.ConnectionConfiguration">
            <constructor-arg value="myServiceName"/>
            <property name="socketFactory" ref="..."/>
        </bean>
    </constructor-arg>
</bean>

<int:channel id="outboundEventChannel"/>

<int-xmpp:outbound-channel-adapter id="outboundEventAdapter"
    channel="outboundEventChannel"
    xmpp-connection="xmppConnection"/>
----

The Smack API also offers static initializers, which can be helpful.
For more complex cases (such as registering a SASL mechanism), you may need to execute certain static initializers.
One of those static initializers is `SASLAuthentication`, which lets you register supported SASL mechanisms.
For that level of complexity, we recommend using Spring Java configuration for the XMPP connection configuration.
That way, you can configure the entire component through Java code and execute all other necessary Java code, including static initializers, at the appropriate time.
The following example shows how to configure an XMPP connection with an SASL (Simple Authentication and Security Layer) in Java:

[source,java]
----
@Configuration
public class CustomConnectionConfiguration {
  @Bean
  public XMPPConnection xmppConnection() {
	SASLAuthentication.supportSASLMechanism("EXTERNAL", 0); // static initializer

	ConnectionConfiguration config = new ConnectionConfiguration("localhost", 5223);
	config.setKeystorePath("path_to_truststore.jks");
	config.setSecurityEnabled(true);
	config.setSocketFactory(SSLSocketFactory.getDefault());
	return new XMPPConnection(config);
  }
}
----

For more information on using Java for application context configuration, see the following section in the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java[Spring Reference Manual].

[[xmpp-message-headers]]
== XMPP Message Headers

The Spring Integration XMPP Adapters automatically map standard XMPP properties.
By default, these properties are copied to and from Spring Integration `MessageHeaders` by using https://docs.spring.io/spring-integration/api/org/springframework/integration/xmpp/support/DefaultXmppHeaderMapper.html[`DefaultXmppHeaderMapper`].

Any user-defined headers are not copied to or from an XMPP Message, unless explicitly specified by the `requestHeaderNames` or `replyHeaderNames` properties of the `DefaultXmppHeaderMapper`.

TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (such "thing*" or "*thing").

Starting with version 4.1, `AbstractHeaderMapper` (a superclass of `DefaultXmppHeaderMapper`) lets you configure the `NON_STANDARD_HEADERS` token for the `requestHeaderNames` property (in addition to `STANDARD_REQUEST_HEADERS`), to map all user-defined headers.

The `org.springframework.xmpp.XmppHeaders` class identifies the default headers to be used by the `DefaultXmppHeaderMapper`:

* `xmpp_from`
* `xmpp_subject`
* `xmpp_thread`
* `xmpp_to`
* `xmpp_type`

Starting with version 4.3, you can negate patterns in the header mappings by preceding the pattern with `!`.
Negated patterns get priority, so a list such as `STANDARD_REQUEST_HEADERS,thing1,thing*,!thing2,!thing3,qux,!thing1` does not map `thing1`, `thing2`,or `thing3`.
That list does map the standard headers plus `thing4` and `qux`.

IMPORTANT: If you have a user-defined header that begins with `!` that you do wish to map, can escape it with `\` thus: `STANDARD_REQUEST_HEADERS,\!myBangHeader`.
In that example, the standard request headers and `!myBangHeader` are mapped.

[[xmpp-extensions]]
== XMPP Extensions

Extensions put the "`Extensible`" in the "`Extensible Messaging and Presence Protocol`".

XMPP is based around XML, a data format that supports a concept known as namespacing.
Through namespacing, you can add bits to XMPP that are not defined in the original specifications.
The XMPP specification deliberately describes only a set of core features:

* How a client connects to a server
* Encryption (SSL/TLS)
* Authentication
* How servers can communicate with each other to relay messages
* A few other basic building blocks

Once you have implemented this, you have an XMPP client and can send any kind of data you like.
However, you may need to do more than the basics.
For example, you might need to include formatting (bold, italic, and so on) in a message, which is not defined in the core XMPP specification.
Well, you can make up a way to do that, but, unless everyone else does it the same way you do, no other software can interpret it (they ignore namespaces they cannot understand).

To solve that problem, the XMPP Standards Foundation (XSF) publishes a series of extra documents, known as https://xmpp.org/extensions/xep-0001.html[XMPP Extension Protocols] (XEPs).
In general, each XEP describes a particular activity (from message formatting to file transfers, multi-user chats, and many more).
They also provide a standard format for everyone to use for that activity.

The Smack API provides many XEP implementations with its `extensions` and `experimental` https://www.igniterealtime.org/builds/smack/docs/latest/documentation/extensions/index.html[projects].
Starting with Spring Integration version 4.3, you can use any XEP with the existing XMPP channel adapters.

To be able to process XEPs or any other custom XMPP extensions, you must provide the Smack's `ProviderManager` pre-configuration.
You can do so with `static` Java code, as the following example shows:

[source,java]
----
ProviderManager.addIQProvider("element", "namespace", new MyIQProvider());
ProviderManager.addExtensionProvider("element", "namespace", new MyExtProvider());
----

You can also use a  `.providers` configuration file in the specific instance and access it with a JVM argument, as the following example shows:

[source,xml]
----
-Dsmack.provider.file=file:///c:/my/provider/mycustom.providers
----

The `mycustom.providers` file might be as follows:

[source,xml]
----
<?xml version="1.0"?>
<smackProviders>
<iqProvider>
    <elementName>query</elementName>
    <namespace>jabber:iq:time</namespace>
    <className>org.jivesoftware.smack.packet.Time</className>
</iqProvider>

<iqProvider>
    <elementName>query</elementName>
    <namespace>https://jabber.org/protocol/disco#items</namespace>
    <className>org.jivesoftware.smackx.provider.DiscoverItemsProvider</className>
</iqProvider>

<extensionProvider>
    <elementName>subscription</elementName>
    <namespace>https://jabber.org/protocol/pubsub</namespace>
    <className>org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider</className>
</extensionProvider>
</smackProviders>
----

For example, the most popular XMPP messaging extension is https://developers.google.com/cloud-messaging/[Google Cloud Messaging] (GCM).
The Smack library provides `org.jivesoftware.smackx.gcm.provider.GcmExtensionProvider` for that purposes.
By default, it registers that class with the `smack-experimental` jar in the classpath by using the `experimental.providers` resource, as the following Maven example shows:

[source,xml]
----
<!-- GCM JSON payload -->
<extensionProvider>
    <elementName>gcm</elementName>
    <namespace>google:mobile:data</namespace>
    <className>org.jivesoftware.smackx.gcm.provider.GcmExtensionProvider</className>
</extensionProvider>
----

Also, the `GcmPacketExtension` lets the target messaging protocol parse incoming packets and build outgoing packets, as the following examples show:

[source,java]
----
GcmPacketExtension gcmExtension = (GcmPacketExtension) xmppMessage.getExtension(GcmPacketExtension.NAMESPACE);
String message = gcmExtension.getJson());
----

[source,java]
----
GcmPacketExtension packetExtension = new GcmPacketExtension(gcmJson);
Message smackMessage = new Message();
smackMessage.addExtension(packetExtension);
----

See xref:xmpp.adoc#xmpp-message-inbound-channel-adapter[Inbound Message Channel Adapter] and xref:xmpp.adoc#xmpp-message-outbound-channel-adapter[Outbound Message Channel Adapter] earlier in this chapter for more information.
