Initial draft of the stored proc. adapters

The following 3 components are provided:

* stored-proc-outbound-channel-adapter
* stored-proc-outbound-gateway
* stored-proc-inbound-channel-adapter
This commit is contained in:
Gunnar Hillert
2011-10-04 00:42:21 -04:00
committed by Mark Fisher
parent 3e1b0596bb
commit b018ea84c8
68 changed files with 4667 additions and 63 deletions

View File

@@ -310,7 +310,7 @@ project('spring-integration-jdbc') {
compile "org.springframework:spring-jdbc:$springVersion"
compile "org.springframework:spring-tx:$springVersion"
testCompile project(":spring-integration-test")
testCompile "com.h2database:h2:1.2.125"
testCompile "com.h2database:h2:1.3.160"
testCompile "hsqldb:hsqldb:1.8.0.10"
testCompile "org.apache.derby:derby:10.5.3.0_1"
testCompile "org.aspectj:aspectjrt:$aspectjVersion"

View File

@@ -220,5 +220,293 @@
separate for different physical channels that happen to have the same
logical name.</para>
</section>
</section>
</section>
<section id="stored-procedures">
<title>Stored Procedures</title>
<para>Spring Integration provides 3 components for stored procedures support:</para>
<itemizedlist>
<listitem>Stored Procedures Inbound Channel Adapter</listitem>
<listitem>Stored Procedures Outbound Channel Adapter</listitem>
<listitem>Stored Procedures Outbound Gateway</listitem>
</itemizedlist>
<section id="sp-common-config-params">
<title>Common Configuration Parameters</title>
</section>
<section id="sp-supported-databases">
<title>Supported Parameters</title>
<para>The Store procedures components use the <classname>org.springframework.jdbc.core.simple.SimpleJdbcCall</classname>
class to facilitate Stored Procedure support. The following databases
are fully supported for executing Stored procedures:</para>
<itemizedlist>
<listitem>Apache Derby</listitem>
<listitem>DB2</listitem>
<listitem>MySQL</listitem>
<listitem>Microsoft SQL Server</listitem>
<listitem>Oracle</listitem>
<listitem>PostgreSQL</listitem>
<listitem>Sybase</listitem>
</itemizedlist>
<para>The following databases are fully supported for executing Sql
functions:</para>
<itemizedlist>
<listitem>MySQL</listitem>
<listitem>Microsoft SQL Server</listitem>
<listitem>Oracle</listitem>
<listitem>PostgreSQL</listitem>
</itemizedlist>
</section>
<note><para>Even though your particular database may not be fully supported, chances
are that you can use the Stored Procedures Spring Integration
components quite successfully anyway, provided your RDBMS supports
Stored Procedures or Functions.</para>
<para>As a matter of fact, some of the provided
integration tests use the the H2 database. Nevertheless it is very important
to thouroughly test those usasge scenarios.</para></note>
<section id="sp-defining-parameter-sources">
<title>Defining Parameter Sources</title>
<para>TBD</para>
</section>
<section id="stored-procedures-inbound-channel-adapter">
<title>Stored Procedures Inbound Channel Adapter</title>
<programlisting language="xml">
<![CDATA[
<int-jdbc:stored-proc-inbound-channel-adapter
channel="" ]]><co id="sp-inbound-xml01-co" linkends="sp-inbound-xml01" /><![CDATA[
stored-procedure-name="" ]]><co id="sp-inbound-xml02-co" linkends="sp-inbound-xml02" /><![CDATA[
data-source="" ]]><co id="sp-inbound-xml03-co" linkends="sp-inbound-xml03" /><![CDATA[
auto-startup="true" ]]><co id="sp-inbound-xml04-co" linkends="sp-inbound-xml04" /><![CDATA[
id="" ]]><co id="sp-inbound-xml05-co" linkends="sp-inbound-xml05" /><![CDATA[
ignore-column-meta-data="false" ]]><co id="sp-inbound-xml06-co" linkends="sp-inbound-xml06" /><![CDATA[
is-function="false" ]]><co id="sp-inbound-xml07-co" linkends="sp-inbound-xml07" /><![CDATA[
max-rows-per-poll="" ]]><co id="sp-inbound-xml08-co" linkends="sp-inbound-xml08" /><![CDATA[
update="" ]]><co id="sp-inbound-xml09-co" linkends="sp-inbound-xml09" /><![CDATA[
update-per-row="false" ]]><co id="sp-inbound-xml10-co" linkends="sp-inbound-xml10" /><![CDATA[
update-sql-parameter-source-factory=""> ]]><co id="sp-inbound-xml11-co" linkends="sp-inbound-xml11" /><![CDATA[
<int:poller/> ]]><co id="sp-inbound-xml12-co" linkends="sp-inbound-xml12" /><![CDATA[
<int-jdbc:sql-parameter-definition name="" direction="IN" ]]><co id="sp-inbound-xml13-co" linkends="sp-inbound-xml13" /><![CDATA[
type="INTEGER" ]]><co id="sp-inbound-xml14-co" linkends="sp-inbound-xml14" /><![CDATA[
scale="10"/> ]]><co id="sp-inbound-xml15-co" linkends="sp-inbound-xml15" /><![CDATA[
<int-jdbc:parameter name="" type="" value=""/> ]]><co id="sp-inbound-xml16-co" linkends="sp-inbound-xml16" /><![CDATA[
<int-jdbc:parameter name="" expression=""/> ]]><co id="sp-inbound-xml17-co" linkends="sp-inbound-xml17" /><![CDATA[
<int-jdbc:returning-resultset name="" row-mapper="" /> ]]><co id="sp-inbound-xml18-co" linkends="sp-inbound-xml18" /><![CDATA[
</int-jdbc:stored-proc-inbound-channel-adapter> ]]><co id="sp-inbound-xml19-co" linkends="sp-inbound-xml19" /><![CDATA[
]]>
</programlisting>
<para>
<calloutlist>
<callout arearefs="sp-inbound-xml01-co" id="sp-inbound-xml01">
<para>Channel to which polled messages will be send. If the stored
procedure or function does not return any data, the payload
of the Message will be Null. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml02-co" id="sp-inbound-xml02">
<para>The name of the stored procedure. If the "is-function"
attribute is "true", this attributes specifies the
function name. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml03-co" id="sp-inbound-xml03">
<para>Reference to a data source to use to access
the database. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml04-co" id="sp-inbound-xml04">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml05-co" id="sp-inbound-xml05">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml06-co" id="sp-inbound-xml06">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml07-co" id="sp-inbound-xml07">
<para>If "true", a SQL Function is called. In that case
the "stored-procedure-name" attribute defines
the name of the called function. Defaults to false. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml08-co" id="sp-inbound-xml08">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml09-co" id="sp-inbound-xml09">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml10-co" id="sp-inbound-xml10">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml11-co" id="sp-inbound-xml11">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml12-co" id="sp-inbound-xml12">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml13-co" id="sp-inbound-xml13">
<para>Specifies the direction of the Sql parameter definition.
Defaults to 'IN'. If your procedure is returning ResultSets,
please use the 'returning-resultset' element. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml14-co" id="sp-inbound-xml14">
<para>The Sql type used for this Sql parameter defintion. Will translate
into the integer value as defined by java.sql.Types. Alternatively
you can provide the integer value as well. If this attribute is
not explicitly set, then it will default to 'VARCHAR'.<emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml15-co" id="sp-inbound-xml15">
<para>The scale of the Sql parameter. Only used for numeric and decimal
parameters. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml16-co" id="sp-inbound-xml16">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml17-co" id="sp-inbound-xml17">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml18-co" id="sp-inbound-xml18">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-inbound-xml19-co" id="sp-inbound-xml19">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
</calloutlist></para>
</section>
<section id="stored-procedures-outbound-channel-adapter">
<title>Stored Procedures Outbound Channel Adapter</title>
<programlisting language="xml">
<![CDATA[
<int-jdbc:stored-proc-outbound-channel-adapter channel="" ]]><co id="sp-outbound-xml01-co" linkends="sp-outbound-xml01" /><![CDATA[
stored-procedure-name="" ]]><co id="sp-outbound-xml02-co" linkends="sp-outbound-xml02" /><![CDATA[
data-source="" ]]><co id="sp-outbound-xml03-co" linkends="sp-outbound-xml03" /><![CDATA[
auto-startup="true" ]]><co id="sp-outbound-xml04-co" linkends="sp-outbound-xml04" /><![CDATA[
id="" ]]><co id="sp-outbound-xml05-co" linkends="sp-outbound-xml05" /><![CDATA[
ignore-column-meta-data="false" ]]><co id="sp-outbound-xml06-co" linkends="sp-outbound-xml06" /><![CDATA[
order="" ]]><co id="sp-outbound-xml07-co" linkends="sp-outbound-xml07" /><![CDATA[
return-value-required="false" ]]><co id="sp-outbound-xml08-co" linkends="sp-outbound-xml08" /><![CDATA[
sql-parameter-source-factory=""> ]]><co id="sp-outbound-xml09-co" linkends="sp-outbound-xml09" /><![CDATA[
<int:poller fixed-rate=""/>
<int-jdbc:sql-parameter-definition name=""/>
<int-jdbc:parameter name=""/>
</int-jdbc:stored-proc-outbound-channel-adapter>
]]>
</programlisting>
<para>
<calloutlist>
<callout arearefs="sp-outbound-xml01-co" id="sp-outbound-xml01">
<para> <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml02-co" id="sp-outbound-xml02">
<para>The name of the stored procedure. If the "is-function"
attribute is "true", this attributes specifies the
function name. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml03-co" id="sp-outbound-xml03">
<para>Reference to a data source to use to access
the database. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml04-co" id="sp-outbound-xml04">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml05-co" id="sp-outbound-xml05">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml06-co" id="sp-outbound-xml06">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml07-co" id="sp-outbound-xml07">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml08-co" id="sp-outbound-xml08">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-outbound-xml09-co" id="sp-outbound-xml09">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
</calloutlist></para>
</section>
<section id="stored-procedures-outbound-gateway">
<title>Stored Procedures Outbound Gateway</title>
<programlisting language="xml">
<![CDATA[
<int-jdbc:stored-proc-outbound-gateway request-channel="" ]]><co id="sp-gateway-xml01-co" linkends="sp-gateway-xml01" /><![CDATA[
stored-procedure-name="" ]]><co id="sp-gateway-xml02-co" linkends="sp-gateway-xml02" /><![CDATA[
data-source="" ]]><co id="sp-gateway-xml03-co" linkends="sp-gateway-xml03" /><![CDATA[
auto-startup="true" ]]><co id="sp-gateway-xml04-co" linkends="sp-gateway-xml04" /><![CDATA[
id="" ]]><co id="sp-gateway-xml05-co" linkends="sp-gateway-xml05" /><![CDATA[
ignore-column-meta-data="false" ]]><co id="sp-gateway-xml06-co" linkends="sp-gateway-xml06" /><![CDATA[
is-function="false" ]]><co id="sp-gateway-xml07-co" linkends="sp-gateway-xml07" /><![CDATA[
order="" ]]><co id="sp-gateway-xml08-co" linkends="sp-gateway-xml08" /><![CDATA[
reply-channel="" ]]><co id="sp-gateway-xml09-co" linkends="sp-gateway-xml09" /><![CDATA[
request-timeout="" ]]><co id="sp-gateway-xml10-co" linkends="sp-gateway-xml10" /><![CDATA[
return-value-required="false" ]]><co id="sp-gateway-xml11-co" linkends="sp-gateway-xml11" /><![CDATA[
sql-parameter-source-factory=""> ]]><co id="sp-gateway-xml12-co" linkends="sp-gateway-xml12" /><![CDATA[
<int-jdbc:sql-parameter-definition name="" direction="IN"
type=""
scale="10"/> ]]><co id="sp-gateway-xml13-co" linkends="sp-gateway-xml13" /><![CDATA[
<int-jdbc:sql-parameter-definition name=""/> ]]><co id="sp-gateway-xml14-co" linkends="sp-gateway-xml14" /><![CDATA[
<int-jdbc:parameter name="" type="" value=""/> ]]><co id="sp-gateway-xml15-co" linkends="sp-gateway-xml15" /><![CDATA[
<int-jdbc:parameter name="" expression=""/> ]]><co id="sp-gateway-xml16-co" linkends="sp-gateway-xml16" /><![CDATA[
<int-jdbc:returning-resultset name="" row-mapper="" /> ]]><co id="sp-gateway-xml17-co" linkends="sp-gateway-xml17" /><![CDATA[
]]></programlisting>
<para>
<calloutlist>
<callout arearefs="sp-gateway-xml01-co" id="sp-gateway-xml01">
<para> <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml02-co" id="sp-gateway-xml02">
<para>The name of the stored procedure. If the "is-function"
attribute is "true", this attributes specifies the
function name. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml03-co" id="sp-gateway-xml03">
<para>Reference to a data source to use to access
the database. <emphasis>Required</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml04-co" id="sp-gateway-xml04">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml05-co" id="sp-gateway-xml05">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml06-co" id="sp-gateway-xml06">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml07-co" id="sp-gateway-xml07">
<para>If "true", a SQL Function is called. In that case
the "stored-procedure-name" attribute defines
the name of the called function. Defaults to false. <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml08-co" id="sp-gateway-xml08">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml09-co" id="sp-gateway-xml09">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml10-co" id="sp-gateway-xml10">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml11-co" id="sp-gateway-xml11">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml12-co" id="sp-gateway-xml12">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml13-co" id="sp-gateway-xml13">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml14-co" id="sp-gateway-xml14">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml15-co" id="sp-gateway-xml15">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml16-co" id="sp-gateway-xml16">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
<callout arearefs="sp-gateway-xml17-co" id="sp-gateway-xml17">
<para> <emphasis>Optional</emphasis>.</para>
</callout>
</calloutlist></para>
</section>
</section>
</chapter>

View File

@@ -137,7 +137,7 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.125</version>
<version>1.3.160</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -20,7 +20,6 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.expression.ExpressionException;
import org.springframework.integration.util.AbstractExpressionEvaluator;
import org.springframework.jdbc.core.namedparam.AbstractSqlParameterSource;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -29,6 +29,7 @@ import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.util.LinkedCaseInsensitiveMap;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.jdbc.core.RowMapperResultSetExtractor;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
/**
* A polling channel adapter that creates messages from the payload returned by

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,335 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.expression.Expression;
import org.springframework.integration.Message;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.util.Assert;
/**
* A message handler that executes Stored Procedures for update purposes.
*
* Stored procedure parameter value are by default automatically extracted from
* the Payload if the payload's bean properties match the parameters of the Stored
* Procedure.
*
* This may be sufficient for basic use cases. For more sophisticated options
* consider passing in one or more {@link ProcedureParameter}.
*
* If you need to handle the return parameters of the called stored procedure
* explicitly, please consider using a {@link StoredProcOutboundGateway} instead.
*
* Also, if you need to execute SQL Functions, please also use the
* {@link StoredProcOutboundGateway}. As functions are typically used to look up
* values, only, the Stored Procedure message handler does purposefully not support
* SQL function calls. If you believe there are valid use-cases for that, please file a
* feature request at http://jira.springsource.org.
*
*
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcExecutor implements InitializingBean {
/**
* Uses the {@link SimpleJdbcCall} implementation for executing Stored Procedures.
* For more details please see:
*/
private final SimpleJdbcCallOperations jdbcCallOperations;
/**
* Name of the stored procedure to execute.
*/
private volatile String storedProcedureName;
/**
* For fully supported databases, the underlying {@link SimpleJdbcCall} can
* retrieve the parameter information for the to be invoked Stored Procedure
* from the JDBC Meta-data. However, if the used database does not support
* meta data lookups or if you like to provide customized parameter definitions,
* this flag can be set to 'true'. It defaults to 'false'.
*/
private volatile boolean ignoreColumnMetaData = false;
/**
* If you database system is not fully supported by Spring and thus obtaining
* parameter definitions from the JDBC Meta-data is not possible, you must define
* the {@link SqlParameter} explicitly.
*/
private volatile List<SqlParameter> sqlParameters = new ArrayList<SqlParameter>(0);
/**
* By default bean properties of the passed in {@link Message} will be used
* as a source for the Stored Procedure's input parameters.
*
* This may be sufficient for basic use cases. For more sophisticated options
* consider passing in one or more {@link ProcedureParameter}.
*/
private volatile SqlParameterSourceFactory sqlParameterSourceFactory = new BeanPropertySqlParameterSourceFactory();
/**
* Indicates that whether only the payload of the passed in {@link Message}
* will be used as a source of parameters. The is 'true' by default because as a
* default a {@link BeanPropertySqlParameterSourceFactory} implementation is
* used for the sqlParameterSourceFactory property.
*/
private volatile boolean usePayloadAsParameterSource = false;
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
*/
private volatile List<ProcedureParameter>procedureParameters;
private volatile boolean isFunction = false;
private volatile boolean returnValueRequired = false;
private volatile Map<String, RowMapper<?>> returningResultSetRowMappers = new HashMap<String, RowMapper<?>>(0);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Constructor taking {@link DataSource} from which the DB Connection can be
* obtained and the select query to execute the stored procedure.
*
* @param dataSource used to create a {@link SimpleJdbcTemplate}, must not be Null
* @param storedProcedureName Name of the Stored Procedure of function, must not be empty
*/
public StoredProcExecutor(DataSource dataSource, String storedProcedureName) {
Assert.notNull(dataSource, "dataSource must not be null.");
Assert.hasText(storedProcedureName, "storedProcedureName must not be null and cannot be empty.");
this.jdbcCallOperations = new SimpleJdbcCall(dataSource);
this.storedProcedureName = storedProcedureName;
}
/**
* Verifies parameters, sets the parameters on {@link SimpleJdbcCallOperations}
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* when {@link ProcedureParameter} are passed in.
*/
public void afterPropertiesSet() {
if (this.procedureParameters != null) {
if (!(this.sqlParameterSourceFactory instanceof ExpressionEvaluatingSqlParameterSourceFactory)) {
this.sqlParameterSourceFactory = new ExpressionEvaluatingSqlParameterSourceFactory();
}
ExpressionEvaluatingSqlParameterSourceFactory expressionSourceFactory
= (ExpressionEvaluatingSqlParameterSourceFactory) this.sqlParameterSourceFactory;
expressionSourceFactory.setStaticParameters(ProcedureParameter.convertStaticParameters(procedureParameters));
expressionSourceFactory.setParameterExpressions(ProcedureParameter.convertExpressions(procedureParameters));
}
if (this.ignoreColumnMetaData) {
this.jdbcCallOperations.withoutProcedureColumnMetaDataAccess();
}
this.jdbcCallOperations.declareParameters(this.sqlParameters.toArray(new SqlParameter[this.sqlParameters.size()]));
if (!this.returningResultSetRowMappers.isEmpty()) {
for (Entry<String, RowMapper<?>> mapEntry : this.returningResultSetRowMappers.entrySet()) {
jdbcCallOperations.returningResultSet(mapEntry.getKey(), mapEntry.getValue());
}
}
if (this.returnValueRequired) {
jdbcCallOperations.withReturnValue();
}
if (this.isFunction) {
this.jdbcCallOperations.withFunctionName(this.storedProcedureName);
} else {
this.jdbcCallOperations.withProcedureName(this.storedProcedureName);
}
}
/**
* Execute a Stored Procedure of Function - Use when not {@link Message} is
* available to extract {@link ProcedureParameter} values from it.
*
* @return Map containing the stored procedure results if any.
*/
public Map<String, Object> executeStoredProcedure() {
return executeStoredProcedureInternal(new Object());
}
/**
* Execute a Stored Procedure of Function - Use with {@link Message} is
* available to extract {@link ProcedureParameter} values from it.
*
* @return Map containing the stored procedure results if any.
*/
public Map<String, Object> executeStoredProcedure(Message<?> message) {
Assert.notNull(message, "The message parameter must not be null.");
if (usePayloadAsParameterSource) {
return executeStoredProcedureInternal(message.getPayload());
} else {
return executeStoredProcedureInternal(message);
}
}
/**
* Execute the Stored Procedure using the passed in {@link Message} as a source
* for parameters.
*
* @param message The message is used to extract parameters for the stored procedure.
* @return A map containing the return values from the Stored Procedure call if any.
*/
private Map<String, Object> executeStoredProcedureInternal(Object input) {
SqlParameterSource storedProcedureParameterSource =
sqlParameterSourceFactory.createParameterSource(input);
return StoredProcExecutor.executeStoredProcedure(jdbcCallOperations,
storedProcedureParameterSource);
}
/**
*/
private static Map<String, Object> executeStoredProcedure(SimpleJdbcCallOperations simpleJdbcCallOperations,
SqlParameterSource storedProcedureParameterSource) {
Map<String, Object> resultMap = simpleJdbcCallOperations.execute(storedProcedureParameterSource);
return resultMap;
}
//~~~~~Setters for Properties~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* For fully supported databases, the underlying {@link SimpleJdbcCall} can
* retrieve the parameter information for the to be invoked Stored Procedure
* from the JDBC Meta-data. However, if the used database does not support
* meta data lookups or if you like to provide customized parameter definitions,
* this flag can be set to 'true'. It defaults to 'false'.
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.ignoreColumnMetaData = ignoreColumnMetaData;
}
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
*/
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
Assert.notEmpty(procedureParameters, "procedureParameters must not be null or empty.");
for (ProcedureParameter procedureParameter : procedureParameters) {
Assert.notNull(procedureParameter, "The provided list (procedureParameters) cannot contain null values.");
}
this.procedureParameters = procedureParameters;
this.usePayloadAsParameterSource = false;
}
/**
* If you database system is not fully supported by Spring and thus obtaining
* parameter definitions from the JDBC Meta-data is not possible, you must define
* the {@link SqlParameter} explicitly.
*/
public void setSqlParameters(List<SqlParameter> sqlParameters) {
Assert.notEmpty(sqlParameters, "sqlParameters must not be null or empty.");
for (SqlParameter sqlParameter : sqlParameters) {
Assert.notNull(sqlParameter, "The provided list (sqlParameters) cannot contain null values.");
}
this.sqlParameters = sqlParameters;
}
/**
* Provides the ability to set a custom {@link SqlParameterSourceFactory}.
* Keep in mind that if {@link ProcedureParameter} are set explicitly and
* you would like to provide a custom {@link SqlParameterSourceFactory},
* then you must provide an instance of {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* If not the SqlParameterSourceFactory will be replaced the default
* {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
Assert.notNull(sqlParameterSourceFactory, "sqlParameterSourceFactory must not be null.");
this.sqlParameterSourceFactory = sqlParameterSourceFactory;
this.usePayloadAsParameterSource = false;
}
/**
* @return the name of the Stored Procedure or Function
* */
public String getStoredProcedureName() {
return this.storedProcedureName;
}
public void setUsePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.usePayloadAsParameterSource = usePayloadAsParameterSource;
}
public void setFunction(boolean isFunction) {
this.isFunction = isFunction;
}
public void setReturnValueRequired(boolean returnValueRequired) {
this.returnValueRequired = returnValueRequired;
}
/**
* If the Stored Procedure returns ResultSets you may provide a map of
* {@link RowMapper} to convert the {@link ResultSet} to meaningful objects.
*
* @param returningResultSetRowMappers The map may not be null and must not contain null values.
*/
public void setReturningResultSetRowMappers(
Map<String, RowMapper<?>> returningResultSetRowMappers) {
Assert.notNull(returningResultSetRowMappers, "returningResultSetRowMappers must not be null.");
for (RowMapper<?> rowMapper : returningResultSetRowMappers.values()) {
Assert.notNull(rowMapper, "The provided map cannot contain null values.");
}
this.returningResultSetRowMappers = returningResultSetRowMappers;
}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.expression.Expression;
import org.springframework.integration.Message;
import org.springframework.integration.MessageDeliveryException;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.util.Assert;
/**
* A message handler that executes Stored Procedures for update purposes.
*
* Stored procedure parameter value are by default automatically extracted from
* the Payload if the payload's bean properties match the parameters of the Stored
* Procedure.
*
* This may be sufficient for basic use cases. For more sophisticated options
* consider passing in one or more {@link ProcedureParameter}.
*
* If you need to handle the return parameters of the called stored procedure
* explicitly, please consider using a {@link StoredProcOutboundGateway} instead.
*
* Also, if you need to execute SQL Functions, please also use the
* {@link StoredProcOutboundGateway}. As functions are typically used to look up
* values, only, the Stored Procedure message handler does purposefully not support
* SQL function calls. If you believe there are valid use-cases for that, please file a
* feature request at http://jira.springsource.org.
*
*
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcMessageHandler extends AbstractMessageHandler implements InitializingBean {
final StoredProcExecutor executor;
/**
* Constructor taking {@link DataSource} from which the DB Connection can be
* obtained and the name of the stored procedure or function to
* execute to retrieve new rows.
*
* @param dataSource used to create a {@link SimpleJdbcTemplate}. Must not be null.
* @param storedProcedureName The name of the Stored Procedure or Function. Must not be null.
*/
public StoredProcMessageHandler(DataSource dataSource, String storedProcedureName) {
Assert.notNull(dataSource, "dataSource must not be null.");
Assert.hasText(storedProcedureName, "storedProcedureName must not be null and cannot be empty.");
this.executor = new StoredProcExecutor(dataSource, storedProcedureName);
this.executor.setUsePayloadAsParameterSource(true);
}
/**
* Verifies parameters, sets the parameters on {@link SimpleJdbcCallOperations}
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* when {@link ProcedureParameter} are passed in.
*/
@Override
protected void onInit() throws Exception {
super.onInit();
this.executor.afterPropertiesSet();
};
/**
* Executes the Stored procedure, delegates to executeStoredProcedure(...).
* Any return values from the Stored procedure are ignored.
*
* Return values are logged at debug level, though.
*/
@Override
protected void handleMessageInternal(Message<?> message) throws MessageRejectedException, MessageHandlingException,
MessageDeliveryException {
Map<String, Object> resultMap = executor.executeStoredProcedure(message);
if (logger.isDebugEnabled()) {
if (resultMap != null && !resultMap.isEmpty()) {
logger.debug(String.format("The StoredProcMessageHandler ignores return "
+ "values, but the called Stored Procedure '%s' returned the "
+ "following data: '%s'", executor.getStoredProcedureName(), resultMap));
}
}
}
//~~~~~Setters for Properties~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* For fully supported databases, the underlying {@link SimpleJdbcCall} can
* retrieve the parameter information for the to be invoked Stored Procedure
* from the JDBC Meta-data. However, if the used database does not support
* meta data lookups or if you like to provide customized parameter definitions,
* this flag can be set to 'true'. It defaults to 'false'.
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
*/
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
/**
* If you database system is not fully supported by Spring and thus obtaining
* parameter definitions from the JDBC Meta-data is not possible, you must define
* the {@link SqlParameter} explicitly.
*/
public void setSqlParameters(List<SqlParameter> sqlParameters) {
this.executor.setSqlParameters(sqlParameters);
}
/**
* Provides the ability to set a custom {@link SqlParameterSourceFactory}.
* Keep in mind that if {@link ProcedureParameter} are set explicitly and
* you would like to provide a custom {@link SqlParameterSourceFactory},
* then you must provide an instance of {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* If not the SqlParameterSourceFactory will be replaced the default
* {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.executor.setSqlParameterSourceFactory(sqlParameterSourceFactory);
}
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import java.sql.CallableStatement;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.util.Assert;
/**
* @author Gunnar Hillert
*
* @since 2.1
*/
public class StoredProcOutboundGateway extends AbstractReplyProducingMessageHandler implements InitializingBean {
private final StoredProcExecutor executor;
private volatile boolean expectSingleResult = false;
/**
* Constructor taking {@link DataSource} from which the DB Connection can be
* obtained and the name of the stored procedure or function to
* execute to retrieve new rows.
*
* @param dataSource used to create a {@link SimpleJdbcTemplate}
* @param storedProcedureName
*/
public StoredProcOutboundGateway(DataSource dataSource, String storedProcedureName) {
Assert.notNull(dataSource, "dataSource must not be null.");
Assert.hasText(storedProcedureName, "storedProcedureName must not be null and cannot be empty.");
this.executor = new StoredProcExecutor(dataSource, storedProcedureName);
this.executor.setUsePayloadAsParameterSource(true);
}
/**
* Verifies parameters, sets the parameters on {@link SimpleJdbcCallOperations}
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* when {@link ProcedureParameter} are passed in.
*/
@Override
protected void onInit() {
super.onInit();
this.executor.afterPropertiesSet();
};
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Map<String, Object> resultMap = executor.executeStoredProcedure(requestMessage);
final Object payload;
if (resultMap.isEmpty()) {
payload = null;
} else {
if (this.expectSingleResult && resultMap.size() == 1) {
payload = resultMap.values().iterator().next();
} else if (this.expectSingleResult && resultMap.size() > 1) {
throw new MessagingException(
"Stored Procedure/Function call returned more than "
+ "1 result object and expectSingleResult was 'true'. ");
} else {
payload = resultMap;
}
}
return MessageBuilder.withPayload(payload).copyHeaders(requestMessage.getHeaders()).build();
}
/**
* Explicit declarations are necessary if the database you use is not a
* Spring-supported database. Currently Spring supports metadata lookup of
* stored procedure calls for the following databases:
*
* <ul>
* <li>Apache Derby</li>
* <li>DB2</li>
* <li>MySQL</li>
* <li>Microsoft SQL Server</li>
* <li>Oracle</li>
* <li>Sybase</li>
* <li>PostgreSQL</li>
* </ul>
* , ,
* We also support metadata lookup of stored functions for the following
* databases:
*
* <ul>
* <li>MySQL</li>
* <li>Microsoft SQL Server</li>
* <li>Oracle</li>
* <li>PostgreSQL</li>
* </ul>
*
* See also: {@link http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/jdbc.html}
*/
public void setSqlParameters(List<SqlParameter> sqlParameters) {
this.executor.setSqlParameters(sqlParameters);
}
/**
* Does your stored procedure return one or more result sets? If so, you
* can use the provided method for setting the respective Rowmappers.
*/
public void setReturningResultSetRowMappers(
Map<String, RowMapper<?>> returningResultSetRowMappers) {
this.executor.setReturningResultSetRowMappers(returningResultSetRowMappers);
}
/**
*
* @param ignoreColumnMetaData
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
*
* @param returnValueRequired
*/
public void setReturnValueRequired(boolean returnValueRequired) {
this.executor.setReturnValueRequired(returnValueRequired);
}
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
public void setIsFunction(boolean isFunction) {
this.executor.setFunction(isFunction);
}
/**
* This parameter indicates that only one result object shall be returned from
* the Stored Procedure/Function Call. If set to true, a resultMap that contains
* only 1 element, will have that 1 element extracted and returned as payload.
*
* If the resultMap contains more than 1 element and expectSingleResult is true,
* then a {@link MessagingException} is thrown.
*
* Otherwise the complete resultMap is returned as the {@link Message} payload.
*
* Important Note: Several databases such as H2 are not fully supported.
* The H2 database, for example, does not fully support the {@link CallableStatement}
* semantics and when executing function calls against H2, a result list is
* returned rather than a single value.
*
* Therefore, even if you set expectSingleResult = true, you may end up with
* a collection being returned.
*
* @param expectSingleResult
*/
public void setExpectSingleResult(boolean expectSingleResult) {
this.expectSingleResult = expectSingleResult;
}
}

