For reference see: https://jira.springsource.org/browse/INT-2882 * Verify spacing * Ensure all source code samples are typed: e.g. <programlisting language="xml"> * Ensure source code fits space in PDF format
278 lines
14 KiB
XML
278 lines
14 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="mongodb"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
<title>MongoDb Support</title>
|
|
|
|
<para>
|
|
As of version 2.1 Spring Integration introduces support for <ulink url="http://www.mongodb.org/">MongoDB</ulink>:
|
|
a <emphasis>"high-performance, open source, document-oriented database"</emphasis>.
|
|
This support comes in the form of a MongoDB-based MessageStore.
|
|
</para>
|
|
|
|
<section id="mongodb-intro">
|
|
<title>Introduction</title>
|
|
<para>
|
|
To download, install, and run MongoDB please refer to the <ulink url="http://www.mongodb.org/downloads">MongoDB documentation</ulink>.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="mongodb-connection">
|
|
<title>Connecting to MongoDb</title>
|
|
|
|
<para>To begin interacting with MongoDB you first need to connect to it. Spring Integration builds on the support provided by another
|
|
Spring project, <ulink url="http://www.springsource.org/spring-data/mongodb">Spring Data MongoDB</ulink>, which provides a factory
|
|
class called <classname>MongoDbFactory</classname> that simplifies integration with the MongoDB Client API.</para>
|
|
|
|
<para><emphasis>MongoDbFactory</emphasis> </para>
|
|
|
|
<para>
|
|
To connect to MongoDB you can use an implementation of the <classname>MongoDbFactory</classname> interface:
|
|
|
|
<programlisting language="java"><![CDATA[public interface MongoDbFactory {
|
|
|
|
/**
|
|
* Creates a default {@link DB} instance.
|
|
*
|
|
* @return the DB instance
|
|
* @throws DataAccessException
|
|
*/
|
|
DB getDb() throws DataAccessException;
|
|
|
|
/**
|
|
* Creates a {@link DB} instance to access the database with the given name.
|
|
*
|
|
* @param dbName must not be {@literal null} or empty.
|
|
*
|
|
* @return the DB instance
|
|
* @throws DataAccessException
|
|
*/
|
|
DB getDb(String dbName) throws DataAccessException;
|
|
}]]></programlisting>
|
|
</para>
|
|
|
|
<para>The example below shows <classname>SimpleMongoDbFactory</classname>, the out-of-the-box implementation:</para>
|
|
|
|
<para>In Java:
|
|
<programlisting language="java"><![CDATA[MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(new Mongo(), "test");]]></programlisting>
|
|
</para>
|
|
|
|
<para>Or in Spring's XML configuration:
|
|
<programlisting language="xml"><![CDATA[<bean id="mongoDbFactory" class="o.s.data.mongodb.core.SimpleMongoDbFactory">
|
|
<constructor-arg>
|
|
<bean class="com.mongodb.Mongo"/>
|
|
</constructor-arg>
|
|
<constructor-arg value="test"/>
|
|
</bean>]]></programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
As you can see <classname>SimpleMongoDbFactory</classname> takes two arguments: 1) a <classname>Mongo</classname> instance and
|
|
2) a String specifying the name of the database. If you need to configure properties such as <code>host</code>, <code>port</code>, etc,
|
|
you can pass those using one of the constructors provided by the underlying <classname>Mongo</classname> class.
|
|
For more information on how to configure MongoDB, please refer to the
|
|
<ulink url="http://static.springsource.org/spring-data/data-document/docs/current/reference/html/">Spring-Data-Document</ulink> reference.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="mongodb-message-store">
|
|
<title>MongoDB Message Store</title>
|
|
|
|
<para>
|
|
As described in EIP, a <ulink url="http://www.eaipatterns.com/MessageStore.html">Message Store</ulink> allows you to persist Messages.
|
|
This can be very useful when dealing with components that have a capability to buffer messages
|
|
(<emphasis>QueueChannel, Aggregator, Resequencer</emphasis>, etc.) if reliability is a concern.
|
|
In Spring Integration, the MessageStore strategy also provides the foundation for the
|
|
<ulink url="http://www.eaipatterns.com/StoreInLibrary.html">ClaimCheck</ulink> pattern, which is described in EIP as well.
|
|
</para>
|
|
|
|
<para>
|
|
Spring Integration's MongoDB module provides the <classname>MongoDbMessageStore</classname> which is an implementation of both
|
|
the <classname>MessageStore</classname> strategy (mainly used by the <emphasis>QueueChannel</emphasis> and <emphasis>ClaimCheck</emphasis>
|
|
patterns) and the <classname>MessageGroupStore</classname> strategy (mainly used by the <emphasis>Aggregator</emphasis> and
|
|
<emphasis>Resequencer</emphasis> patterns).
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting language="xml"><![CDATA[<bean id="mongoDbMessageStore" class="o.s.i.mongodb.store.MongoDbMessageStore">
|
|
<constructor-arg ref="mongoDbFactory"/>
|
|
</bean>
|
|
|
|
<int:channel id="somePersistentQueueChannel">
|
|
<int:queue message-store="mongoDbMessageStore"/>
|
|
<int:channel>
|
|
|
|
<int:aggregator input-channel="inputChannel" output-channel="outputChannel"
|
|
message-store="mongoDbMessageStore"/>]]></programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Above is a sample <classname>MongoDbMessageStore</classname> configuration that shows its usage by a <emphasis>QueueChannel</emphasis>
|
|
and an <emphasis>Aggregator</emphasis>. As you can see it is a simple bean configuration, and it expects a
|
|
<classname>MongoDbFactory</classname> as a constructor argument.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="mongodb-inbound-channel-adapter">
|
|
<title>MongoDB Inbound Channel Adapter</title>
|
|
|
|
<para>
|
|
The <emphasis>MongoDb Inbound Channel Adapter</emphasis> is a polling consumer that reads data
|
|
from MongoDb and sends it as a Message payload.
|
|
</para>
|
|
|
|
<programlisting language="xml"><![CDATA[<int-mongodb:inbound-channel-adapter id="mongoInboundAdapter"
|
|
channel="replyChannel"
|
|
query="{'name' : 'Bob'}"
|
|
entity-class="java.lang.Object"
|
|
auto-startup="false">
|
|
<int:poller fixed-rate="100"/>
|
|
</int-mongodb:inbound-channel-adapter>]]></programlisting>
|
|
|
|
<para>
|
|
As you can see from the configuration above, you configure a <emphasis>MongoDb Inbound Channel Adapter</emphasis> using
|
|
the <code>inbound-channel-adapter</code> element, providing values for various attributes such as:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><code>query</code> or <code>query-expression</code> - a
|
|
JSON query (see <ulink url="http://www.mongodb.org/display/DOCS/Querying">MongoDb Querying</ulink>) </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>entity-class</code> - the type of the payload object; if not supplied, a
|
|
<classname>com.mongodb.DBObject</classname> will be returned.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>collection-name</code> or <code>collection-name-expression</code> -
|
|
Identifies the name of the MongoDb collection to use. </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>mongodb-factory</code> -
|
|
reference to an instance of <classname>o.s.data.mongodb.MongoDbFactory</classname> </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>mongo-template</code> -
|
|
reference to an instance of <classname>o.s.data.mongodb.core.MongoTemplate</classname>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
and other attributes that are common across all other inbound adapters (e.g., 'channel').
|
|
</para>
|
|
<note>
|
|
You cannot set both <code>mongo-template</code> and <code>mongodb-factory</code>.
|
|
</note>
|
|
<para>
|
|
The example above is relatively simple and static since it has a literal value for the <code>query</code> and uses
|
|
the default name for a <code>collection</code>. Sometimes you may need to change those values at runtime, based on some condition.
|
|
To do that, simply use their <code>-expression</code> equivalents (<code>query-expression</code> and
|
|
<code>collection-name-expression</code>) where the provided expression can be any valid SpEL expression.
|
|
</para>
|
|
<para>
|
|
Also, you may wish to do some post-processing to the successfully processed data that was read from the MongoDb.
|
|
For example; you may want to move or remove a document after its been processed.
|
|
You can do this using Transaction Synchronization feature that was added with Spring Integration 2.2.
|
|
</para>
|
|
<programlisting language="xml"><![CDATA[<int-mongodb:inbound-channel-adapter id="mongoInboundAdapter"
|
|
channel="replyChannel"
|
|
query="{'name' : 'Bob'}"
|
|
entity-class="java.lang.Object"
|
|
auto-startup="false">
|
|
<int:poller fixed-rate="200" max-messages-per-poll="1">
|
|
<int:transactional synchronization-factory="syncFactory"/>
|
|
</int:poller>
|
|
</int-mongodb:inbound-channel-adapter>
|
|
|
|
<int:transaction-synchronization-factory id="syncFactory">
|
|
<int:after-commit expression="@documentCleaner.remove(#mongoTemplate, payload, headers.mongo_collectionName)" channe="someChannel"/>
|
|
</int:transaction-synchronization-factory>
|
|
|
|
<bean id="documentCleaner" class="foo.bar.DocumentCleaner"/>
|
|
|
|
<bean id="transactionManager" class="o.s.i.transaction.PseudoTransactionManager"/>]]></programlisting>
|
|
|
|
<programlisting language="java"><![CDATA[public class DocumentCleaner {
|
|
public void remove(MongoOperations mongoOperations, Object target, String collectionName) {
|
|
if (target instanceof List<?>){
|
|
List<?> documents = (List<?>) target;
|
|
for (Object document : documents) {
|
|
mongoOperations.remove(new BasicQuery(JSON.serialize(document)), collectionName);
|
|
}
|
|
}
|
|
}
|
|
}]]></programlisting>
|
|
<para>
|
|
As you can see from the above, all you need to do is declare your poller to be transactional with a <code>transactional</code> element.
|
|
This element can reference a real transaction manager (for example if some other part of your flow invokes JDBC).
|
|
If you don't have a 'real' transaction, you can use a
|
|
<classname>org.springframework.integration.transaction.PseudoTransactionManager</classname> which is an implementation
|
|
of Spring's <classname>PlatformTransactionManager</classname> and enables the use of the transaction synchronization
|
|
features of the mongo adapter when there is no actual transaction.
|
|
</para>
|
|
<important>
|
|
This does NOT make MongoDB itself transactional, it simply allows the synchronization of actions to be taken before/after success (commit)
|
|
or after failure (rollback).
|
|
</important>
|
|
<para>
|
|
Once your poller is transactional all you need to do is set an instance of the
|
|
<classname>org.springframework.integration.transaction.TransactionSynchronizationFactory</classname> on the <code>transactional</code> element.
|
|
<classname>TransactionSynchronizationFactory</classname> will create an instance of the <classname>TransactioinSynchronization</classname>.
|
|
For your convenience, we've exposed a default SpEL-based <classname>TransactionSynchronizationFactory</classname> which allows
|
|
you to configure SpEL expressions, with their execution being coordinated (synchronized) with a transaction.
|
|
Expressions for before-commit, after-commit, and after-rollback are supported, together with a channel for each where the
|
|
evaluation result (if any) will be sent. For each sub-element you can specify <code>expression</code> and/or <code>channel</code>
|
|
attributes. If only the <code>channel</code> attribute is present the received Message will be sent there as part of the particular
|
|
synchronization scenario. If only the <code>expression</code> attribute is present and the result of an expression is a non-Null
|
|
value, a Message with the result as the payload will be generated and sent to a default channel (NullChannel) and will appear in the
|
|
logs (DEBUG). If you want the evaluation result to go to a specific channel add a <code>channel</code> attribute. If the result of an
|
|
expression is null or void, no Message will be generated.
|
|
</para>
|
|
<para>
|
|
For more information about transaction synchronization, see <xref linkend="transaction-synchronization"/>.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="mongodb-outbound-channel-adapter">
|
|
<title>MongoDB Outbound Channel Adapter</title>
|
|
|
|
<para>
|
|
The <emphasis>MongoDb Outbound Channel Adapter</emphasis> allows you to write the Message payload to a MongoDb document store
|
|
</para>
|
|
|
|
<programlisting language="xml"><![CDATA[<int-mongodb:outbound-channel-adapter id="fullConfigWithCollectionExpression"
|
|
collection-name="myCollection"
|
|
mongo-converter="mongoConverter"
|
|
mongodb-factory="mongoDbFactory" />]]></programlisting>
|
|
|
|
<para>
|
|
As you can see from the configuration above, you configure a <emphasis>MongoDb Outbound Channel Adapter</emphasis> using
|
|
the <code>outbound-channel-adapter</code> element, providing values for various attributes such as:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><code>collection-name</code> or <code>collection-name-expression</code> -
|
|
Identifies the name of the MongoDb collection to use. </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>mongo-converter</code> -
|
|
reference to an instance of <classname>o.s.data.mongodb.core.convert.MongoConverter</classname> to assist with
|
|
converting a raw java object to a JSON document representation </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>mongodb-factory</code> -
|
|
reference to an instance of <classname>o.s.data.mongodb.MongoDbFactory</classname> </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><code>mongo-template</code> -
|
|
reference to an instance of <classname>o.s.data.mongodb.core.MongoTemplate</classname>
|
|
(NOTE: you can not have both mongo-template and mongodb-factory set)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
and other attributes that are common across all other inbound adapters (e.g., 'channel').
|
|
</para>
|
|
<para>
|
|
The example above is relatively simple and static since it has a literal value for the <code>collection-name</code>.
|
|
Sometimes you may need to change this value at runtime based on some condition.
|
|
To do that, simply use <code>collection-name-expression</code>
|
|
where the provided expression can be any valid SpEL expression.
|
|
</para>
|
|
</section>
|
|
|
|
</chapter> |