INT-2674 - Add JdbcChannelMessageStore
INT-2674 - Added slow/failing JDBC Message Store Tests INT-2674 - Code Review Changes INT-2674 - Add support for HSQL INT-2674 - Add documentation * Refactor Test Cases * Code Review Changes INT-2674 - Code Review Changes INT-2674 - Code Review Changes INT-2674 - Renamed classes INT-2674 - Code Review Changes
This commit is contained in:
committed by
Gary Russell
parent
5b0b0d731f
commit
a5d7de848d
@@ -297,38 +297,149 @@
|
||||
|
||||
<section id="jdbc-message-store">
|
||||
<title>JDBC Message Store</title>
|
||||
|
||||
<para>The JDBC module provides an implementation of the Spring Integration
|
||||
<classname>MessageStore</classname> (important in the Claim Check pattern)
|
||||
and <classname>MessageGroupStore</classname> (important in stateful
|
||||
patterns like Aggregator) backed by a database. Both interfaces are
|
||||
implemented by the JdbcMessageStore, and there is also support for
|
||||
configuring store instances in XML. For example:</para>
|
||||
|
||||
<programlisting language="xml"><![CDATA[<int-jdbc:message-store id="messageStore" data-source="dataSource"/>
|
||||
<para>
|
||||
Spring Integration provides 2 JDBC specifc Message Store implementations.
|
||||
The first one, is the <classname>JdbcMessageStore</classname> which is
|
||||
suitable to be used in conjunction with <emphasis>Aggregators</emphasis>
|
||||
and the <emphasis>Claimcheck</emphasis> pattern. While it can be used for
|
||||
backing <emphasis>Message Channels</emphasis> as well, you may want to
|
||||
consider using the <classname>JdbcChannelMessageStore</classname> implementation
|
||||
instead, as it provides a more targeted and scalable implementation.
|
||||
</para>
|
||||
<section id="jdbc-message-store-generic">
|
||||
<title>The Generic JDBC Message Store</title>
|
||||
<para>
|
||||
The JDBC module provides an implementation of the Spring Integration
|
||||
<classname>MessageStore</classname> (important in the Claim Check pattern)
|
||||
and <classname>MessageGroupStore</classname> (important in stateful
|
||||
patterns like Aggregator) backed by a database. Both interfaces are
|
||||
implemented by the <classname>JdbcMessageStore</classname>, and there
|
||||
is also support for configuring store instances in XML.
|
||||
For example:</para>
|
||||
<programlisting language="xml"><![CDATA[<int-jdbc:message-store id="messageStore" data-source="dataSource"/>
|
||||
]]></programlisting>
|
||||
|
||||
<para>A <classname>JdbcTemplate</classname> can be specified instead of a
|
||||
<classname>DataSource</classname>.</para>
|
||||
|
||||
<para>Other optional attributes are show in the next example:</para>
|
||||
|
||||
<para><programlisting language="xml"><![CDATA[<int-jdbc:message-store id="messageStore" data-source="dataSource"
|
||||
<para>
|
||||
A <classname>JdbcTemplate</classname> can be specified instead of a
|
||||
<classname>DataSource</classname>.
|
||||
</para>
|
||||
<para>
|
||||
Other optional attributes are show in the next example:
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[<int-jdbc:message-store id="messageStore" data-source="dataSource"
|
||||
lob-handler="lobHandler" table-prefix="MY_INT_"/>]]></programlisting>
|
||||
<para>
|
||||
Here we have specified a <classname>LobHandler</classname> for dealing
|
||||
with messages as large objects (e.g. often necessary if using Oracle)
|
||||
and a prefix for the table names in the queries generated by the store.
|
||||
The table name prefix defaults to "INT_".
|
||||
</para>
|
||||
</section>
|
||||
<section id="jdbc-message-store-channels">
|
||||
<title>Backing Message Channels</title>
|
||||
<para>
|
||||
If you intent backing <emphasis>Message Channels</emphasis> using JDBC,
|
||||
it is recommended to use the provided <classname>JdbcChannelMessageStore</classname>
|
||||
implementation instead. It can only be used in conjuntion
|
||||
with <emphasis>Message Channels</emphasis>.
|
||||
</para>
|
||||
<note>
|
||||
The provided <classname>JdbcChannelMessageStore</classname>
|
||||
implementation is available since <emphasis>Spring Integration 2.2.</emphasis>.
|
||||
</note>
|
||||
<para><emphasis>Supported Database</emphasis></para>
|
||||
<para>
|
||||
The <classname>JdbcChannelMessageStore</classname> uses database specific
|
||||
SQL queries to retrieve messages from the database. Therefore, users must
|
||||
set the <interfacename>ChannelMessageStoreQueryProvider</interfacename> property on the
|
||||
<classname>JdbcChannelMessageStore</classname>. This
|
||||
<interfacename>channelMessageStoreQueryProvider</interfacename>
|
||||
provides the SQL queries and Spring Integration provides support for
|
||||
the following relational databases:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>PostgreSQL</listitem>
|
||||
<listitem>HSQLDB</listitem>
|
||||
<listitem>MySQL</listitem>
|
||||
<listitem>Oracle</listitem>
|
||||
<listitem>Derby</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
If your database is not listed, you can easily extend
|
||||
the <classname>AbstractChannelMessageStoreQueryProvider</classname>
|
||||
class and provide your own custom queries.
|
||||
</para>
|
||||
<important>
|
||||
<para>
|
||||
Generally it is not recommened to use a relational database for the
|
||||
purpose of queuing. Instead, if possible, consider using either JMS or
|
||||
AMQP, for which message store implementation are provided as well. For
|
||||
further reference please see the following resources:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><ulink url="https://www.engineyard.com/blog/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you/">5 subtle ways you’re using MySQL as a queue, and why it’ll bite you</ulink></listitem>
|
||||
<listitem><ulink url="http://mikehadlow.blogspot.com/2012/04/database-as-queue-anti-pattern.html">The Database As Queue Anti-Pattern</ulink></listitem>
|
||||
</itemizedlist>
|
||||
</important>
|
||||
<para><emphasis>Concurrent Polling</emphasis></para>
|
||||
<para>
|
||||
When polling a <emphasis>Message Channel</emphasis>, you have the option
|
||||
to configure the associated <classname>Poller</classname> with a
|
||||
<interfacename>TaskExecutor</interfacename> reference.
|
||||
</para>
|
||||
<para>
|
||||
Keep in mind, though, that if you use a JDBC backed <emphasis>Message Channel</emphasis> and
|
||||
you are planning on polling the channel and consequently the message
|
||||
store transactionally with multiple threads, you should ensure that
|
||||
you use a relational database that supports
|
||||
<ulink url="http://en.wikipedia.org/wiki/Multiversion_concurrency_control">Multiversion Concurrency Control</ulink> (MVCC).
|
||||
Otherwise, locking may be an issue and the performance, when using multiple
|
||||
threads, may not materialize as expected. For example Apache Derby is
|
||||
problematic in that regard.
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[…
|
||||
<bean id="queryProvider"
|
||||
class="o.s.i.jdbc.store.channel.PostgresChannelMessageStoreQueryProvider"/>
|
||||
|
||||
Here we have specified a <classname>LobHandler</classname> for dealing with
|
||||
messages as large objects (e.g. often necessary if using Oracle) and a
|
||||
prefix for the table names in the queries generated by the store. The
|
||||
table name prefix defaults to "INT_".</para>
|
||||
<int:transaction-synchronization-factory id="syncFactory">
|
||||
<int:after-commit expression="@store.removeFromIdCache(headers.id.toString())" />
|
||||
<int:after-rollback expression="@store.removeFromIdCache(headers.id.toString())"/>
|
||||
</int:transaction-synchronization-factory>
|
||||
|
||||
<task:executor id="pool" pool-size="10"
|
||||
queue-capacity="10" rejection-policy="CALLER_RUNS" />
|
||||
|
||||
<bean id="store" class="o.s.i.jdbc.store.JdbcChannelMessageStore">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
<property name="channelMessageStoreQueryProvider" ref="queryProvider"/>
|
||||
<property name="region" value="TX_TIMEOUT"/>
|
||||
<property name="usingIdCache" value="true"/>
|
||||
</bean>
|
||||
|
||||
<int:channel id="inputChannel">
|
||||
<int:queue message-store="store"/>
|
||||
</int:channel>
|
||||
|
||||
<int:bridge input-channel="inputChannel" output-channel="outputChannel">
|
||||
<int:poller fixed-delay="500" receive-timeout="500"
|
||||
max-messages-per-poll="1" task-executor="pool">
|
||||
<int:transactional propagation="REQUIRED" synchronization-factory="syncFactory"
|
||||
isolation="READ_COMMITTED" transaction-manager="transactionManager" />
|
||||
</int:poller>
|
||||
</int:bridge>
|
||||
|
||||
<int:channel id="outputChannel" />
|
||||
…]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>Initializing the Database</title>
|
||||
|
||||
<para>Spring Integration ships with some sample scripts that can be used
|
||||
to initialize a database. In the spring-integration-jdbc JAR file you
|
||||
will find scripts in the
|
||||
<classname>org.springframework.integration.jdbc</classname> package:
|
||||
there is a create and a drop script example for a range of common
|
||||
<classname>org.springframework.integration.jdbc</classname> and in the
|
||||
<classname>org.springframework.integration.jdbc.store.channel</classname>
|
||||
package: there is a create and a drop script example for a range of common
|
||||
database platforms. A common way to use these scripts is to reference
|
||||
them in a <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html#d0e24182">Spring
|
||||
@@ -353,7 +464,7 @@
|
||||
message data for a persistent channel is keyed in the store on the
|
||||
channel name, so if the channel names are not globally unique then there
|
||||
is the danger of channels picking up data that was not intended for
|
||||
them. To avoid this, the message store region can be used to keep data
|
||||
them. To avoid this, the message store <emphasis>region</emphasis> can be used to keep data
|
||||
separate for different physical channels that happen to have the same
|
||||
logical name.</para>
|
||||
</section>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
</para>
|
||||
</section>
|
||||
<section id="2.2-jdbc-11">
|
||||
<title>JDBC Adapter - Stored Procedures Components</title>
|
||||
<title>JDBC Support - Stored Procedures Components</title>
|
||||
<para><emphasis>SpEL Support</emphasis></para>
|
||||
<para>
|
||||
When using the Stored Procedure components of the Spring Integration
|
||||
@@ -92,13 +92,22 @@
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section id="2.2-jdbc-gateway-update-optional">
|
||||
<title>JDBC Adapter - Outbound Gateway</title>
|
||||
<title>JDBC Support - Outbound Gateway</title>
|
||||
<para>
|
||||
When using the JDBC Outbound Gateway, the update query is no longer
|
||||
mandatory. You can now provide solely a select query using the request
|
||||
message as a source of parameters.
|
||||
</para>
|
||||
</section>
|
||||
<section id="2.2-jdbc-message-store-channels">
|
||||
<title>JDBC Support - Channel-specific Message Store Implementation</title>
|
||||
<para>
|
||||
A new <emphasis>Message Channel</emphasis>-specific Message Store
|
||||
Implementation has been added, providing a more scalable solution
|
||||
using database-specific SQL queries. For more information please
|
||||
see: <xref linkend="jdbc-message-store-channels"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section id="2.2-file-adapter">
|
||||
<title>File Adapter - Improved File Overwrite/Append Handling</title>
|
||||
<para>
|
||||
|
||||
Reference in New Issue
Block a user