View File

@@ -0,0 +1,230 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import java.sql.CallableStatement;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.util.Assert;
/**
* A polling channel adapter that creates messages from the payload returned by
* executing a stored procedure or Sql function. Optionally an update can be executed
* after the execution of the Stored Procedure or Function in order to update
* processed rows.
*
* @author Gunnar Hillert
* @since 2.1
*/
public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport implements MessageSource<Object> {
final StoredProcExecutor executor;
private volatile boolean expectSingleResult = false;
/**
* Constructor taking {@link DataSource} from which the DB Connection can be
* obtained and the stored procedure name to execute.
*
* @param dataSource used to create a {@link SimpleJdbcCall}
* @param storedProcedureName Name of the Stored Procedure of Function to execute
*/
public StoredProcPollingChannelAdapter(DataSource dataSource, String storedProcedureName) {
Assert.notNull(dataSource, "dataSource must not be null.");
Assert.hasText(storedProcedureName, "storedProcedureName must not be null and cannot be empty.");
this.executor = new StoredProcExecutor(dataSource, storedProcedureName);
}
@Override
protected void onInit() throws Exception {
super.onInit();
this.executor.afterPropertiesSet();
}
/**
* Executes the query. If a query result set contains one or more rows, the
* Message payload will contain either a List of Maps for each row or, if a
* RowMapper has been provided, the values mapped from those rows. If the
* query returns no rows, this method will return <code>null</code>.
*/
public Message<Object> receive() {
Object payload = poll();
if (payload == null) {
return null;
}
return MessageBuilder.withPayload(payload).build();
}
/**
* Execute the select query and the update query if provided. Returns the
* rows returned by the select query. If a RowMapper has been provided, the
* mapped results are returned.
*/
private Object poll() {
final Object payload;
Map<String, ?> resultMap = doPoll();
if (resultMap.isEmpty()) {
payload = null;
} else {
if (this.expectSingleResult && resultMap.size() == 1) {
payload = resultMap.values().iterator().next();
} else if (this.expectSingleResult && resultMap.size() > 1) {
throw new MessagingException(
"Stored Procedure/Function call returned more than "
+ "1 result object and expectSingleResult was 'true'. ");
} else {
payload = resultMap;
}
}
return payload;
}
protected Map<String, ?> doPoll() {
Map<String, Object> payload = this.executor.executeStoredProcedure();
return payload;
}
public String getComponentType(){
return "stored-proc:inbound-channel-adapter";
}
/**
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.executor.setSqlParameterSourceFactory(sqlParameterSourceFactory);
}
/**
* Explicit declarations are necessary if the database you use is not a
* Spring-supported database. Currently Spring supports metadata lookup of
* stored procedure calls for the following databases:
*
* <ul>
* <li>Apache Derby</li>
* <li>DB2</li>
* <li>MySQL</li>
* <li>Microsoft SQL Server</li>
* <li>Oracle</li>
* <li>Sybase</li>
* <li>PostgreSQL</li>
* </ul>
* , ,
* We also support metadata lookup of stored functions for the following
* databases:
*
* <ul>
* <li>MySQL</li>
* <li>Microsoft SQL Server</li>
* <li>Oracle</li>
* <li>PostgreSQL</li>
* </ul>
*
* See also: {@link http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/jdbc.html}
*/
public void setSqlParameters(List<SqlParameter> sqlParameters) {
this.executor.setSqlParameters(sqlParameters);
}
/**
* Does your stored procedure return one or more result sets? If so, you
* can use the provided method for setting the respective Rowmappers.
*/
public void setReturningResultSetRowMappers(
Map<String, RowMapper<?>> returningResultSetRowMappers) {
this.executor.setReturningResultSetRowMappers(returningResultSetRowMappers);
}
/**
*
* @param ignoreColumnMetaData
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
*
* @param returnValueRequired
*/
public void setReturnValueRequired(boolean returnValueRequired) {
this.executor.setReturnValueRequired(returnValueRequired);
}
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
/**
* Indicates whether a Stored Procedure or a Function is being executed.
* The default value is false.
*
* @param isFunction If set to true an Sql Function is executed rather than a Stored Procedure.
*/
public void setFunction(boolean isFunction) {
this.executor.setFunction(isFunction);
}
/**
* This parameter indicates that only one result object shall be returned from
* the Stored Procedure/Function Call. If set to true, a resultMap that contains
* only 1 element, will have that 1 element extracted and returned as payload.
*
* If the resultMap contains more than 1 element and expectSingleResult is true,
* then a {@link MessagingException} is thrown.
*
* Otherwise the complete resultMap is returned as the {@link Message} payload.
*
* Important Note: Several databases such as H2 are not fully supported.
* The H2 database, for example, does not fully support the {@link CallableStatement}
* semantics and when executing function calls against H2, a result list is
* returned rather than a single value.
*
* Therefore, even if you set expectSingleResult = true, you may end up with
* a collection being returned.
*
* @param expectSingleResult
*/
public void setExpectSingleResult(boolean expectSingleResult) {
this.expectSingleResult = expectSingleResult;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -19,6 +19,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.JdbcMessageHandler;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -41,7 +42,7 @@ public class JdbcMessageHandlerParser extends AbstractOutboundChannelAdapterPars
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.integration.jdbc.JdbcMessageHandler");
.genericBeanDefinition(JdbcMessageHandler.class);
String dataSourceRef = element.getAttribute("data-source");
String jdbcOperationsRef = element.getAttribute("jdbc-operations");
boolean refToDataSourceSet = StringUtils.hasText(dataSourceRef);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -18,6 +18,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.JdbcMessageStore;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -35,7 +36,7 @@ public class JdbcMessageStoreParser extends AbstractBeanDefinitionParser {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.integration.jdbc.JdbcMessageStore");
.genericBeanDefinition(JdbcMessageStore.class);
String dataSourceRef = element.getAttribute("data-source");
String simpleJdbcOperationsRef = element.getAttribute("jdbc-operations");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
*
* @author Jonas Partner
* @author Dave Syer
* @author Gunnar Hillert
*
* @since 2.0
*/
public class JdbcNamespaceHandler extends AbstractIntegrationNamespaceHandler {
@@ -32,6 +34,9 @@ public class JdbcNamespaceHandler extends AbstractIntegrationNamespaceHandler {
registerBeanDefinitionParser("outbound-channel-adapter", new JdbcMessageHandlerParser());
registerBeanDefinitionParser("outbound-gateway", new JdbcOutboundGatewayParser());
registerBeanDefinitionParser("message-store", new JdbcMessageStoreParser());
registerBeanDefinitionParser("stored-proc-outbound-channel-adapter", new StoredProcMessageHandlerParser());
registerBeanDefinitionParser("stored-proc-inbound-channel-adapter", new StoredProcPollingChannelAdapterParser());
registerBeanDefinitionParser("stored-proc-outbound-gateway", new StoredProcOutboundGatewayParser());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -17,6 +17,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.JdbcOutboundGateway;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -58,7 +59,7 @@ public class JdbcOutboundGatewayParser extends AbstractConsumerEndpointParser {
return null;
}
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.integration.jdbc.JdbcOutboundGateway");
.genericBeanDefinition(JdbcOutboundGateway.class);
if (refToDataSourceSet) {
builder.addConstructorArgReference(dataSourceRef);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,15 @@
package org.springframework.integration.jdbc.config;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.JdbcPollingChannelAdapter;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for {@link org.springframework.integration.jdbc.JdbcPollingChannelAdapter}.
@@ -46,7 +46,7 @@ public class JdbcPollingChannelAdapterParser extends AbstractPollingInboundChann
protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.integration.jdbc.JdbcPollingChannelAdapter");
.genericBeanDefinition(JdbcPollingChannelAdapter.class);
String dataSourceRef = element.getAttribute("data-source");
String jdbcOperationsRef = element.getAttribute("jdbc-operations");
boolean refToDataSourceSet = StringUtils.hasText(dataSourceRef);

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import java.sql.Types;
import org.springframework.util.Assert;
/**
* This Enumeration provides a handy wrapper around {@link Types}. This makes it
* possible to look up String representation of the enum constant's name, and thus
* looking up the respective JDBC Type (int-value).
*
* @author Gunnar Hillert
* @since 2.1
*
*/
public enum JdbcTypesEnum {
BIT(Types.BIT),
TINYINT(Types.TINYINT),
SMALLINT(Types.SMALLINT),
INTEGER(Types.INTEGER),
BIGINT(Types.BIGINT),
FLOAT(Types.FLOAT),
REAL(Types.REAL),
DOUBLE(Types.DOUBLE),
NUMERIC(Types.NUMERIC),
DECIMAL(Types.DECIMAL),
CHAR(Types.CHAR),
VARCHAR(Types.VARCHAR),
LONGVARCHAR(Types.LONGVARCHAR),
DATE(Types.DATE),
TIME(Types.TIME),
TIMESTAMP(Types.TIMESTAMP),
BINARY(Types.BINARY),
VARBINARY(Types.VARBINARY),
LONGVARBINARY(Types.LONGVARBINARY),
NULL(Types.NULL),
OTHER(Types.OTHER),
JAVA_OBJECT(Types.JAVA_OBJECT),
DISTINCT(Types.DISTINCT),
STRUCT(Types.STRUCT),
ARRAY(Types.ARRAY),
BLOB(Types.BLOB),
CLOB(Types.CLOB),
REF(Types.REF),
DATALINK(Types.DATALINK),
BOOLEAN(Types.BOOLEAN),
ROWID(Types.ROWID),
NCHAR(Types.NCHAR),
NVARCHAR(Types.NVARCHAR),
LONGNVARCHAR(Types.LONGNVARCHAR),
NCLOB(Types.NCLOB),
SQLXML(Types.SQLXML);
private int code;
/** Constructor */
JdbcTypesEnum(int code) {
this.code = code;
}
/**
* Get the numerical representation of the JDBC Type enum. The numerical value
* matches exactly the equivalent value in {@link Types}
*
* @return The numerical representation of the constant.
*/
public int getCode() {
return this.code;
}
/**
* Retrieves the matching enum constant for a provided String representation
* of the SQL Types. The provided name must match exactly the identifier as
* used to declare the enum constant.
*
* @param sqlTypeAsString Name of the enum to convert. Must be not null and not empty.
* @return The enumeration that matches. Returns Null of no match was found.
*
*/
public static JdbcTypesEnum convertToJdbcTypesEnum(String sqlTypeAsString) {
Assert.hasText(sqlTypeAsString, "Parameter sqlTypeAsString, must not be null nor empty");
for (JdbcTypesEnum jdbcType : JdbcTypesEnum.values()) {
if (jdbcType.name().equalsIgnoreCase(sqlTypeAsString)) {
return jdbcType;
}
}
return null;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.StoredProcMessageHandler;
import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcMessageHandlerParser extends AbstractOutboundChannelAdapterParser {
protected boolean shouldGenerateId() {
return false;
}
protected boolean shouldGenerateIdAsFallback() {
return true;
}
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(StoredProcMessageHandler.class);
String dataSourceRef = element.getAttribute("data-source");
String storedProcedureName = element.getAttribute("stored-procedure-name");
builder.addConstructorArgReference(dataSourceRef);
builder.addConstructorArgValue(storedProcedureName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-column-meta-data");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
if (!procedureParameterList.isEmpty()) {
builder.addPropertyValue("procedureParameters", procedureParameterList);
}
if (!sqlParameterDefinitionList.isEmpty()) {
builder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
}
return builder.getBeanDefinition();
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.StoredProcOutboundGateway;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointParser {
protected boolean shouldGenerateId() {
return false;
}
protected boolean shouldGenerateIdAsFallback() {
return true;
}
@Override
protected BeanDefinitionBuilder parseHandler(Element gatewayElement, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(StoredProcOutboundGateway.class);
String dataSourceRef = gatewayElement.getAttribute("data-source");
String storedProcedureName = gatewayElement.getAttribute("stored-procedure-name");
builder.addConstructorArgReference(dataSourceRef);
builder.addConstructorArgValue(storedProcedureName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "is-function");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "ignore-column-meta-data");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "expect-single-result");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "return-value-required");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(gatewayElement, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(gatewayElement, parserContext);
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(gatewayElement, parserContext);
if (!procedureParameterList.isEmpty()) {
builder.addPropertyValue("procedureParameters", procedureParameterList);
}
if (!sqlParameterDefinitionList.isEmpty()) {
builder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
}
if (!returningResultsetMap.isEmpty()) {
builder.addPropertyValue("returningResultSetRowMappers", returningResultsetMap);
}
String replyChannel = gatewayElement.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
builder.addPropertyReference("outputChannel", replyChannel);
}
return builder;
}
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
}
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import java.sql.Types;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
*
*
* @author Gunnar Hillert
* @since 2.1
*
*/
public final class StoredProcParserUtils {
private static final Log logger = LogFactory
.getLog(StoredProcParserUtils.class);
/** Prevent instantiation. */
private StoredProcParserUtils() {
throw new AssertionError();
}
/**
*
* @param gatewayElement
* @param parserContext
* @return
*/
public static ManagedList<BeanDefinition> getSqlParameterDefinitionBeanDefinitions(
Element storedProcComponent, ParserContext parserContext) {
List<Element> sqlParameterDefinitionChildElements = DomUtils.getChildElementsByTagName(storedProcComponent, "sql-parameter-definition");
ManagedList<BeanDefinition> sqlParameterList = new ManagedList<BeanDefinition>();
for (Element childElement : sqlParameterDefinitionChildElements) {
String name = childElement.getAttribute("name");
String sqlType = childElement.getAttribute("type");
String direction = childElement.getAttribute("direction");
String scale = childElement.getAttribute("scale");
final BeanDefinitionBuilder parameterBuilder;
if ("OUT".equalsIgnoreCase(direction)) {
parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlOutParameter.class);
} else if ("INOUT".equalsIgnoreCase(direction)) {
parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlInOutParameter.class);
} else {
parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlParameter.class);
}
if (StringUtils.hasText(name)) {
parameterBuilder.addConstructorArgValue(name);
} else {
parserContext.getReaderContext().error(
"The 'name' attribute must be set for the Sql parameter element.", storedProcComponent);
}
if (StringUtils.hasText(sqlType)) {
JdbcTypesEnum jdbcTypeEnum = JdbcTypesEnum.convertToJdbcTypesEnum(sqlType);
if (jdbcTypeEnum != null) {
parameterBuilder.addConstructorArgValue(jdbcTypeEnum.getCode());
} else {
parameterBuilder.addConstructorArgValue(sqlType);
}
} else {
parameterBuilder.addConstructorArgValue(Types.VARCHAR);
}
if (StringUtils.hasText(scale)) {
parameterBuilder.addConstructorArgValue(new TypedStringValue(scale, Integer.class));
}
sqlParameterList.add(parameterBuilder.getBeanDefinition());
}
return sqlParameterList;
}
/**
*
* @param gatewayElement
* @param parserContext
* @return
*/
public static ManagedList<BeanDefinition> getProcedureParameterBeanDefinitions(
Element storedProcComponent, ParserContext parserContext) {
ManagedList<BeanDefinition> procedureParameterList = new ManagedList<BeanDefinition>();
List<Element> parameterChildElements = DomUtils
.getChildElementsByTagName(storedProcComponent, "parameter");
for (Element childElement : parameterChildElements) {
BeanDefinitionBuilder parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(ProcedureParameter.class);
String name = childElement.getAttribute("name");
String expression = childElement.getAttribute("expression");
String value = childElement.getAttribute("value");
String type = childElement.getAttribute("type");
if (StringUtils.hasText(name)) {
parameterBuilder.addPropertyValue("name", name);
} else {
parserContext
.getReaderContext()
.error("The 'name' attribute must be set for the Stored Procedure parameter element.",
storedProcComponent);
}
if (StringUtils.hasText(expression)) {
parameterBuilder.addPropertyValue("expression", expression);
}
if (StringUtils.hasText(value)) {
if (!StringUtils.hasText(type)) {
logger.info(String
.format("Type attribute not set for Store Procedure parameter '%s'. Defaulting to 'java.lang.String'.",
value));
parameterBuilder.addPropertyValue("value",
new TypedStringValue(value, String.class));
} else {
parameterBuilder.addPropertyValue("value",
new TypedStringValue(value, type));
}
}
procedureParameterList.add(parameterBuilder.getBeanDefinition());
}
return procedureParameterList;
}
/**
*
* @param gatewayElement
* @param parserContext
* @return
*/
public static ManagedMap<String, BeanDefinition> getReturningResultsetBeanDefinitions(
Element storedProcComponent, ParserContext parserContext) {
List<Element> returningResultsetChildElements = DomUtils.getChildElementsByTagName(storedProcComponent, "returning-resultset");
ManagedMap<String, BeanDefinition> returningResultsetMap = new ManagedMap<String, BeanDefinition>();
for (Element childElement : returningResultsetChildElements) {
String name = childElement.getAttribute("name");
String rowMapperAsString = childElement.getAttribute("row-mapper");
if (!StringUtils.hasText(name)) {
parserContext.getReaderContext().error(
"The 'name' attribute must be set for the 'returning-resultset' element.", storedProcComponent);
}
if (!StringUtils.hasText(rowMapperAsString)) {
parserContext.getReaderContext().error(
"The 'row-mapper' attribute must be set for the 'returning-resultset' element.", storedProcComponent);
}
BeanDefinitionBuilder rowMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(rowMapperAsString);
returningResultsetMap.put(name, rowMapperBuilder.getBeanDefinition());
}
return returningResultsetMap;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.jdbc.StoredProcPollingChannelAdapter;
import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcPollingChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
protected boolean shouldGenerateId() {
return false;
}
protected boolean shouldGenerateIdAsFallback() {
return true;
}
@Override
protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(StoredProcPollingChannelAdapter.class);
String dataSourceRef = element.getAttribute("data-source");
String storedProcedureName = element.getAttribute("stored-procedure-name");
builder.addConstructorArgReference(dataSourceRef);
builder.addConstructorArgValue(storedProcedureName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-column-meta-data");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "return-value-required");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expect-single-result");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "function");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
if (!procedureParameterList.isEmpty()) {
builder.addPropertyValue("procedureParameters", procedureParameterList);
}
if (!sqlParameterDefinitionList.isEmpty()) {
builder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
}
if (!returningResultsetMap.isEmpty()) {
builder.addPropertyValue("returningResultSetRowMappers", returningResultsetMap);
}
return builder.getBeanDefinition();
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc.storedproc;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.Assert;
/**
* Abstraction of Procedure parameters allowing to provide static parameters
* and SpEl Expression based parameters.
*
* @author Gunnar Hillert
* @since 2.1
*
*/
public class ProcedureParameter {
private String name;
private Object value;
private String expression;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return this.value;
}
public void setValue(Object value) {
this.value = value;
}
public String getExpression() {
return this.expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
/**
* Instantiates a new Procedure Parameter.
*
* @param name Name of the procedure parameter, must not be null or empty
* @param value If null, the expression property must be set
* @param expression If null, the value property must be set
*/
public ProcedureParameter(String name, Object value, String expression) {
super();
Assert.hasText(name, "Please provide a name.");
this.name = name;
this.value = value;
this.expression = expression;
}
/**
* Default constructor.
*/
public ProcedureParameter() {
super();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ProcedureParameter [name=").append(this.name)
.append(", value=").append(this.value)
.append(", expression=").append(this.expression)
.append("]");
return builder.toString();
}
/**
* Utility method that converts a Collection of {@link ProcedureParameter} to
* a Map containing only expression parameters.
*
* @param procedureParameters Must not be null.
* @return Map containing only the Expression bound parameters. Will never be null.
*/
public static Map<String, String> convertExpressions(Collection<ProcedureParameter> procedureParameters) {
Assert.notNull(procedureParameters, "The Collection of procedureParameters must not be null.");
Map<String, String> staticParameters = new HashMap<String, String>();
for (ProcedureParameter parameter : procedureParameters) {
if (parameter.getExpression() != null) {
staticParameters.put(parameter.getName(), parameter.getExpression());
}
}
return staticParameters;
}
/**
* Utility method that converts a Collection of {@link ProcedureParameter} to
* a Map containing only static parameters.
*
* @param procedureParameters Must not be null.
* @return Map containing only the static parameters. Will never be null.
*/
public static Map<String, Object> convertStaticParameters(Collection<ProcedureParameter> procedureParameters) {
Map<String, Object> staticParameters = new HashMap<String, Object>();
for (ProcedureParameter parameter : procedureParameters) {
if (parameter.getValue() != null) {
staticParameters.put(parameter.getName(), parameter.getValue());
}
}
return staticParameters;
}
}

View File

@@ -551,4 +551,609 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="stored-proc-outbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines an outbound Channel Adapter for updating a
database using stored procedures.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0"
maxOccurs="1" />
<xsd:element name="sql-parameter-definition" minOccurs="0"
maxOccurs="unbounded" type="sqlParameterDefinitionType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded"
type="parameterSubElementType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Provides a mechanism to provide stored procedure
parameters.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attributeGroup ref="coreStoredProcComponentAttributes"/>
<xsd:attribute name="sql-parameter-source-factory"
type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. The input is the whole
outgoing message. The
default factory creates a bean
property parameter source so the query can specify named
parameters like :payload and :headers[foo].
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.jdbc.SqlParameterSourceFactory" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Channel from which messages will be output.
When a message is sent to this channel it will
cause the query
to be executed.
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation>
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="return-value-required" default="false">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stored-proc-outbound-gateway">
<xsd:annotation>
<xsd:documentation>
Defines an Outbound Channel Gateway for updating a database using
a stored procedure. The response of the stored procedure is used
to populate the Message for the reply channel.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:sequence>
<xsd:element name="sql-parameter-definition" minOccurs="0"
maxOccurs="unbounded" type="sqlParameterDefinitionType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
generally need not be declared as for those
databases the type information can be
retrieved from the JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded"
type="parameterSubElementType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Provides a mechanism to provide stored procedure
parameters. Parameters can be either static
or provided using a SpEL Expression.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="returning-resultset" minOccurs="0"
maxOccurs="unbounded" type="returningResultSetRowMappersType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Storeed procedured may return multiple resultsets.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:sequence>
<xsd:attributeGroup ref="coreStoredProcComponentAttributes"/>
<xsd:attribute name="sql-parameter-source-factory"
type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. The input is the whole
outgoing message. The
default factory creates a bean
property parameter source so the query can specify named
parameters like :payload and :headers[foo].
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.jdbc.SqlParameterSourceFactory" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="is-function" default="false">
<xsd:annotation>
<xsd:documentation>
If "true", a SQL Function is called. In that case
the "stored-procedure-name" attribute defines
the name of the called function.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="expect-single-result" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
This parameter indicates that only one result object shall be returned from
the Stored Procedure/Function Call. If set to true and the result map
from the Stored Procedure/Function Call contains only 1 element,
then that 1 element is extracted and returned as payload.
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
payload.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
The H2 database, for example, does not fully support the CallableStatement
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
you may end up with a collection being returned.
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="request-channel" type="xsd:string"
use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="request-timeout" type="xsd:string" />
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation>
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="return-value-required" default="false">
<xsd:annotation>
<xsd:documentation>
Indicates whether this procedure's return value
should be included.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stored-proc-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines an inbound Channel Adapter for polling a
database using a stored procedure or function.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0"
maxOccurs="1" />
<xsd:element name="sql-parameter-definition" minOccurs="0"
maxOccurs="unbounded" type="sqlParameterDefinitionType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded"
type="parameterSubElementType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Provides a mechanism to provide stored procedure
parameters.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="returning-resultset" minOccurs="0"
maxOccurs="unbounded" type="returningResultSetRowMappersType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Storeed procedured may return multiple resultsets.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attributeGroup ref="coreStoredProcComponentAttributes"/>
<xsd:attribute name="is-function" default="false">
<xsd:annotation>
<xsd:documentation>
If "true", a SQL Function is called. In that case
the "stored-procedure-name" attribute defines
the name of the called function.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="expect-single-result" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
This parameter indicates that only one result object shall be returned from
the Stored Procedure/Function Call. If set to true and the result map
from the Stored Procedure/Function Call contains only 1 element,
then that 1 element is extracted and returned as payload.
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
payload.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
The H2 database, for example, does not fully support the CallableStatement
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
you may end up with a collection being returned.
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Channel to which polled messages will be send. If the stored
procedure or function does not return any data, the payload
of the Message will be Null.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="coreStoredProcComponentAttributes">
<xsd:attribute name="id" type="xsd:string" use="optional" />
<xsd:attribute name="stored-procedure-name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The name of the stored procedure. If the "is-function"
attribute is "true", this attributes specifies the
function name.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="data-source" type="xsd:string" use="required" >
<xsd:annotation>
<xsd:documentation>
Reference to a data source to use to access
the database.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="javax.sql.DataSource" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" type="xsd:string" default="true" use="optional">
<xsd:annotation>
<xsd:documentation>
Flag to indicate that the poller should start automatically
on startup (default true).
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="ignore-column-meta-data" default="false" use="optional">
<xsd:annotation>
<xsd:documentation>
If true, the JDBC parameter definitions for the stored procedure
are not automatically derived from the underlying JDBC connection. In
that case you must specify all Sql parameter definitions explicitly
using the 'sql-parameter-definition' sub-element.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:complexType name="parameterSubElementType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of stored procedure or function parameter.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="value" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The value of the parameter. Either this or the 'expression'
attribute must be provided.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="type" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The type of the value used. If nothing is provided this attribute
will default to java.lang.String. This attribute is not used
when the 'expression' attribute is used instead.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Expression to be evaluated to produce a value for the header.
Either this or the 'value' attribute must be provided.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="returningResultSetRowMappersType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the under which the resultset will be returned.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="row-mapper" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The fully qualified class name of the row mapper.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="sqlParameterDefinitionType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the Sql parameter.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="direction" use="optional" default="IN">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the direction of the Sql parameter definition. Defaults
to 'IN'. If your procedure is returning ResultSets, please
use the 'returning-resultset' element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="sqlTypeDirection xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="type">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Sql type used for this Sql parameter defintion. Will translate
into the integer value as defined by java.sql.Types. Alternatively
you can provide the integer value as well. If this attribute is
not explicitly set, then it will default to 'VARCHAR'.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="sqlType xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="scale" type="xsd:integer" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scale of the Sql parameter. Only used for numeric and decimal
parameters.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="sqlType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="VARCHAR"/>
<xsd:enumeration value="ARRAY"/>
<xsd:enumeration value="BIGINT"/>
<xsd:enumeration value="BINARY"/>
<xsd:enumeration value="BIT"/>
<xsd:enumeration value="BLOB"/>
<xsd:enumeration value="BOOLEAN"/>
<xsd:enumeration value="CHAR"/>
<xsd:enumeration value="CLOB"/>
<xsd:enumeration value="DATALINK"/>
<xsd:enumeration value="DATE"/>
<xsd:enumeration value="DECIMAL"/>
<xsd:enumeration value="DISTINCT"/>
<xsd:enumeration value="DOUBLE"/>
<xsd:enumeration value="FLOAT"/>
<xsd:enumeration value="INTEGER"/>
<xsd:enumeration value="JAVA_OBJECT"/>
<xsd:enumeration value="LONGVARBINARY"/>
<xsd:enumeration value="LONGNVARCHAR"/>
<xsd:enumeration value="LONGVARCHAR"/>
<xsd:enumeration value="NCHAR"/>
<xsd:enumeration value="NCLOB"/>
<xsd:enumeration value="NULL"/>
<xsd:enumeration value="NUMERIC"/>
<xsd:enumeration value="NVARCHAR"/>
<xsd:enumeration value="OTHER"/>
<xsd:enumeration value="REAL"/>
<xsd:enumeration value="REF"/>
<xsd:enumeration value="ROWID"/>
<xsd:enumeration value="SMALLINT"/>
<xsd:enumeration value="SQLXML"/>
<xsd:enumeration value="STRUCT"/>
<xsd:enumeration value="TIME"/>
<xsd:enumeration value="TIMESTAMP"/>
<xsd:enumeration value="TINYINT"/>
<xsd:enumeration value="VARBINARY"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="sqlTypeDirection">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="IN"/>
<xsd:enumeration value="OUT"/>
<xsd:enumeration value="INOUT"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -1,11 +0,0 @@
log4j.rootCategory=WARN, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
log4j.category.org.springframework=WARN
# log4j.category.org.springframework.integration=DEBUG
# log4j.category.org.springframework.integration.jdbc=DEBUG
log4j.category.org.springframework.jdbc=DEBUG

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import java.util.Map;
import org.junit.After;
@@ -29,8 +31,6 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*/

View File

@@ -36,9 +36,9 @@
<int:logging-channel-adapter channel="output" />
<service-activator id="service-activator"
input-channel="input" output-channel="output"
input-channel="input" output-channel="output"
xmlns="http://www.springframework.org/schema/integration">
<beans:bean
<beans:bean
class="org.springframework.integration.jdbc.JdbcMessageStoreChannelIntegrationTests$Service" />
<poller fixed-rate="200">
<advice-chain>

View File

@@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.channel.QueueChannel;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,10 @@
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@@ -35,10 +39,6 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* @author Jonas Partner
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at

View File

@@ -0,0 +1,243 @@
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
public class StoredProcExecutorTest {
@Test
public void testStoredProcExecutorWithNullDataSource() {
try {
new StoredProcExecutor(null, "storedProcedureName");
} catch (IllegalArgumentException e) {
assertEquals("dataSource must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testStoredProcExecutorWithNullProcedureName() {
DataSource datasource = mock(DataSource.class);
try {
new StoredProcExecutor(datasource, null);
} catch (IllegalArgumentException e) {
assertEquals("storedProcedureName must not be null and cannot be empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testStoredProcExecutorWithEmptyProcedureName() {
DataSource datasource = mock(DataSource.class);
try {
new StoredProcExecutor(datasource, " ");
} catch (IllegalArgumentException e) {
assertEquals("storedProcedureName must not be null and cannot be empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithNullMap() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
try {
storedProcExecutor.setReturningResultSetRowMappers(null);
} catch (IllegalArgumentException e) {
assertEquals("returningResultSetRowMappers must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithMapContainingNullValues() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
Map<String, RowMapper<?>> rowmappers = new HashMap<String, RowMapper<?>>();
rowmappers.put("results", null);
try {
storedProcExecutor.setReturningResultSetRowMappers(rowmappers);
} catch (IllegalArgumentException e) {
assertEquals("The provided map cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithEmptyMap() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
Map<String, RowMapper<?>> rowmappers = new HashMap<String, RowMapper<?>>();
storedProcExecutor.setReturningResultSetRowMappers(rowmappers);
//Should Successfully finish
}
@Test
public void testSetSqlParameterSourceFactoryWithNullParameter() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
try {
storedProcExecutor.setSqlParameterSourceFactory(null);
} catch (IllegalArgumentException e) {
assertEquals("sqlParameterSourceFactory must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithNullValueInList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<SqlParameter> sqlParameters = new ArrayList<SqlParameter>();
sqlParameters.add(null);
try {
storedProcExecutor.setSqlParameters(sqlParameters);
} catch (IllegalArgumentException e) {
assertEquals("The provided list (sqlParameters) cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithEmptyList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<SqlParameter> sqlParameters = new ArrayList<SqlParameter>();
try {
storedProcExecutor.setSqlParameters(sqlParameters);
} catch (IllegalArgumentException e) {
assertEquals("sqlParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithNullList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
try {
storedProcExecutor.setSqlParameters(null);
} catch (IllegalArgumentException e) {
assertEquals("sqlParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithNullValueInList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
procedureParameters.add(null);
try {
storedProcExecutor.setProcedureParameters(procedureParameters);
} catch (IllegalArgumentException e) {
assertEquals("The provided list (procedureParameters) cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithEmptyList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
try {
storedProcExecutor.setProcedureParameters(procedureParameters);
} catch (IllegalArgumentException e) {
assertEquals("procedureParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithNullList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
try {
storedProcExecutor.setProcedureParameters(null);
} catch (IllegalArgumentException e) {
assertEquals("procedureParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.integration.jdbc.storedproc.User;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
/**
* @author Gunnar Hillert
*/
public class StoredProcMessageHandlerDerbyIntegrationTests {
private static Log LOGGER = LogFactory.getLog(StoredProcMessageHandlerDerbyIntegrationTests.class);
private EmbeddedDatabase embeddedDatabase;
private JdbcTemplate jdbcTemplate;
@Before
public void setUp() throws SQLException {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder.setType(EmbeddedDatabaseType.DERBY);
builder.addScript("classpath:derby-stored-procedures.sql");
this.embeddedDatabase = builder.build();
this.jdbcTemplate = new JdbcTemplate(this.embeddedDatabase);
}
@After
public void tearDown() {
this.embeddedDatabase.shutdown();
}
@Test
public void testDerbyStoredProcedureInsertWithDefaultSqlSource() {
StoredProcMessageHandler messageHandler = new StoredProcMessageHandler(this.embeddedDatabase, "CREATE_USER");
messageHandler.afterPropertiesSet();
MessageBuilder<User> message = MessageBuilder.withPayload(new User("username", "password", "email"));
messageHandler.handleMessage(message.build());
Map<String, Object> map = jdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME=?", "username");
assertEquals("Wrong username", "username", map.get("USERNAME"));
assertEquals("Wrong password", "password", map.get("PASSWORD"));
assertEquals("Wrong email", "email", map.get("EMAIL"));
}
@Test
public void testDerbyStoredProcedureInsertWithExpression() {
StoredProcMessageHandler messageHandler = new StoredProcMessageHandler(this.embeddedDatabase, "CREATE_USER");
final List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
procedureParameters.add(new ProcedureParameter("username", null, "payload.username.toUpperCase()"));
procedureParameters.add(new ProcedureParameter("password", null, "payload.password.toUpperCase()"));
procedureParameters.add(new ProcedureParameter("email", null, "payload.email.toUpperCase()"));
messageHandler.setProcedureParameters(procedureParameters);
messageHandler.afterPropertiesSet();
MessageBuilder<User> message = MessageBuilder.withPayload(new User("Eric.Cartman", "c4rtm4n", "eric@cartman.com"));
messageHandler.handleMessage(message.build());
Map<String, Object> map = jdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME=?", "ERIC.CARTMAN");
assertEquals("Wrong username", "ERIC.CARTMAN", map.get("USERNAME"));
assertEquals("Wrong password", "C4RTM4N", map.get("PASSWORD"));
assertEquals("Wrong email", "ERIC@CARTMAN.COM", map.get("EMAIL"));
}
@Test
public void testDerbyStoredProcedureInsertWithHeaderExpression() {
StoredProcMessageHandler messageHandler = new StoredProcMessageHandler(this.embeddedDatabase, "CREATE_USER");
final List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
procedureParameters.add(new ProcedureParameter("USERNAME", null, "headers[business_id] + '_' + payload.username"));
procedureParameters.add(new ProcedureParameter("password", "static_password", null));
procedureParameters.add(new ProcedureParameter("email", "static_email" , null));
messageHandler.setProcedureParameters(procedureParameters);
messageHandler.afterPropertiesSet();
MessageBuilder<User> message = MessageBuilder.withPayload(new User("Eric.Cartman", "c4rtm4n", "eric@cartman.com"));
message.setHeader("business_id", "1234");
messageHandler.handleMessage(message.build());
Map<String, Object> map = jdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME=?", "1234_Eric.Cartman");
assertEquals("Wrong username", "1234_Eric.Cartman", map.get("USERNAME"));
assertEquals("Wrong password", "static_password", map.get("PASSWORD"));
assertEquals("Wrong email", "static_email", map.get("EMAIL"));
}
}

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<jdbc:embedded-database id="datasource" type="DERBY">
<jdbc:script location="classpath:derby-stored-procedures.sql"/>
</jdbc:embedded-database>
<int:poller id="defaultPoller" default="true" fixed-rate="5000"/>
<int:gateway id="startGateway" default-request-channel="startChannel"
service-interface="org.springframework.integration.jdbc.storedproc.CreateUser" />
<int:channel id="startChannel"/>
<int-jdbc:stored-proc-outbound-gateway request-channel="startChannel" stored-procedure-name="CREATE_USER_RETURN_ALL" data-source="datasource"
auto-startup="true"
id="gateway"
ignore-column-meta-data="false"
is-function="false"
expect-single-result="true"
reply-channel="outputChannel">
<int-jdbc:parameter name="username" expression="payload.username"/>
<int-jdbc:parameter name="password" expression="payload.password"/>
<int-jdbc:parameter name="email" expression="payload.email"/>
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.UserMapper" />
</int-jdbc:stored-proc-outbound-gateway>
<int:channel id="outputChannel"/>
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" />
<bean id="consumer" class="org.springframework.integration.jdbc.StoredProcOutboundGatewayWithNamespaceIntegrationTests$Consumer"/>
<int:logging-channel-adapter channel="errorChannel" log-full-message="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
</beans>

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.jdbc.storedproc.CreateUser;
import org.springframework.integration.jdbc.storedproc.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gunnar Hillert
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcOutboundGatewayWithNamespaceIntegrationTests {
@Autowired
private AbstractApplicationContext context;
@Autowired
private Consumer consumer;
@Autowired
CreateUser createUser;
@Test
public void test() throws Exception {
createUser.createUser(new User("myUsername", "myPassword", "myEmail"));
List<Message<?>> received = new ArrayList<Message<?>>();
received.add(consumer.poll(2000));
Message<?> message = received.get(0);
context.stop();
assertNotNull(message);
assertNotNull(message.getPayload());
assertNotNull(message.getPayload() instanceof Collection<?>);
Collection<User> allUsers = (Collection<User>) message.getPayload();
assertTrue(allUsers.size() == 1);
User userFromDb = allUsers.iterator().next();
assertEquals("Wrong username", "myUsername", userFromDb.getUsername());
assertEquals("Wrong password", "myPassword", userFromDb.getPassword());
assertEquals("Wrong email", "myEmail", userFromDb.getEmail());
}
static class Counter {
private final AtomicInteger count = new AtomicInteger();
public Integer next() throws InterruptedException {
if (count.get()>2){
//prevent message overload
return null;
}
return Integer.valueOf(count.incrementAndGet());
}
}
static class Consumer {
private final BlockingQueue<Message<?>> messages = new LinkedBlockingQueue<Message<?>>();
@ServiceActivator
public void receive(Message<?>message) {
messages.add(message);
}
Message<?> poll(long timeoutInMillis) throws InterruptedException {
return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
}
}
}

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<jdbc:embedded-database id="dataSource" type="DERBY">
<jdbc:script location="classpath:derby-stored-procedures.sql"/>
</jdbc:embedded-database>
<int:poller id="defaultPoller" default="true" fixed-rate="5000"/>
<int:gateway id="startGateway" default-request-channel="startChannel"
service-interface="org.springframework.integration.jdbc.storedproc.CreateUser" />
<int:channel id="startChannel"/>
<bean id="gateway" class="org.springframework.integration.jdbc.StoredProcOutboundGateway">
<constructor-arg name="dataSource" ref="dataSource" />
<constructor-arg name="storedProcedureName" value="CREATE_USER_RETURN_ALL"/>
<property name="isFunction" value="false"/>
<property name="expectSingleResult" value="true"/>
<property name="outputChannel" ref="outputChannel"/>
<property name="procedureParameters" >
<util:list>
<bean class="org.springframework.integration.jdbc.storedproc.ProcedureParameter">
<property name="name" value="username"/>
<property name="expression" value="payload.username"/>
</bean>
<bean class="org.springframework.integration.jdbc.storedproc.ProcedureParameter">
<property name="name" value="password"/>
<property name="expression" value="payload.password"/>
</bean>
<bean class="org.springframework.integration.jdbc.storedproc.ProcedureParameter">
<property name="name" value="email"/>
<property name="expression" value="payload.email"/>
</bean>
</util:list>
</property>
<property name="returningResultSetRowMappers">
<util:map map-class="java.util.Hashtable">
<entry key="out" value-ref="rowMapper"/>
</util:map>
</property>
</bean>
<bean id="storedProcedureEndpoint"
class="org.springframework.integration.endpoint.EventDrivenConsumer">
<constructor-arg name="inputChannel" ref="startChannel"/>
<constructor-arg name="handler" ref="gateway"/>
</bean>
<bean id="rowMapper" class="org.springframework.integration.jdbc.storedproc.UserMapper"/>
<int:channel id="outputChannel"/>
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" />
<bean id="consumer" class="org.springframework.integration.jdbc.StoredProcOutboundGatewayWithSpringContextIntegrationTests$Consumer"/>
<int:logging-channel-adapter channel="errorChannel" log-full-message="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.jdbc.storedproc.CreateUser;
import org.springframework.integration.jdbc.storedproc.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gunnar Hillert
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcOutboundGatewayWithSpringContextIntegrationTests {
private static Logger logger = Logger.getLogger(StoredProcOutboundGatewayWithSpringContextIntegrationTests.class);
@Autowired
private DataSource datasource;
@Autowired
private AbstractApplicationContext context;
@Autowired
private Consumer consumer;
@Autowired
CreateUser createUser;
@Test
public void test() throws Exception {
createUser.createUser(new User("myUsername", "myPassword", "myEmail"));
List<Message<?>> received = new ArrayList<Message<?>>();
received.add(consumer.poll(2000));
Message<?> message = received.get(0);
context.stop();
assertNotNull(message);
assertNotNull(message.getPayload());
assertNotNull(message.getPayload() instanceof Collection<?>);
Collection<User> allUsers = (Collection<User>) message.getPayload();
assertTrue(allUsers.size() == 1);
}
static class Counter {
private final AtomicInteger count = new AtomicInteger();
public Integer next() throws InterruptedException {
if (count.get()>2){
//prevent message overload
return null;
}
return Integer.valueOf(count.incrementAndGet());
}
}
static class Consumer {
private final BlockingQueue<Message<?>> messages = new LinkedBlockingQueue<Message<?>>();
@ServiceActivator
public void receive(Message<?>message) {
messages.add(message);
}
Message<?> poll(long timeoutInMillis) throws InterruptedException {
return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
}
}
}

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:h2-stored-procedures.sql"/>
</jdbc:embedded-database>
<int-jdbc:stored-proc-inbound-channel-adapter id="inbound-adapter" channel="outputChannel" data-source="dataSource"
ignore-column-meta-data="true"
expect-single-result="true"
stored-procedure-name="GET_RANDOM_NUMBER">
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.jdbc.core.SingleColumnRowMapper"/>
</int-jdbc:stored-proc-inbound-channel-adapter>
<int:poller id="defaultPoller" default="true" fixed-rate="5000"/>
<int:channel id="outputChannel"/>
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" />
<bean id="consumer" class="org.springframework.integration.jdbc.StoredProcPollingChannelAdapterWithNamespace2IntegrationTests$Consumer"/>
<int:logging-channel-adapter channel="errorChannel" log-full-message="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gunnar Hillert
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcPollingChannelAdapterWithNamespace2IntegrationTests {
private static Logger logger = Logger.getLogger(StoredProcPollingChannelAdapterWithNamespace2IntegrationTests.class);
@Autowired
private AbstractApplicationContext context;
@Autowired
private Consumer consumer;
@Test
public void pollH2DatabaseUsingStoredProcedureCall() throws Exception {
List<Message<?>> received = new ArrayList<Message<?>>();
received.add(consumer.poll(60000));
Message<?> message = received.get(0);
context.stop();
assertNotNull(message);
assertNotNull(message.getPayload());
assertTrue(message.getPayload() instanceof List<?>);
List<Integer> resultList = (List<Integer>) message.getPayload();
assertTrue(resultList.size() == 1);
}
static class Counter {
private final AtomicInteger count = new AtomicInteger();
public Integer next() throws InterruptedException {
if (count.get()>2){
//prevent message overload
return null;
}
return Integer.valueOf(count.incrementAndGet());
}
}
static class Consumer {
private final BlockingQueue<Message<?>> messages = new LinkedBlockingQueue<Message<?>>();
@ServiceActivator
public void receive(Message<?>message) {
messages.add(message);
}
Message<?> poll(long timeoutInMillis) throws InterruptedException {
return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
}
}
}

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:h2-stored-procedures.sql"/>
</jdbc:embedded-database>
<int-jdbc:stored-proc-inbound-channel-adapter id="inbound-adapter" channel="outputChannel" data-source="dataSource"
ignore-column-meta-data="true"
expect-single-result="true"
stored-procedure-name="GET_PRIME_NUMBERS">
<int-jdbc:sql-parameter-definition name="beginRange" direction="IN" type="INTEGER"/>
<int-jdbc:sql-parameter-definition name="endRange" direction="IN" type="INTEGER"/>
<int-jdbc:parameter name="beginRange" value="1" type="java.lang.Integer"/>
<int-jdbc:parameter name="endRange" value="10" type="java.lang.Integer"/>
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
</int-jdbc:stored-proc-inbound-channel-adapter>
<int:poller id="defaultPoller" default="true" fixed-rate="5000"/>
<int:channel id="outputChannel"/>
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" />
<bean id="consumer" class="org.springframework.integration.jdbc.StoredProcPollingChannelAdapterWithNamespaceIntegrationTests$Consumer"/>
<int:logging-channel-adapter channel="errorChannel" log-full-message="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gunnar Hillert
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcPollingChannelAdapterWithNamespaceIntegrationTests {
private static Logger logger = Logger.getLogger(StoredProcPollingChannelAdapterWithNamespaceIntegrationTests.class);
@Autowired
private AbstractApplicationContext context;
@Autowired
private Consumer consumer;
@Test
public void pollH2DatabaseUsingStoredProcedureCall() throws Exception {
List<Message<?>> received = new ArrayList<Message<?>>();
received.add(consumer.poll(60000));
Message<?> message = received.get(0);
context.stop();
assertNotNull(message);
assertNotNull(message.getPayload());
assertNotNull(message.getPayload() instanceof Collection<?>);
List<Integer> primeNumbers = (List<Integer>) message.getPayload();
assertTrue(primeNumbers.size() == 4);
assertTrue(Integer.valueOf(2).equals(primeNumbers.get(0)));
assertTrue(Integer.valueOf(3).equals(primeNumbers.get(1)));
assertTrue(Integer.valueOf(5).equals(primeNumbers.get(2)));
assertTrue(Integer.valueOf(7).equals(primeNumbers.get(3)));
}
static class Counter {
private final AtomicInteger count = new AtomicInteger();
public Integer next() throws InterruptedException {
if (count.get()>2){
//prevent message overload
return null;
}
return Integer.valueOf(count.incrementAndGet());
}
}
static class Consumer {
private final BlockingQueue<Message<?>> messages = new LinkedBlockingQueue<Message<?>>();
@ServiceActivator
public void receive(Message<?>message) {
messages.add(message);
}
Message<?> poll(long timeoutInMillis) throws InterruptedException {
return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
}
}
}

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:h2-stored-procedures.sql"/>
</jdbc:embedded-database>
<int:poller id="defaultPoller" default="true" fixed-rate="5000"/>
<bean id="source" class="org.springframework.integration.jdbc.StoredProcPollingChannelAdapter">
<constructor-arg name="dataSource" ref="dataSource" />
<constructor-arg name="storedProcedureName" value="GET_PRIME_NUMBERS"/>
<property name="function" value="false"/>
<property name="expectSingleResult" value="true"/>
<property name="procedureParameters" >
<util:list>
<bean class="org.springframework.integration.jdbc.storedproc.ProcedureParameter">
<property name="name" value="beginRange"/>
<property name="value" value="1"/>
</bean>
<bean class="org.springframework.integration.jdbc.storedproc.ProcedureParameter">
<property name="name" value="endRange"/>
<property name="value" value="10"/>
</bean>
</util:list>
</property>
<property name="sqlParameters">
<util:list>
<bean class="org.springframework.jdbc.core.SqlParameter">
<constructor-arg name="name" value="beginRange"/>
<constructor-arg name="sqlType"><util:constant static-field="java.sql.Types.INTEGER"/></constructor-arg>
</bean>
<bean class="org.springframework.jdbc.core.SqlParameter">
<constructor-arg name="name" value="endRange"/>
<constructor-arg name="sqlType"><util:constant static-field="java.sql.Types.INTEGER"/></constructor-arg>
</bean>
</util:list>
</property>
<property name="returningResultSetRowMappers">
<util:map map-class="java.util.Hashtable">
<entry key="out" value-ref="rowMapper"/>
</util:map>
</property>
<property name="ignoreColumnMetaData" value="true"/>
</bean>
<bean id="rowMapper" class="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
<bean id="storedProcedureEndpoint"
class="org.springframework.integration.endpoint.SourcePollingChannelAdapter">
<property name="source" ref="source"/>
<property name="outputChannel" ref="outputChannel"/>
<property name="pollerMetadata" ref="defaultPoller"/>
</bean>
<int:channel id="outputChannel"/>
<!-- <int:channel id="errorChannel" /> -->
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" />
<bean id="consumer" class="org.springframework.integration.jdbc.StoredProcPollingChannelAdapterWithSpringContextIntegrationTests$Consumer"/>
<int:logging-channel-adapter channel="errorChannel" log-full-message="true"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gunnar Hillert
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcPollingChannelAdapterWithSpringContextIntegrationTests {
private static Logger logger = Logger.getLogger(StoredProcPollingChannelAdapterWithSpringContextIntegrationTests.class);
@Autowired
private DataSource datasource;
@Autowired
private AbstractApplicationContext context;
@Autowired
private Consumer consumer;
@Test
public void test() throws Exception {
List<Message<?>> received = new ArrayList<Message<?>>();
received.add(consumer.poll(2000));
Message<?> message = received.get(0);
context.stop();
assertNotNull(message);
assertNotNull(message.getPayload());
assertNotNull(message.getPayload() instanceof Collection<?>);
Collection<Integer> primeNumbers = (Collection<Integer>) message.getPayload();
assertTrue(primeNumbers.size() == 4);
}
static class Counter {
private final AtomicInteger count = new AtomicInteger();
public Integer next() throws InterruptedException {
if (count.get()>2){
//prevent message overload
return null;
}
return Integer.valueOf(count.incrementAndGet());
}
}
static class Consumer {
private final BlockingQueue<Message<?>> messages = new LinkedBlockingQueue<Message<?>>();
@ServiceActivator
public void receive(Message<?>message) {
messages.add(message);
}
Message<?> poll(long timeoutInMillis) throws InterruptedException {
return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
}
}
}

View File

@@ -13,6 +13,9 @@
package org.springframework.integration.jdbc.config;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.Map;
@@ -30,10 +33,6 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
* @author Mark Fisher

View File

@@ -9,7 +9,6 @@ import java.io.OutputStream;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.DefaultSerializer;

View File

@@ -12,6 +12,10 @@
*/
package org.springframework.integration.jdbc.config;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Collections;
import java.util.Map;
@@ -31,11 +35,6 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Dave Syer
* @author Oleg Zhurakousky

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,11 @@
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -38,11 +43,6 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
// Not transactional because the poller threads need access to the data
// @Transactional
public class JdbcPollingChannelAdapterParserTests {

View File

@@ -0,0 +1,57 @@
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import org.hsqldb.Types;
import org.junit.Test;
public class JdbcTypesEnumTests {
@Test
public void testGetCode() {
JdbcTypesEnum jdbcTypesEnum = JdbcTypesEnum.convertToJdbcTypesEnum("VARCHAR");
assertNotNull("Expected not null jdbcTypesEnum.", jdbcTypesEnum);
assertEquals(Integer.valueOf(Types.VARCHAR), Integer.valueOf(jdbcTypesEnum.getCode()));
}
@Test
public void testConvertToJdbcTypesEnumWithInvalidParameter() {
JdbcTypesEnum jdbcTypesEnum = JdbcTypesEnum.convertToJdbcTypesEnum("KENNY4JDBC");
assertNull("Expected null return value.", jdbcTypesEnum);
}
@Test
public void testConvertToJdbcTypesEnumWithNullParameter() {
try {
JdbcTypesEnum.convertToJdbcTypesEnum(null);
} catch (IllegalArgumentException e) {
assertEquals("Parameter sqlTypeAsString, must not be null nor empty", e.getMessage());
return;
}
fail("Expected Exception");
}
@Test
public void testConvertToJdbcTypesEnumWithEmptyParameter() {
try {
JdbcTypesEnum.convertToJdbcTypesEnum(" ");
} catch (IllegalArgumentException e) {
assertEquals("Parameter sqlTypeAsString, must not be null nor empty", e.getMessage());
return;
}
fail("Expected Exception");
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import java.sql.Types;
import java.util.List;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcMessageHandlerParserTests {
private ConfigurableApplicationContext context;
private EventDrivenConsumer consumer;
@Test
public void testProcedureNameIsSet() throws Exception {
setUp("basicStoredProcOutboundChannelAdapterTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.consumer);
Object handler = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(handler);
Object executor = accessor.getPropertyValue("executor");
DirectFieldAccessor executorAccessor = new DirectFieldAccessor(executor);
Object testProcedure1 = executorAccessor.getPropertyValue("storedProcedureName");
assertEquals("Resolution Required should be 'testProcedure1' but was " + testProcedure1, "testProcedure1", testProcedure1);
}
@Test
public void testProcedurepParametersAreSet() throws Exception {
setUp("basicStoredProcOutboundChannelAdapterTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.consumer);
Object handler = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(handler);
Object executor = accessor.getPropertyValue("executor");
DirectFieldAccessor executorAccessor = new DirectFieldAccessor(executor);
Object procedureParameters = executorAccessor.getPropertyValue("procedureParameters");
assertNotNull(procedureParameters);
assertTrue(procedureParameters instanceof List);
List<ProcedureParameter>procedureParametersAsList = (List<ProcedureParameter>) procedureParameters;
assertTrue(procedureParametersAsList.size() == 4);
ProcedureParameter parameter1 = procedureParametersAsList.get(0);
ProcedureParameter parameter2 = procedureParametersAsList.get(1);
ProcedureParameter parameter3 = procedureParametersAsList.get(2);
ProcedureParameter parameter4 = procedureParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("description", parameter2.getName());
assertEquals("password", parameter3.getName());
assertEquals("age", parameter4.getName());
assertEquals("kenny", parameter1.getValue());
assertEquals("Who killed Kenny?", parameter2.getValue());
assertNull(parameter3.getValue());
assertEquals(Integer.valueOf(30), (Integer) parameter4.getValue());
assertNull(parameter1.getExpression());
assertNull(parameter2.getExpression());
assertEquals("payload.username", parameter3.getExpression());
assertNull(parameter4.getExpression());
}
@Test
public void testSqlParametersAreSet() throws Exception {
setUp("basicStoredProcOutboundChannelAdapterTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.consumer);
Object handler = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(handler);
Object executor = accessor.getPropertyValue("executor");
DirectFieldAccessor executorAccessor = new DirectFieldAccessor(executor);
Object sqlParameters = executorAccessor.getPropertyValue("sqlParameters");
assertNotNull(sqlParameters);
assertTrue(sqlParameters instanceof List);
List<SqlParameter>sqlParametersAsList = (List<SqlParameter>) sqlParameters;
assertTrue(sqlParametersAsList.size() == 4);
SqlParameter parameter1 = sqlParametersAsList.get(0);
SqlParameter parameter2 = sqlParametersAsList.get(1);
SqlParameter parameter3 = sqlParametersAsList.get(2);
SqlParameter parameter4 = sqlParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("password", parameter2.getName());
assertEquals("age", parameter3.getName());
assertEquals("description", parameter4.getName());
assertNull("Expect that the scale is null.", parameter1.getScale());
assertNull("Expect that the scale is null.", parameter2.getScale());
assertEquals("Expect that the scale is 5.", Integer.valueOf(5), parameter3.getScale());
assertNull("Expect that the scale is null.", parameter4.getScale());
assertEquals("SqlType is ", Types.VARCHAR, parameter1.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter2.getSqlType());
assertEquals("SqlType is ", Types.INTEGER, parameter3.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter4.getSqlType());
assertTrue(parameter1 instanceof SqlParameter);
assertTrue(parameter2 instanceof SqlOutParameter);
assertTrue(parameter3 instanceof SqlInOutParameter);
assertTrue(parameter4 instanceof SqlParameter);
}
@After
public void tearDown(){
if(context != null){
context.close();
}
}
public void setUp(String name, Class<?> cls){
context = new ClassPathXmlApplicationContext(name, cls);
consumer = this.context.getBean("storedProcedureOutboundChannelAdapter", EventDrivenConsumer.class);
}
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.jdbc.storedproc.PrimeMapper;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcOutboundGatewayParserTests {
private ConfigurableApplicationContext context;
private EventDrivenConsumer outboundGateway;
@Test
public void testProcedureNameIsSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object storedProcedureName = accessor.getPropertyValue("storedProcedureName");
assertEquals("Wrong stored procedure name", "GET_PRIME_NUMBERS", storedProcedureName);
}
@Test
public void testProcedurepParametersAreSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object procedureParameters = accessor.getPropertyValue("procedureParameters");
assertNotNull(procedureParameters);
assertTrue(procedureParameters instanceof List);
List<ProcedureParameter>procedureParametersAsList = (List<ProcedureParameter>) procedureParameters;
assertTrue(procedureParametersAsList.size() == 4);
ProcedureParameter parameter1 = procedureParametersAsList.get(0);
ProcedureParameter parameter2 = procedureParametersAsList.get(1);
ProcedureParameter parameter3 = procedureParametersAsList.get(2);
ProcedureParameter parameter4 = procedureParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("description", parameter2.getName());
assertEquals("password", parameter3.getName());
assertEquals("age", parameter4.getName());
assertEquals("kenny", parameter1.getValue());
assertEquals("Who killed Kenny?", parameter2.getValue());
assertNull(parameter3.getValue());
assertEquals(Integer.valueOf(30), (Integer) parameter4.getValue());
assertNull(parameter1.getExpression());
assertNull(parameter2.getExpression());
assertEquals("payload.username", parameter3.getExpression());
assertNull(parameter4.getExpression());
}
@Test
public void testReturningResultSetRowMappersAreSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object returningResultSetRowMappers = accessor.getPropertyValue("returningResultSetRowMappers");
assertNotNull(returningResultSetRowMappers);
assertTrue(returningResultSetRowMappers instanceof Map);
Map<String, RowMapper<?>> returningResultSetRowMappersAsMap = (Map<String, RowMapper<?>>) returningResultSetRowMappers;
assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 1", returningResultSetRowMappersAsMap.size() == 1);
Entry<String, ?> mapEntry1 = returningResultSetRowMappersAsMap.entrySet().iterator().next();
assertEquals("out", mapEntry1.getKey());
assertTrue(mapEntry1.getValue() instanceof PrimeMapper);
}
@Test
public void testSqlParametersAreSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object sqlParameters = accessor.getPropertyValue("sqlParameters");
assertNotNull(sqlParameters);
assertTrue(sqlParameters instanceof List);
List<SqlParameter>sqlParametersAsList = (List<SqlParameter>) sqlParameters;
assertTrue(sqlParametersAsList.size() == 4);
SqlParameter parameter1 = sqlParametersAsList.get(0);
SqlParameter parameter2 = sqlParametersAsList.get(1);
SqlParameter parameter3 = sqlParametersAsList.get(2);
SqlParameter parameter4 = sqlParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("password", parameter2.getName());
assertEquals("age", parameter3.getName());
assertEquals("description", parameter4.getName());
assertNull("Expect that the scale is null.", parameter1.getScale());
assertNull("Expect that the scale is null.", parameter2.getScale());
assertEquals("Expect that the scale is 5.", Integer.valueOf(5), parameter3.getScale());
assertNull("Expect that the scale is null.", parameter4.getScale());
assertEquals("SqlType is ", Types.VARCHAR, parameter1.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter2.getSqlType());
assertEquals("SqlType is ", Types.INTEGER, parameter3.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter4.getSqlType());
assertTrue(parameter1 instanceof SqlParameter);
assertTrue(parameter2 instanceof SqlOutParameter);
assertTrue(parameter3 instanceof SqlInOutParameter);
assertTrue(parameter4 instanceof SqlParameter);
}
@After
public void tearDown(){
if(context != null){
context.close();
}
}
public void setUp(String name, Class<?> cls){
this.context = new ClassPathXmlApplicationContext(name, cls);
this.outboundGateway = this.context.getBean("storedProcedureOutboundGateway", EventDrivenConsumer.class);
}
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.jdbc.storedproc.PrimeMapper;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
* @since 2.1
*
*/
public class StoredProcPollingChannelAdapterParserTests {
private ConfigurableApplicationContext context;
private SourcePollingChannelAdapter pollingAdapter;
@Test
public void testProcedureNameIsSet() throws Exception {
setUp("storedProcPollingChannelAdapterParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.pollingAdapter);
Object source = accessor.getPropertyValue("source");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object storedProcedureName = accessor.getPropertyValue("storedProcedureName");
assertEquals("Wrong stored procedure name", "GET_PRIME_NUMBERS", storedProcedureName);
}
@Test
public void testProcedurepParametersAreSet() throws Exception {
setUp("storedProcPollingChannelAdapterParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.pollingAdapter);
Object source = accessor.getPropertyValue("source");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object procedureParameters = accessor.getPropertyValue("procedureParameters");
assertNotNull(procedureParameters);
assertTrue(procedureParameters instanceof List);
List<ProcedureParameter>procedureParametersAsList = (List<ProcedureParameter>) procedureParameters;
assertTrue(procedureParametersAsList.size() == 4);
ProcedureParameter parameter1 = procedureParametersAsList.get(0);
ProcedureParameter parameter2 = procedureParametersAsList.get(1);
ProcedureParameter parameter3 = procedureParametersAsList.get(2);
ProcedureParameter parameter4 = procedureParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("description", parameter2.getName());
assertEquals("password", parameter3.getName());
assertEquals("age", parameter4.getName());
assertEquals("kenny", parameter1.getValue());
assertEquals("Who killed Kenny?", parameter2.getValue());
assertNull(parameter3.getValue());
assertEquals(Integer.valueOf(30), (Integer) parameter4.getValue());
assertNull(parameter1.getExpression());
assertNull(parameter2.getExpression());
assertEquals("payload.username", parameter3.getExpression());
assertNull(parameter4.getExpression());
}
@Test
public void testReturningResultSetRowMappersAreSet() throws Exception {
setUp("storedProcPollingChannelAdapterParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.pollingAdapter);
Object source = accessor.getPropertyValue("source");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object returningResultSetRowMappers = accessor.getPropertyValue("returningResultSetRowMappers");
assertNotNull(returningResultSetRowMappers);
assertTrue(returningResultSetRowMappers instanceof Map);
Map<String, RowMapper<?>> returningResultSetRowMappersAsMap = (Map<String, RowMapper<?>>) returningResultSetRowMappers;
assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 1", returningResultSetRowMappersAsMap.size() == 1);
Entry<String, ?> mapEntry1 = returningResultSetRowMappersAsMap.entrySet().iterator().next();
assertEquals("out", mapEntry1.getKey());
assertTrue(mapEntry1.getValue() instanceof PrimeMapper);
}
@Test
public void testSqlParametersAreSet() throws Exception {
setUp("storedProcPollingChannelAdapterParserTest.xml", getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(this.pollingAdapter);
Object source = accessor.getPropertyValue("source");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Object sqlParameters = accessor.getPropertyValue("sqlParameters");
assertNotNull(sqlParameters);
assertTrue(sqlParameters instanceof List);
List<SqlParameter>sqlParametersAsList = (List<SqlParameter>) sqlParameters;
assertTrue(sqlParametersAsList.size() == 4);
SqlParameter parameter1 = sqlParametersAsList.get(0);
SqlParameter parameter2 = sqlParametersAsList.get(1);
SqlParameter parameter3 = sqlParametersAsList.get(2);
SqlParameter parameter4 = sqlParametersAsList.get(3);
assertEquals("username", parameter1.getName());
assertEquals("password", parameter2.getName());
assertEquals("age", parameter3.getName());
assertEquals("description", parameter4.getName());
assertNull("Expect that the scale is null.", parameter1.getScale());
assertNull("Expect that the scale is null.", parameter2.getScale());
assertEquals("Expect that the scale is 5.", Integer.valueOf(5), parameter3.getScale());
assertNull("Expect that the scale is null.", parameter4.getScale());
assertEquals("SqlType is ", Types.VARCHAR, parameter1.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter2.getSqlType());
assertEquals("SqlType is ", Types.INTEGER, parameter3.getSqlType());
assertEquals("SqlType is ", Types.VARCHAR, parameter4.getSqlType());
assertTrue(parameter1 instanceof SqlParameter);
assertTrue(parameter2 instanceof SqlOutParameter);
assertTrue(parameter3 instanceof SqlInOutParameter);
assertTrue(parameter4 instanceof SqlParameter);
}
@After
public void tearDown(){
if(context != null){
context.close();
}
}
public void setUp(String name, Class<?> cls){
this.context = new ClassPathXmlApplicationContext(name, cls);
this.pollingAdapter = this.context.getBean("storedProcedurePollingChannelAdapter", SourcePollingChannelAdapter.class);
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="target"/>
<jdbc:embedded-database id="dataSource" type="HSQL"/>
<int-jdbc:message-store id="messageStore" data-source="dataSource"/>
<int-jdbc:stored-proc-outbound-channel-adapter id="storedProcedureOutboundChannelAdapter"
data-source="dataSource" channel="target"
stored-procedure-name="testProcedure1">
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR"/>
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5"/>
<int-jdbc:sql-parameter-definition name="description" />
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
<int-jdbc:parameter name="password" expression="payload.username"/>
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
</int-jdbc:stored-proc-outbound-channel-adapter>
</beans>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="requestChannel"/>
<int:channel id="replyChannel"/>
<jdbc:embedded-database id="datasource" type="HSQL"/>
<int-jdbc:stored-proc-outbound-gateway request-channel="requestChannel" stored-procedure-name="GET_PRIME_NUMBERS" data-source="datasource"
auto-startup="true"
id="storedProcedureOutboundGateway"
ignore-column-meta-data="false"
is-function="false"
order="2"
reply-channel="replyChannel"
request-timeout="555"
return-value-required="false">
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR"/>
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5"/>
<int-jdbc:sql-parameter-definition name="description" />
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
<int-jdbc:parameter name="password" expression="payload.username"/>
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
<int:poller default="true" fixed-rate="10000"/>
</beans>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="target"/>
<jdbc:embedded-database id="dataSource" type="HSQL"/>
<int-jdbc:stored-proc-inbound-channel-adapter id="storedProcedurePollingChannelAdapter"
data-source="dataSource" channel="target"
stored-procedure-name="GET_PRIME_NUMBERS"
is-function="false">
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR"/>
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5"/>
<int-jdbc:sql-parameter-definition name="description" />
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
<int-jdbc:parameter name="password" expression="payload.username"/>
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
</int-jdbc:stored-proc-inbound-channel-adapter>
<int:poller default="true" fixed-rate="10000"/>
</beans>

View File

@@ -0,0 +1,5 @@
package org.springframework.integration.jdbc.storedproc;
public interface CreateUser {
void createUser(User user);
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.storedproc;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class PrimeMapper implements RowMapper<Integer> {
public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getInt("PRIME");
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.storedproc;
public class User {
private String username;
private String password;
private String email;
public User(String username, String password, String email) {
super();
this.username = username;
this.password = password;
this.email = email;
}
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public String getEmail() {
return this.email;
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.jdbc.storedproc;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class UserMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
return new User(rs.getString("username"), rs.getString("password"), rs.getString("email"));
}
}

View File

@@ -0,0 +1,16 @@
package org.springframework.integration.jdbc.storedproc.derby;
import java.util.Locale;
/**
*
* @author Gunnar Hillert
*
*/
public final class DerbyFunctions {
public static String convertStringToUpperCase( String invalue ) {
return invalue.toUpperCase(Locale.ENGLISH);
}
}

View File

@@ -0,0 +1,62 @@
package org.springframework.integration.jdbc.storedproc.derby;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.support.JdbcUtils;
/**
*
* @author Gunnar Hillert
*
*/
public final class DerbyStoredProcedures {
public static void createUser(String username, String password, String email)
throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = DriverManager.getConnection("jdbc:default:connection");
String sql = "INSERT INTO USERS "
+ "(USERNAME, PASSWORD, EMAIL) VALUES (?,?,?)";
stmt = conn.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
stmt.setString(3, email);
stmt.executeUpdate();
} finally {
JdbcUtils.closeStatement(stmt);
JdbcUtils.closeConnection(conn);
}
}
public static void createUserAndReturnAll(String username, String password,
String email, ResultSet[] returnedData) throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
PreparedStatement stmt2 = null;
try {
conn = DriverManager.getConnection("jdbc:default:connection");
String sql = "INSERT INTO USERS "
+ "(USERNAME, PASSWORD, EMAIL) VALUES (?,?,?)";
stmt = conn.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
stmt.setString(3, email);
stmt.executeUpdate();
stmt2 = conn.prepareStatement("select * from USERS");
returnedData[0] = stmt2.executeQuery();
} finally {
JdbcUtils.closeConnection(conn);
}
}
}

View File

@@ -0,0 +1,36 @@
package org.springframework.integration.jdbc.storedproc.h2;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.h2.tools.SimpleResultSet;
import org.hsqldb.Types;
/**
*
* @author Gunnar Hillert
*
*/
public final class H2StoredProcedures {
public static ResultSet getPrimes(int beginRange, int endRange) throws SQLException {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("PRIME", Types.INTEGER, 10, 0);
for (int i = beginRange; i <= endRange; i++) {
if (new BigInteger(String.valueOf(i)).isProbablePrime(100)) {
rs.addRow(i);
}
}
return rs;
}
public static Integer random() {
return 1 + (int)(Math.random() * 100);
}
}

View File

@@ -0,0 +1,7 @@
# Use Log4j
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
# Configuration file of the log
#log4j.configuration=file:log4j-rabbit-stocks.properties

View File

@@ -0,0 +1,4 @@
CREATE FUNCTION CONVERT_STRING_TO_UPPER_CASE (invalue VARCHAR(50)) RETURNS VARCHAR(50) PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyFunctions.convertStringToUpperCase';
create table USERS(USERNAME varchar(100),PASSWORD varchar(100), EMAIL varchar(100));
CREATE PROCEDURE CREATE_USER( IN username VARCHAR(100), IN password VARCHAR(100), IN email VARCHAR(100) ) PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.createUser';
CREATE PROCEDURE CREATE_USER_RETURN_ALL(IN username VARCHAR(100), IN password VARCHAR(100), IN email VARCHAR(100)) PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.createUserAndReturnAll';

View File

@@ -0,0 +1,2 @@
CREATE ALIAS IF NOT EXISTS GET_PRIME_NUMBERS FOR "org.springframework.integration.jdbc.storedproc.h2.H2StoredProcedures.getPrimes"
CREATE ALIAS IF NOT EXISTS GET_RANDOM_NUMBER FOR "org.springframework.integration.jdbc.storedproc.h2.H2StoredProcedures.random"

View File

@@ -0,0 +1,8 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
log4j.category.org.springframework.integration=INFO
log4j.category.org.apache.derby=INFO