diff --git a/build.gradle b/build.gradle
index bf842a4418..4d4e867cb2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -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"
diff --git a/docs/src/reference/docbook/jdbc.xml b/docs/src/reference/docbook/jdbc.xml
index 50744fbca3..c626c50bfc 100644
--- a/docs/src/reference/docbook/jdbc.xml
+++ b/docs/src/reference/docbook/jdbc.xml
@@ -220,5 +220,293 @@
separate for different physical channels that happen to have the same
logical name.
-
+
+
+ Stored Procedures
+ Spring Integration provides 3 components for stored procedures support:
+
+ Stored Procedures Inbound Channel Adapter
+ Stored Procedures Outbound Channel Adapter
+ Stored Procedures Outbound Gateway
+
+
+ Common Configuration Parameters
+
+
+ Supported Parameters
+ The Store procedures components use the org.springframework.jdbc.core.simple.SimpleJdbcCall
+ class to facilitate Stored Procedure support. The following databases
+ are fully supported for executing Stored procedures:
+
+ Apache Derby
+ DB2
+ MySQL
+ Microsoft SQL Server
+ Oracle
+ PostgreSQL
+ Sybase
+
+ The following databases are fully supported for executing Sql
+ functions:
+
+ MySQL
+ Microsoft SQL Server
+ Oracle
+ PostgreSQL
+
+
+ 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.
+ 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.
+
+ Defining Parameter Sources
+ TBD
+
+
+ Stored Procedures Inbound Channel Adapter
+
+
+ ]]> ]]> ]]> ]]> ]]> ]]> ]]>
+
+
+
+
+ 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. Required .
+
+
+ The name of the stored procedure. If the "is-function"
+ attribute is "true", this attributes specifies the
+ function name. Required .
+
+
+ Reference to a data source to use to access
+ the database. Required .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ 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. Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Specifies the direction of the Sql parameter definition.
+ Defaults to 'IN'. If your procedure is returning ResultSets,
+ please use the 'returning-resultset' element. Optional .
+
+
+ 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'.Optional .
+
+
+ The scale of the Sql parameter. Only used for numeric and decimal
+ parameters. Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+
+
+ Stored Procedures Outbound Channel Adapter
+
+
+ ]]>
+
+
+
+
+ ]]>
+
+
+
+
+ Required .
+
+
+ The name of the stored procedure. If the "is-function"
+ attribute is "true", this attributes specifies the
+ function name. Required .
+
+
+ Reference to a data source to use to access
+ the database. Required .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+
+
+ Stored Procedures Outbound Gateway
+
+
+ ]]> ]]> ]]> ]]> ]]> ]]>
+
+
+
+
+ Required .
+
+
+ The name of the stored procedure. If the "is-function"
+ attribute is "true", this attributes specifies the
+ function name. Required .
+
+
+ Reference to a data source to use to access
+ the database. Required .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ 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. Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+ Optional .
+
+
+
+
diff --git a/spring-integration-jdbc/pom.xml b/spring-integration-jdbc/pom.xml
index 0e853cac42..855df4e1ee 100644
--- a/spring-integration-jdbc/pom.xml
+++ b/spring-integration-jdbc/pom.xml
@@ -137,7 +137,7 @@
com.h2database
h2
- 1.2.125
+ 1.3.160
test
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/BeanPropertySqlParameterSourceFactory.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/BeanPropertySqlParameterSourceFactory.java
index c5a51db28c..47eaac4895 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/BeanPropertySqlParameterSourceFactory.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/BeanPropertySqlParameterSourceFactory.java
@@ -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
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactory.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactory.java
index bceec60c0b..9b507d1c47 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactory.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactory.java
@@ -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;
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcMessageHandler.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcMessageHandler.java
index 199ad48ab6..e77d983d63 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcMessageHandler.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcMessageHandler.java
@@ -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;
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
index 7d51a1ffb2..638d1de4a8 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
@@ -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.
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapter.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapter.java
index d593127e69..37dec868f5 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapter.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapter.java
@@ -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
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/SqlParameterSourceFactory.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/SqlParameterSourceFactory.java
index 818976f240..8829257499 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/SqlParameterSourceFactory.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/SqlParameterSourceFactory.java
@@ -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.
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java
new file mode 100644
index 0000000000..ef788f99c7
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java
@@ -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 sqlParameters = new ArrayList(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 ListprocedureParameters;
+
+ private volatile boolean isFunction = false;
+ private volatile boolean returnValueRequired = false;
+ private volatile Map> returningResultSetRowMappers = new HashMap>(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> 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 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 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 executeStoredProcedureInternal(Object input) {
+
+ SqlParameterSource storedProcedureParameterSource =
+ sqlParameterSourceFactory.createParameterSource(input);
+
+ return StoredProcExecutor.executeStoredProcedure(jdbcCallOperations,
+ storedProcedureParameterSource);
+ }
+
+ /**
+ */
+ private static Map executeStoredProcedure(SimpleJdbcCallOperations simpleJdbcCallOperations,
+ SqlParameterSource storedProcedureParameterSource) {
+
+ Map 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 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 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> 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;
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcMessageHandler.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcMessageHandler.java
new file mode 100644
index 0000000000..ad10961c1a
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcMessageHandler.java
@@ -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 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 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 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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcOutboundGateway.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcOutboundGateway.java
new file mode 100644
index 0000000000..2f6218d58d
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcOutboundGateway.java
@@ -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 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:
+ *
+ *
+ * Apache Derby
+ * DB2
+ * MySQL
+ * Microsoft SQL Server
+ * Oracle
+ * Sybase
+ * PostgreSQL
+ *
+ * , ,
+ * We also support metadata lookup of stored functions for the following
+ * databases:
+ *
+ *
+ * MySQL
+ * Microsoft SQL Server
+ * Oracle
+ * PostgreSQL
+ *
+ *
+ * See also: {@link http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/jdbc.html}
+ */
+ public void setSqlParameters(List 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> 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 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;
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapter.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapter.java
new file mode 100644
index 0000000000..a004efedfb
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapter.java
@@ -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 {
+
+ 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 null.
+ */
+ public Message 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 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 doPoll() {
+ Map 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:
+ *
+ *
+ * Apache Derby
+ * DB2
+ * MySQL
+ * Microsoft SQL Server
+ * Oracle
+ * Sybase
+ * PostgreSQL
+ *
+ * , ,
+ * We also support metadata lookup of stored functions for the following
+ * databases:
+ *
+ *
+ * MySQL
+ * Microsoft SQL Server
+ * Oracle
+ * PostgreSQL
+ *
+ *
+ * See also: {@link http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/jdbc.html}
+ */
+ public void setSqlParameters(List 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> 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 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;
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParser.java
index 88f6a3cb66..03c8f26abb 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParser.java
@@ -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);
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParser.java
index 2cdc8029bc..6f62280fa9 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParser.java
@@ -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");
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcNamespaceHandler.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcNamespaceHandler.java
index 3b00d75b94..bb47940cf8 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcNamespaceHandler.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcNamespaceHandler.java
@@ -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());
}
}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
index d3fa1c2e46..498cf2631d 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
@@ -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);
}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParser.java
index cfd9196f03..044c771eab 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParser.java
@@ -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);
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcTypesEnum.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcTypesEnum.java
new file mode 100644
index 0000000000..eb0690f44c
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcTypesEnum.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParser.java
new file mode 100644
index 0000000000..7e93e71d62
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParser.java
@@ -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 procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
+ final ManagedList sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
+
+ if (!procedureParameterList.isEmpty()) {
+ builder.addPropertyValue("procedureParameters", procedureParameterList);
+ }
+ if (!sqlParameterDefinitionList.isEmpty()) {
+ builder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
+ }
+
+ return builder.getBeanDefinition();
+
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java
new file mode 100644
index 0000000000..0965fcf4c4
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java
@@ -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 procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(gatewayElement, parserContext);
+ final ManagedList sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(gatewayElement, parserContext);
+ final ManagedMap 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";
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java
new file mode 100644
index 0000000000..592f624eb8
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java
@@ -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 getSqlParameterDefinitionBeanDefinitions(
+ Element storedProcComponent, ParserContext parserContext) {
+ List sqlParameterDefinitionChildElements = DomUtils.getChildElementsByTagName(storedProcComponent, "sql-parameter-definition");
+ ManagedList sqlParameterList = new ManagedList();
+
+ 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 getProcedureParameterBeanDefinitions(
+ Element storedProcComponent, ParserContext parserContext) {
+
+ ManagedList procedureParameterList = new ManagedList();
+
+ List 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 getReturningResultsetBeanDefinitions(
+ Element storedProcComponent, ParserContext parserContext) {
+
+ List returningResultsetChildElements = DomUtils.getChildElementsByTagName(storedProcComponent, "returning-resultset");
+
+ ManagedMap returningResultsetMap = new ManagedMap();
+
+ 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;
+
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParser.java
new file mode 100644
index 0000000000..8891e10339
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParser.java
@@ -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 procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
+ final ManagedList sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
+ final ManagedMap 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();
+
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/storedproc/ProcedureParameter.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/storedproc/ProcedureParameter.java
new file mode 100644
index 0000000000..a634de113d
--- /dev/null
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/storedproc/ProcedureParameter.java
@@ -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 convertExpressions(Collection procedureParameters) {
+
+ Assert.notNull(procedureParameters, "The Collection of procedureParameters must not be null.");
+
+ Map staticParameters = new HashMap();
+
+ 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 convertStaticParameters(Collection procedureParameters) {
+
+ Map staticParameters = new HashMap();
+
+ for (ProcedureParameter parameter : procedureParameters) {
+ if (parameter.getValue() != null) {
+ staticParameters.put(parameter.getName(), parameter.getValue());
+ }
+ }
+
+ return staticParameters;
+ }
+
+}
diff --git a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.1.xsd b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.1.xsd
index 7edd8c1ce1..6cbe957168 100644
--- a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.1.xsd
+++ b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.1.xsd
@@ -551,4 +551,609 @@
+
+
+
+ Defines an outbound Channel Adapter for updating a
+ database using stored procedures.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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].
+
+
+
+
+
+
+
+
+
+
+
+ Channel from which messages will be output.
+ When a message is sent to this channel it will
+ cause the query
+ to be executed.
+
+
+
+
+
+
+
+
+
+
+ Specifies the order for invocation when this endpoint is connected as a
+ subscriber to a SubscribableChannel.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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].
+
+
+
+
+
+
+
+
+
+
+ If "true", a SQL Function is called. In that case
+ the "stored-procedure-name" attribute defines
+ the name of the called function.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Specifies the order for invocation when this endpoint is connected as a
+ subscriber to a SubscribableChannel.
+
+
+
+
+
+
+ Indicates whether this procedure's return value
+ should be included.
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines an inbound Channel Adapter for polling a
+ database using a stored procedure or function.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If "true", a SQL Function is called. In that case
+ the "stored-procedure-name" attribute defines
+ the name of the called function.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The name of the stored procedure. If the "is-function"
+ attribute is "true", this attributes specifies the
+ function name.
+
+
+
+
+
+
+ Reference to a data source to use to access
+ the database.
+
+
+
+
+
+
+
+
+
+
+
+ Flag to indicate that the poller should start automatically
+ on startup (default true).
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-integration-jdbc/src/test/java/log4j.properties b/spring-integration-jdbc/src/test/java/log4j.properties
deleted file mode 100644
index 93d810c941..0000000000
--- a/spring-integration-jdbc/src/test/java/log4j.properties
+++ /dev/null
@@ -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
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactoryTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactoryTests.java
index 3da48a671a..b7547b125a 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactoryTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/ExpressionEvaluatingSqlParameterSourceFactoryTests.java
@@ -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.
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageHandlerIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageHandlerIntegrationTests.java
index b9f9dd2465..776112989a 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageHandlerIntegrationTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageHandlerIntegrationTests.java
@@ -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
*/
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests-context.xml
index 7465176f06..5d0e486bfd 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests-context.xml
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests-context.xml
@@ -36,9 +36,9 @@
-
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests.java
index df5f92c092..1bb07e13c6 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelIntegrationTests.java
@@ -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;
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelOnePollerIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelOnePollerIntegrationTests.java
index 79c702b36c..ca36418b95 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelOnePollerIntegrationTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelOnePollerIntegrationTests.java
@@ -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
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelTests.java
index 42300e48b6..1deeaab7b6 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcMessageStoreChannelTests.java
@@ -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.
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapterIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapterIntegrationTests.java
index 8450577d6b..11dab33b28 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapterIntegrationTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapterIntegrationTests.java
@@ -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
*/
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/LockInterceptor.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/LockInterceptor.java
index 5a5adfd18a..1d961413c4 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/LockInterceptor.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/LockInterceptor.java
@@ -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
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTest.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTest.java
new file mode 100644
index 0000000000..73de1a05f5
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTest.java
@@ -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> rowmappers = new HashMap>();
+ 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> rowmappers = new HashMap>();
+
+ 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 sqlParameters = new ArrayList();
+ 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 sqlParameters = new ArrayList();
+
+ 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 procedureParameters = new ArrayList();
+ 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 procedureParameters = new ArrayList();
+
+ 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.");
+
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcMessageHandlerDerbyIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcMessageHandlerDerbyIntegrationTests.java
new file mode 100644
index 0000000000..d4b447350e
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcMessageHandlerDerbyIntegrationTests.java
@@ -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 message = MessageBuilder.withPayload(new User("username", "password", "email"));
+ messageHandler.handleMessage(message.build());
+
+ Map 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 procedureParameters = new ArrayList();
+ 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 message = MessageBuilder.withPayload(new User("Eric.Cartman", "c4rtm4n", "eric@cartman.com"));
+ messageHandler.handleMessage(message.build());
+
+
+
+ Map 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 procedureParameters = new ArrayList();
+ 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 message = MessageBuilder.withPayload(new User("Eric.Cartman", "c4rtm4n", "eric@cartman.com"));
+ message.setHeader("business_id", "1234");
+ messageHandler.handleMessage(message.build());
+
+ Map 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"));
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests-context.xml
new file mode 100644
index 0000000000..82c12e6629
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests-context.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests.java
new file mode 100644
index 0000000000..940f8fbbd3
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithNamespaceIntegrationTests.java
@@ -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> received = new ArrayList>();
+
+ received.add(consumer.poll(2000));
+
+ Message> message = received.get(0);
+ context.stop();
+ assertNotNull(message);
+ assertNotNull(message.getPayload());
+ assertNotNull(message.getPayload() instanceof Collection>);
+
+ Collection allUsers = (Collection) 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> messages = new LinkedBlockingQueue>();
+
+ @ServiceActivator
+ public void receive(Message>message) {
+ messages.add(message);
+ }
+
+ Message> poll(long timeoutInMillis) throws InterruptedException {
+ return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests-context.xml
new file mode 100644
index 0000000000..b0b9d53e59
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests-context.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests.java
new file mode 100644
index 0000000000..7e616549ae
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpringContextIntegrationTests.java
@@ -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> received = new ArrayList>();
+
+ received.add(consumer.poll(2000));
+
+ Message> message = received.get(0);
+ context.stop();
+ assertNotNull(message);
+ assertNotNull(message.getPayload());
+ assertNotNull(message.getPayload() instanceof Collection>);
+
+ Collection allUsers = (Collection) 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> messages = new LinkedBlockingQueue>();
+
+ @ServiceActivator
+ public void receive(Message>message) {
+ messages.add(message);
+ }
+
+ Message> poll(long timeoutInMillis) throws InterruptedException {
+ return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests-context.xml
new file mode 100644
index 0000000000..6d2feb635c
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests-context.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests.java
new file mode 100644
index 0000000000..37143a00c4
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespace2IntegrationTests.java
@@ -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> received = new ArrayList>();
+
+ received.add(consumer.poll(60000));
+
+ Message> message = received.get(0);
+ context.stop();
+ assertNotNull(message);
+ assertNotNull(message.getPayload());
+ assertTrue(message.getPayload() instanceof List>);
+
+ List resultList = (List) 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> messages = new LinkedBlockingQueue>();
+
+ @ServiceActivator
+ public void receive(Message>message) {
+ messages.add(message);
+ }
+
+ Message> poll(long timeoutInMillis) throws InterruptedException {
+ return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests-context.xml
new file mode 100644
index 0000000000..86e40f009f
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests-context.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests.java
new file mode 100644
index 0000000000..ecfd0f50cb
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithNamespaceIntegrationTests.java
@@ -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> received = new ArrayList>();
+
+ received.add(consumer.poll(60000));
+
+ Message> message = received.get(0);
+ context.stop();
+ assertNotNull(message);
+ assertNotNull(message.getPayload());
+ assertNotNull(message.getPayload() instanceof Collection>);
+
+ List primeNumbers = (List) 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> messages = new LinkedBlockingQueue>();
+
+ @ServiceActivator
+ public void receive(Message>message) {
+ messages.add(message);
+ }
+
+ Message> poll(long timeoutInMillis) throws InterruptedException {
+ return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests-context.xml
new file mode 100644
index 0000000000..62e7eaf171
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests-context.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests.java
new file mode 100644
index 0000000000..67f12156fd
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcPollingChannelAdapterWithSpringContextIntegrationTests.java
@@ -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> received = new ArrayList>();
+
+ received.add(consumer.poll(2000));
+
+ Message> message = received.get(0);
+ context.stop();
+ assertNotNull(message);
+ assertNotNull(message.getPayload());
+ assertNotNull(message.getPayload() instanceof Collection>);
+
+ Collection primeNumbers = (Collection) 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> messages = new LinkedBlockingQueue>();
+
+ @ServiceActivator
+ public void receive(Message>message) {
+ messages.add(message);
+ }
+
+ Message> poll(long timeoutInMillis) throws InterruptedException {
+ return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
index 9f7d047a41..62e21c04c6 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
@@ -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
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParserTests.java
index 3f557fc9e2..975862b08c 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageStoreParserTests.java
@@ -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;
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
index 65dc05d53b..f1fbd3f58f 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
@@ -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
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParserTests.java
index 44d22080bf..e618fd1fc9 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcPollingChannelAdapterParserTests.java
@@ -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 {
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcTypesEnumTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcTypesEnumTests.java
new file mode 100644
index 0000000000..98d53df05a
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcTypesEnumTests.java
@@ -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");
+
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java
new file mode 100644
index 0000000000..97001acfda
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java
@@ -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);
+
+ ListprocedureParametersAsList = (List) 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);
+
+ ListsqlParametersAsList = (List) 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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
new file mode 100644
index 0000000000..ca64551f64
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
@@ -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);
+
+ ListprocedureParametersAsList = (List) 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> returningResultSetRowMappersAsMap = (Map>) returningResultSetRowMappers;
+
+ assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 1", returningResultSetRowMappersAsMap.size() == 1);
+
+ Entry 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);
+
+ ListsqlParametersAsList = (List) 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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParserTests.java
new file mode 100644
index 0000000000..ddee1c26cf
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcPollingChannelAdapterParserTests.java
@@ -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);
+
+ ListprocedureParametersAsList = (List) 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> returningResultSetRowMappersAsMap = (Map>) returningResultSetRowMappers;
+
+ assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 1", returningResultSetRowMappersAsMap.size() == 1);
+
+ Entry 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);
+
+ ListsqlParametersAsList = (List) 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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/basicStoredProcOutboundChannelAdapterTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/basicStoredProcOutboundChannelAdapterTest.xml
new file mode 100644
index 0000000000..cc92757fa4
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/basicStoredProcOutboundChannelAdapterTest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml
new file mode 100644
index 0000000000..14d8873e61
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcPollingChannelAdapterParserTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcPollingChannelAdapterParserTest.xml
new file mode 100644
index 0000000000..59bb1c0cc5
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcPollingChannelAdapterParserTest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/CreateUser.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/CreateUser.java
new file mode 100644
index 0000000000..d2d309610b
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/CreateUser.java
@@ -0,0 +1,5 @@
+package org.springframework.integration.jdbc.storedproc;
+
+public interface CreateUser {
+ void createUser(User user);
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/PrimeMapper.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/PrimeMapper.java
new file mode 100644
index 0000000000..80ade75553
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/PrimeMapper.java
@@ -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 {
+ public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return rs.getInt("PRIME");
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/User.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/User.java
new file mode 100644
index 0000000000..991b6556c1
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/User.java
@@ -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;
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/UserMapper.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/UserMapper.java
new file mode 100644
index 0000000000..2eb1559899
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/UserMapper.java
@@ -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 {
+ public User mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new User(rs.getString("username"), rs.getString("password"), rs.getString("email"));
+ }
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyFunctions.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyFunctions.java
new file mode 100644
index 0000000000..59f8ae8af6
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyFunctions.java
@@ -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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java
new file mode 100644
index 0000000000..b0dda9e308
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java
@@ -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);
+ }
+
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/h2/H2StoredProcedures.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/h2/H2StoredProcedures.java
new file mode 100644
index 0000000000..d5e8dc87d5
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/h2/H2StoredProcedures.java
@@ -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);
+ }
+
+}
diff --git a/spring-integration-jdbc/src/test/resources/commons-logging.properties b/spring-integration-jdbc/src/test/resources/commons-logging.properties
new file mode 100644
index 0000000000..51cd942d4c
--- /dev/null
+++ b/spring-integration-jdbc/src/test/resources/commons-logging.properties
@@ -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
diff --git a/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql b/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql
new file mode 100644
index 0000000000..9d7ee63f2a
--- /dev/null
+++ b/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql
@@ -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';
\ No newline at end of file
diff --git a/spring-integration-jdbc/src/test/resources/h2-stored-procedures.sql b/spring-integration-jdbc/src/test/resources/h2-stored-procedures.sql
new file mode 100644
index 0000000000..43b4da6b90
--- /dev/null
+++ b/spring-integration-jdbc/src/test/resources/h2-stored-procedures.sql
@@ -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"
diff --git a/spring-integration-jdbc/src/test/resources/log4j.properties b/spring-integration-jdbc/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..73cb4696d0
--- /dev/null
+++ b/spring-integration-jdbc/src/test/resources/log4j.properties
@@ -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