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:
Gunnar Hillert
2012-11-06 13:16:47 -05:00
committed by Gary Russell
parent 5b0b0d731f
commit a5d7de848d
54 changed files with 2168 additions and 39 deletions

View File

@@ -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 youre using MySQL as a queue, and why itll 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>

View File

@@ -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>