Merge pull request #185 from ghillert/INT-2241

Stored Proc: Add attribute: skipUndeclaredResults

  For reference see: https://jira.springsource.org/browse/INT-2241
This commit is contained in:
Mark Fisher
2011-11-17 12:34:21 -05:00
16 changed files with 628 additions and 375 deletions

View File

@@ -26,6 +26,7 @@ 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.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
@@ -65,7 +66,7 @@ public class StoredProcExecutor implements InitializingBean {
/**
* Uses the {@link SimpleJdbcCall} implementation for executing Stored Procedures.
*/
private final SimpleJdbcCallOperations jdbcCallOperations;
private final SimpleJdbcCall jdbcCallOperations;
/**
* Name of the stored procedure or function to be executed.
@@ -81,6 +82,16 @@ public class StoredProcExecutor implements InitializingBean {
*/
private volatile boolean ignoreColumnMetaData = false;
/**
* If this variable is set to true then all results from a stored procedure call
* that don't have a corresponding SqlOutParameter declaration will be bypassed.
*
* The value is set on the underlying {@link JdbcTemplate}.
*
* Value defaults to <code>true</code>.
*/
private volatile boolean skipUndeclaredResults = true;
/**
* If your database system is not fully supported by Spring and thus obtaining
* parameter definitions from the JDBC Meta-data is not possible, you must define
@@ -204,6 +215,8 @@ public class StoredProcExecutor implements InitializingBean {
this.jdbcCallOperations.withProcedureName(this.storedProcedureName);
}
this.jdbcCallOperations.getJdbcTemplate().setSkipUndeclaredResults(this.skipUndeclaredResults);
}
/**
@@ -333,19 +346,67 @@ public class StoredProcExecutor implements InitializingBean {
return this.storedProcedureName;
}
/**
* If set to 'true', the payload of the Message will be used as a source for
* providing parameters. If false the entire Message will be available as a
* source for parameters.
*
* If no {@link ProcedureParameter} are passed in, this property will default to
* 'true'. This means that using a default {@link BeanPropertySqlParameterSourceFactory}
* the bean properties of the payload will be used as a source for parameter values for
* the to-be-executed Stored Procedure or Function.
*
* However, if {@link ProcedureParameter} are passed in, then this property
* will by default evaluate to 'false'. {@link ProcedureParameter} allow for
* SpEl Expressions to be provided and therefore it is highly beneficial to
* have access to the entire {@link Message}.
*
* @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source.
*/
public void setUsePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.usePayloadAsParameterSource = usePayloadAsParameterSource;
}
/**
* 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.isFunction = isFunction;
}
/**
* Indicates the procedure's return value should be included in the results
* returned.
*
* @param returnValueRequired
*/
public void setReturnValueRequired(boolean returnValueRequired) {
this.returnValueRequired = returnValueRequired;
}
/**
/**
* If this variable is set to <code>true</code> then all results from a stored
* procedure call that don't have a corresponding {@link SqlOutParameter}
* declaration will be bypassed.
*
* E.g. Stored Procedures may return an update count value, even though your
* Stored Procedure only declared a single result parameter. The exact behavior
* depends on the used database.
*
* The value is set on the underlying {@link JdbcTemplate}.
*
* Only few developers will probably ever like to process update counts, thus
* the value defaults to <code>true</code>.
*
*/
public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
this.skipUndeclaredResults = skipUndeclaredResults;
}
/**
* If the Stored Procedure returns ResultSets you may provide a map of
* {@link RowMapper} to convert the {@link ResultSet} to meaningful objects.
*

View File

@@ -21,9 +21,6 @@ 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;
@@ -35,33 +32,31 @@ 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.
*
* Stored procedure parameter values 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
* 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 purposefully does 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
* 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.
*
@@ -69,17 +64,17 @@ public class StoredProcMessageHandler extends AbstractMessageHandler implements
* @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);
}
/**
* Verifies parameters, sets the parameters on {@link SimpleJdbcCallOperations}
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* when {@link ProcedureParameter} are passed in.
*/
@Override
@@ -87,44 +82,43 @@ public class StoredProcMessageHandler extends AbstractMessageHandler implements
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.
* 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 {
protected void handleMessageInternal(Message<?> message) {
Map<String, Object> resultMap = executor.executeStoredProcedure(message);
if (logger.isDebugEnabled()) {
if (resultMap != null && !resultMap.isEmpty()) {
logger.debug(String.format("The StoredProcMessageHandler ignores return "
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
* 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'.
* this flag can be set to <code>true</code>. It defaults to <code>false</code>.
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
@@ -132,25 +126,25 @@ public class StoredProcMessageHandler extends AbstractMessageHandler implements
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
/**
* If you database system is not fully supported by Spring and thus obtaining
* If your 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.
* the {@link SqlParameter} explicitly.
*/
public void setSqlParameters(List<SqlParameter> sqlParameters) {
this.executor.setSqlParameters(sqlParameters);
}
/**
* Provides the ability to set a custom {@link SqlParameterSourceFactory}.
* Keep in mind that if {@link ProcedureParameter} are set explicitly and
* you would like to provide a custom {@link SqlParameterSourceFactory},
* then you must provide an instance of {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* If not the SqlParameterSourceFactory will be replaced the default
* 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 by the default
* {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
@@ -158,24 +152,24 @@ public class StoredProcMessageHandler extends AbstractMessageHandler implements
}
/**
* If set to 'true', the payload of the Message will be used as a source for
* providing parameters. If false the entire Message will be available as a
* source for parameters.
*
* If set to 'true', the payload of the Message will be used as a source for
* providing parameters. If false the entire Message will be available as a
* source for parameters.
*
* If no {@link ProcedureParameter} are passed in, this property will default to
* 'true'. This means that using a default {@link BeanPropertySqlParameterSourceFactory}
* the bean properties of the payload will be used as a source for parameter values for
* the bean properties of the payload will be used as a source for parameter values for
* the to-be-executed Stored Procedure or Function.
*
* However, if {@link ProcedureParameter} are passed in, then this property
* will by default evaluate to 'false'. {@link ProcedureParameter} allow for
*
* However, if {@link ProcedureParameter} are passed in, then this property
* will by default evaluate to 'false'. {@link ProcedureParameter} allow for
* SpEl Expressions to be provided and therefore it is highly beneficial to
* have access to the entire {@link Message}.
*
* @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source.
*
* @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source.
*/
public void setUsePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.executor.setUsePayloadAsParameterSource(usePayloadAsParameterSource);
}
}

View File

@@ -21,13 +21,16 @@ import java.util.Map;
import javax.sql.DataSource;
import org.springframework.expression.Expression;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHandlingException;
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.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
@@ -43,27 +46,27 @@ public class StoredProcOutboundGateway extends AbstractReplyProducingMessageHand
private final StoredProcExecutor executor;
private volatile boolean expectSingleResult = false;
/**
* Constructor taking {@link DataSource} from which the DB Connection can be
* 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
* @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);
}
/**
* Verifies parameters, sets the parameters on {@link SimpleJdbcCallOperations}
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* and ensures the appropriate {@link SqlParameterSourceFactory} is defined
* when {@link ProcedureParameter} are passed in.
*/
@Override
@@ -74,19 +77,19 @@ public class StoredProcOutboundGateway extends AbstractReplyProducingMessageHand
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Map<String, Object> resultMap = executor.executeStoredProcedure(requestMessage);
final Object payload;
if (resultMap.isEmpty()) {
payload = null;
} else {
if (this.expectSingleResult && resultMap.size() == 1) {
payload = resultMap.values().iterator().next();
} else if (this.expectSingleResult && resultMap.size() > 1) {
throw new MessageHandlingException(requestMessage,
"Stored Procedure/Function call returned more than "
+ "1 result object and expectSingleResult was 'true'. ");
@@ -94,11 +97,11 @@ public class StoredProcOutboundGateway extends AbstractReplyProducingMessageHand
} else {
payload = resultMap;
}
}
return MessageBuilder.withPayload(payload).copyHeaders(requestMessage.getHeaders()).build();
}
/**
@@ -142,80 +145,121 @@ public class StoredProcOutboundGateway extends AbstractReplyProducingMessageHand
}
/**
* If true, the JDBC parameter definitions for the stored procedure are not
* automatically derived from the underlying JDBC connection. In that case
* you must pass in {@link SqlParameter} explicitly..
*
* @param ignoreColumnMetaData
* @param ignoreColumnMetaData Defaults to <code>false</code>.
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
* Indicates the procedure's return value should be included in the results
* returned.
*
* @param returnValueRequired
*/
public void setReturnValueRequired(boolean returnValueRequired) {
this.executor.setReturnValueRequired(returnValueRequired);
}
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
*/
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
/**
* 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 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
* 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.
*
*
* 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
*
* 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;
}
/**
*
* @param sqlParameterSourceFactory
*/
/**
* 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 by the default
* {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.executor.setSqlParameterSourceFactory(sqlParameterSourceFactory);
}
/**
* If set to 'true', the payload of the Message will be used as a source for
* providing parameters. If false the entire Message will be available as a
* source for parameters.
*
* If set to 'true', the payload of the Message will be used as a source for
* providing parameters. If false the entire Message will be available as a
* source for parameters.
*
* If no {@link ProcedureParameter} are passed in, this property will default to
* 'true'. This means that using a default {@link BeanPropertySqlParameterSourceFactory}
* the bean properties of the payload will be used as a source for parameter values for
* the bean properties of the payload will be used as a source for parameter values for
* the to-be-executed Stored Procedure or Function.
*
* However, if {@link ProcedureParameter} are passed in, then this property
* will by default evaluate to 'false'. {@link ProcedureParameter} allow for
*
* However, if {@link ProcedureParameter} are passed in, then this property
* will by default evaluate to 'false'. {@link ProcedureParameter} allow for
* SpEl Expressions to be provided and therefore it is highly beneficial to
* have access to the entire {@link Message}.
*
* @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source.
*
* @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source.
*/
public void setUsePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.executor.setUsePayloadAsParameterSource(usePayloadAsParameterSource);
}
/**
* If this variable is set to <code>true</code> then all results from a stored
* procedure call that don't have a corresponding {@link SqlOutParameter}
* declaration will be bypassed.
*
* E.g. Stored Procedures may return an update count value, even though your
* Stored Procedure only declared a single result parameter. The exact behavior
* depends on the used database.
*
* The value is set on the underlying {@link JdbcTemplate}.
*
* Only few developers will probably ever like to process update counts, thus
* the value defaults to <code>true</code>.
*
*/
public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
this.executor.setSkipUndeclaredResults(skipUndeclaredResults);
}
}

View File

@@ -21,21 +21,24 @@ import java.util.Map;
import javax.sql.DataSource;
import org.springframework.expression.Expression;
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.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlOutParameter;
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
* 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
@@ -46,7 +49,7 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
private 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.
@@ -55,10 +58,10 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
* @param storedProcedureName Name of the Stored Procedure or 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);
}
@@ -97,11 +100,11 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
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'. ");
@@ -109,11 +112,11 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
} else {
payload = resultMap;
}
}
return payload;
}
protected Map<String, ?> doPoll() {
@@ -124,10 +127,17 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
return "stored-proc:inbound-channel-adapter";
}
/**
*
* @param sqlParameterSourceFactory
*/
/**
* 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 by the default
* {@link ExpressionEvaluatingSqlParameterSourceFactory}.
*
* @param sqlParameterSourceFactory
*/
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.executor.setSqlParameterSourceFactory(sqlParameterSourceFactory);
}
@@ -173,30 +183,39 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
}
/**
* If true, the JDBC parameter definitions for the stored procedure are not
* automatically derived from the underlying JDBC connection. In that case
* you must pass in {@link SqlParameter} explicitly..
*
* @param ignoreColumnMetaData
* @param ignoreColumnMetaData Defaults to <code>false</code>.
*/
public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) {
this.executor.setIgnoreColumnMetaData(ignoreColumnMetaData);
}
/**
* Indicates the procedure's return value should be included in the results
* returned.
*
* @param returnValueRequired
*/
public void setReturnValueRequired(boolean returnValueRequired) {
this.executor.setReturnValueRequired(returnValueRequired);
}
/**
* Custom Stored Procedure parameters that may contain static values
* or Strings representing an {@link Expression}.
*/
public void setProcedureParameters(List<ProcedureParameter> procedureParameters) {
this.executor.setProcedureParameters(procedureParameters);
}
/**
* 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.
* 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);
@@ -204,26 +223,45 @@ public class StoredProcPollingChannelAdapter extends IntegrationObjectSupport im
/**
* 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
* 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.
*
*
* 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
*
* 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;
}
/**
* If this variable is set to <code>true</code> then all results from a stored
* procedure call that don't have a corresponding {@link SqlOutParameter}
* declaration will be bypassed.
*
* E.g. Stored Procedures may return an update count value, even though your
* Stored Procedure only declared a single result parameter. The exact behavior
* depends on the used database.
*
* The value is set on the underlying {@link JdbcTemplate}.
*
* Only few developers will probably ever like to process update counts, thus
* the value defaults to <code>true</code>.
*
*/
public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
this.executor.setSkipUndeclaredResults(skipUndeclaredResults);
}
}

View File

@@ -1,11 +1,11 @@
/*
* 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.
@@ -26,7 +26,7 @@ import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*
*/
public class StoredProcMessageHandlerParser extends AbstractOutboundChannelAdapterParser {
@@ -43,30 +43,30 @@ public class StoredProcMessageHandlerParser extends AbstractOutboundChannelAdapt
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);
builder.addConstructorArgValue(storedProcedureName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-column-meta-data");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "use-payload-as-parameter-source");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "sql-parameter-source-factory");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
if (!procedureParameterList.isEmpty()) {
builder.addPropertyValue("procedureParameters", procedureParameterList);
}
if (!sqlParameterDefinitionList.isEmpty()) {
builder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
}
return builder.getBeanDefinition();
}
}

View File

@@ -1,11 +1,11 @@
/*
* 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.
@@ -27,10 +27,10 @@ import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*
*/
public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointParser {
protected boolean shouldGenerateId() {
return false;
}
@@ -47,18 +47,18 @@ public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointPar
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");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "use-payload-as-parameter-source");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, gatewayElement, "sql-parameter-source-factory");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, gatewayElement, "skip-undeclared-results");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(gatewayElement, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(gatewayElement, parserContext);
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(gatewayElement, parserContext);
@@ -85,5 +85,5 @@ public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointPar
protected String getInputChannelAttributeName() {
return "request-channel";
}
}

View File

@@ -1,11 +1,11 @@
/*
* 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.
@@ -27,10 +27,10 @@ import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
* @since 2.1
*
*
*/
public class StoredProcPollingChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
protected boolean shouldGenerateId() {
return false;
}
@@ -41,20 +41,21 @@ public class StoredProcPollingChannelAdapterParser extends AbstractPollingInboun
@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");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "skip-undeclared-results");
final ManagedList<BeanDefinition> procedureParameterList = StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
final ManagedList<BeanDefinition> sqlParameterDefinitionList = StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
@@ -68,9 +69,9 @@ public class StoredProcPollingChannelAdapterParser extends AbstractPollingInboun
if (!returningResultsetMap.isEmpty()) {
builder.addPropertyValue("returningResultSetRowMappers", returningResultsetMap);
}
return builder.getBeanDefinition();
}
}

View File

@@ -256,7 +256,7 @@
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. The input is the whole
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
@@ -325,7 +325,7 @@
supplied here, or (if keys-generated="true") can be the
primary keys generated from an auto-increment, or else just a
count of the number of rows affected by the update. The response
is in general a case insensitive Map (or list of maps if multi-valued), unless
is in general a case insensitive Map (or list of maps if multi-valued), unless
a select query and a row-mapper is provided. If the update count is
returned then the map key is "UPDATE".
</xsd:documentation>
@@ -365,7 +365,7 @@
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. The input is the whole
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
@@ -381,7 +381,7 @@
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. The input is the whole
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
@@ -568,12 +568,12 @@
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
@@ -581,16 +581,16 @@
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
@@ -613,21 +613,21 @@
<xsd:appinfo>
<xsd:documentation>
<![CDATA[
If set to 'true', the payload of the Message will be used
as a source for providing parameters. If false the entire
Message will be available as a source for parameters.
If no Procedure Parameters are passed in, this property
will default to 'true'. This means that using a default
BeanPropertySqlParameterSourceFactory the bean properties
of the payload will be used as a source for parameter
If set to 'true', the payload of the Message will be used
as a source for providing parameters. If false the entire
Message will be available as a source for parameters.
If no Procedure Parameters are passed in, this property
will default to 'true'. This means that using a default
BeanPropertySqlParameterSourceFactory the bean properties
of the payload will be used as a source for parameter
values for the to-be-executed Stored Procedure or Function.
However, if Procedure Parameters are passed in, then this
property will by default evaluate to 'false'. ProcedureParameter
allow for SpEl Expressions to be provided and therefore
it is highly beneficial to have access to the entire Message.
]]>
However, if Procedure Parameters are passed in, then this
property will by default evaluate to 'false'. ProcedureParameter
allow for SpEl Expressions to be provided and therefore
it is highly beneficial to have access to the entire Message.
]]>
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
@@ -704,12 +704,12 @@
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
generally need not be declared as for those
databases the type information can be
retrieved from the JDBC Metadata.
generally need not be declared as for those
databases the type information can be
retrieved from the JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
@@ -717,27 +717,27 @@
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:element>
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded"
type="parameterSubElementType">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Provides a mechanism to provide stored procedure
parameters. Parameters can be either static
parameters. Parameters can be either static
or provided using a SpEL Expression.
]]>
</xsd:documentation>
@@ -748,7 +748,7 @@
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Storeed procedured may return multiple resultsets.
Stored procedures may return multiple resultsets.
]]>
</xsd:documentation>
</xsd:annotation>
@@ -761,28 +761,28 @@
<xsd:appinfo>
<xsd:documentation>
<![CDATA[
If set to 'true', the payload of the Message will be used
as a source for providing parameters. If false the entire
Message will be available as a source for parameters.
If no Procedure Parameters are passed in, this property
will default to 'true'. This means that using a default
BeanPropertySqlParameterSourceFactory the bean properties
of the payload will be used as a source for parameter
If set to 'true', the payload of the Message will be used
as a source for providing parameters. If false the entire
Message will be available as a source for parameters.
If no Procedure Parameters are passed in, this property
will default to 'true'. This means that using a default
BeanPropertySqlParameterSourceFactory the bean properties
of the payload will be used as a source for parameter
values for the to-be-executed Stored Procedure or Function.
However, if Procedure Parameters are passed in, then this
property will by default evaluate to 'false'. ProcedureParameter
allow for SpEl Expressions to be provided and therefore
it is highly beneficial to have access to the entire Message.
]]>
However, if Procedure Parameters are passed in, then this
property will by default evaluate to 'false'. ProcedureParameter
allow for SpEl Expressions to be provided and therefore
it is highly beneficial to have access to the entire Message.
]]>
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="sql-parameter-source-factory"
type="xsd:string">
<xsd:annotation>
@@ -800,7 +800,7 @@
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="is-function" default="false">
<xsd:annotation>
<xsd:documentation>
@@ -813,29 +813,51 @@
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="skip-undeclared-results" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
If this attribute is set to 'true', then all results from
a stored procedure call that don't have a corresponding
'SqlOutParameter' declaration will be bypassed.
E.g. Stored Procedures may return an update count value,
even though your Stored Procedure only declared a single
result parameter. The exact behavior depends on the used
database.
The value is set on the underlying 'JdbcTemplate'.
Only few developers will probably ever like to process
update counts, thus the value defaults to 'true'.]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="expect-single-result" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
This parameter indicates that only one result object shall be returned from
the Stored Procedure/Function Call. If set to true and the result map
the Stored Procedure/Function Call. If set to true and the result map
from the Stored Procedure/Function Call contains only 1 element,
then that 1 element is extracted and returned as payload.
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
payload.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
The H2 database, for example, does not fully support the CallableStatement
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
you may end up with a collection being returned.
]]>
</xsd:documentation>
@@ -843,7 +865,7 @@
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="request-channel" type="xsd:string"
use="required">
<xsd:annotation>
@@ -877,8 +899,8 @@
<xsd:attribute name="return-value-required" default="false">
<xsd:annotation>
<xsd:documentation>
Indicates whether this procedure's return value
should be included.
Indicates the procedure's return value should be included
in the results returned.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
@@ -905,12 +927,12 @@
<xsd:documentation>
<![CDATA[
For fully supported database these parameters
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
need not be declared as for those database the
type information can be retrieved from the
JDBC Metadata.
Fully Supported Databases (Stored Procedures):
* Apache Derby
* DB2
* MySQL
@@ -918,20 +940,20 @@
* Oracle
* PostgreSQL
* Sybase
Fully Supported Databases (Functions)
* MySQL
* Microsoft SQL Server
* Oracle
* PostgreSQL
If you use a database not listed above, you
MUST provide Sql Parameter Definitions.
MUST provide Sql Parameter Definitions.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:element>
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded"
type="parameterSubElementType">
<xsd:annotation>
@@ -967,29 +989,51 @@
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="skip-undeclared-results" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
If this attribute is set to 'true', then all results from
a stored procedure call that don't have a corresponding
'SqlOutParameter' declaration will be bypassed.
E.g. Stored Procedures may return an update count value,
even though your Stored Procedure only declared a single
result parameter. The exact behavior depends on the used
database.
The value is set on the underlying 'JdbcTemplate'.
Only few developers will probably ever like to process
update counts, thus the value defaults to 'true'.]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="expect-single-result" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
This parameter indicates that only one result object shall be returned from
the Stored Procedure/Function Call. If set to true and the result map
the Stored Procedure/Function Call. If set to true and the result map
from the Stored Procedure/Function Call contains only 1 element,
then that 1 element is extracted and returned as payload.
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
If the result map contains more than 1 element and
expect-single-result is true, then a MessagingException
is thrown.
Otherwise the complete result map is returned as the
payload.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
Important Note: Several databases such as H2 are not
fully supported for Stored Procedure and/oir Function calls.
The H2 database, for example, does not fully support the CallableStatement
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
semantics and when executing function calls against H2, a result list is
returned, rather than a single value.
Therefore, even if you set expect-single-result = true,
you may end up with a collection being returned.
]]>
</xsd:documentation>
@@ -1003,7 +1047,7 @@
<xsd:documentation>
Channel to which polled messages will be send. If the stored
procedure or function does not return any data, the payload
of the Message will be Null.
of the Message will be Null.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
@@ -1043,7 +1087,7 @@
<xsd:attribute name="auto-startup" type="xsd:string" default="true" use="optional">
<xsd:annotation>
<xsd:documentation>
Flag to indicate that the poller should start automatically
Flag to indicate that the poller should start automatically
on startup (default true).
</xsd:documentation>
</xsd:annotation>
@@ -1052,7 +1096,7 @@
<xsd:annotation>
<xsd:documentation>
If true, the JDBC parameter definitions for the stored procedure
are not automatically derived from the underlying JDBC connection. In
are not automatically derived from the underlying JDBC connection. In
that case you must specify all Sql parameter definitions explicitly
using the 'sql-parameter-definition' sub-element.
</xsd:documentation>
@@ -1061,20 +1105,20 @@
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:complexType name="parameterSubElementType">
</xsd:attributeGroup>
<xsd:complexType name="parameterSubElementType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of stored procedure or function parameter.
The name of stored procedure or function parameter.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="value" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The value of the parameter. Either this or the 'expression'
The value of the parameter. Either this or the 'expression'
attribute must be provided.
]]></xsd:documentation>
</xsd:annotation>
@@ -1083,11 +1127,11 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The type of the value used. If nothing is provided this attribute
will default to java.lang.String. This attribute is not used
will default to java.lang.String. This attribute is not used
when the 'expression' attribute is used instead.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -1097,24 +1141,24 @@
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="returningResultSetRowMappersType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the under which the resultset will be returned.
The name of the under which the resultset will be returned.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="row-mapper" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The fully qualified class name of the row mapper.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="sqlParameterDefinitionType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
@@ -1126,38 +1170,38 @@
<xsd:attribute name="direction" use="optional" default="IN">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the direction of the Sql parameter definition. Defaults
to 'IN'. If your procedure is returning ResultSets, please
use the 'returning-resultset' element.
Specifies the direction of the Sql parameter definition. Defaults
to 'IN'. If your procedure is returning ResultSets, please
use the 'returning-resultset' element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="sqlTypeDirection xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="type">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Sql type used for this Sql parameter defintion. Will translate
into the integer value as defined by java.sql.Types. Alternatively
you can provide the integer value as well. If this attribute is
you can provide the integer value as well. If this attribute is
not explicitly set, then it will default to 'VARCHAR'.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="sqlType xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="scale" type="xsd:integer" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scale of the Sql parameter. Only used for numeric and decimal
parameters.
parameters.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="sqlType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="VARCHAR"/>
@@ -1198,12 +1242,12 @@
<xsd:enumeration value="VARBINARY"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="sqlTypeDirection">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="IN"/>
<xsd:enumeration value="OUT"/>
<xsd:enumeration value="INOUT"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:simpleType>
</xsd:schema>

View File

@@ -16,6 +16,15 @@
package org.springframework.integration.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.integration.test.matcher.PayloadAndHeaderMatcher.sameExceptIgnorableHeaders;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -41,16 +50,6 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.integration.test.matcher.PayloadAndHeaderMatcher.sameExceptIgnorableHeaders;
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class JdbcMessageStoreTests {

View File

@@ -1,3 +1,18 @@
/*
* 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;
@@ -20,90 +35,90 @@ public class StoredProcExecutorTest {
@Test
public void testStoredProcExecutorWithNullDataSource() {
try {
new StoredProcExecutor(null, "storedProcedureName");
} catch (IllegalArgumentException e) {
assertEquals("dataSource must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testStoredProcExecutorWithNullProcedureName() {
DataSource datasource = mock(DataSource.class);
try {
new StoredProcExecutor(datasource, null);
} catch (IllegalArgumentException e) {
assertEquals("storedProcedureName must not be null and cannot be empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testStoredProcExecutorWithEmptyProcedureName() {
DataSource datasource = mock(DataSource.class);
try {
new StoredProcExecutor(datasource, " ");
} catch (IllegalArgumentException e) {
assertEquals("storedProcedureName must not be null and cannot be empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithNullMap() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
try {
storedProcExecutor.setReturningResultSetRowMappers(null);
} catch (IllegalArgumentException e) {
assertEquals("returningResultSetRowMappers must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithMapContainingNullValues() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
Map<String, RowMapper<?>> rowmappers = new HashMap<String, RowMapper<?>>();
rowmappers.put("results", null);
try {
storedProcExecutor.setReturningResultSetRowMappers(rowmappers);
} catch (IllegalArgumentException e) {
assertEquals("The provided map cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetReturningResultSetRowMappersWithEmptyMap() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
Map<String, RowMapper<?>> rowmappers = new HashMap<String, RowMapper<?>>();
storedProcExecutor.setReturningResultSetRowMappers(rowmappers);
@@ -111,7 +126,7 @@ public class StoredProcExecutorTest {
//Should Successfully finish
}
@Test
public void testSetSqlParameterSourceFactoryWithNullParameter() {
DataSource datasource = mock(DataSource.class);
@@ -123,53 +138,53 @@ public class StoredProcExecutorTest {
assertEquals("sqlParameterSourceFactory must not be null.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithNullValueInList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<SqlParameter> sqlParameters = new ArrayList<SqlParameter>();
sqlParameters.add(null);
try {
storedProcExecutor.setSqlParameters(sqlParameters);
} catch (IllegalArgumentException e) {
assertEquals("The provided list (sqlParameters) cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithEmptyList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<SqlParameter> sqlParameters = new ArrayList<SqlParameter>();
try {
storedProcExecutor.setSqlParameters(sqlParameters);
} catch (IllegalArgumentException e) {
assertEquals("sqlParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetSqlParametersWithNullList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
@@ -179,53 +194,53 @@ public class StoredProcExecutorTest {
assertEquals("sqlParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithNullValueInList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
procedureParameters.add(null);
try {
storedProcExecutor.setProcedureParameters(procedureParameters);
} catch (IllegalArgumentException e) {
assertEquals("The provided list (procedureParameters) cannot contain null values.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithEmptyList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
List<ProcedureParameter> procedureParameters = new ArrayList<ProcedureParameter>();
try {
storedProcExecutor.setProcedureParameters(procedureParameters);
} catch (IllegalArgumentException e) {
assertEquals("procedureParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
@Test
public void testSetProcedureParametersWithNullList() {
DataSource datasource = mock(DataSource.class);
StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource, "storedProcedureName");
@@ -235,9 +250,9 @@ public class StoredProcExecutorTest {
assertEquals("procedureParameters must not be null or empty.", e.getMessage());
return;
}
fail("Exception expected.");
}
}

View File

@@ -21,7 +21,6 @@ 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;

View File

@@ -14,6 +14,7 @@
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -60,6 +61,19 @@ public class StoredProcOutboundGatewayParserTests {
assertEquals("Wrong stored procedure name", "GET_PRIME_NUMBERS", storedProcedureName);
}
@Test
public void testSkipUndeclaredResultsAttributeSet() 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);
boolean skipUndeclaredResults = (Boolean) accessor.getPropertyValue("skipUndeclaredResults");
assertFalse(skipUndeclaredResults);
}
@Test
public void testProcedurepParametersAreSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());

View File

@@ -60,6 +60,19 @@ public class StoredProcPollingChannelAdapterParserTests {
assertEquals("Wrong stored procedure name", "GET_PRIME_NUMBERS", storedProcedureName);
}
@Test
public void testSkipUndeclaredResultsAttributeSet() 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);
boolean skipUndeclaredResults = (Boolean) accessor.getPropertyValue("skipUndeclaredResults");
assertTrue("skipUndeclaredResults was not set and should default to 'true'", skipUndeclaredResults);
}
@Test
public void testProcedurepParametersAreSet() throws Exception {
setUp("storedProcPollingChannelAdapterParserTest.xml", getClass());

View File

@@ -11,7 +11,7 @@
<int:channel id="requestChannel"/>
<int:channel id="replyChannel"/>
<jdbc:embedded-database id="datasource" type="HSQL"/>
<int-jdbc:stored-proc-outbound-gateway request-channel="requestChannel" stored-procedure-name="GET_PRIME_NUMBERS" data-source="datasource"
@@ -19,15 +19,16 @@
id="storedProcedureOutboundGateway"
ignore-column-meta-data="false"
is-function="false"
skip-undeclared-results="false"
order="2"
reply-channel="replyChannel"
request-timeout="555"
return-value-required="false">
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR"/>
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5"/>
<int-jdbc:sql-parameter-definition name="description" />
<int-jdbc:sql-parameter-definition name="description" />
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
<int-jdbc:parameter name="password" expression="payload.username"/>
@@ -35,6 +36,6 @@
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
<int:poller default="true" fixed-rate="10000"/>
</beans>

View File

@@ -1,3 +1,18 @@
/*
* 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 interface CreateUser {

View File

@@ -1,3 +1,18 @@
/*
* 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 static org.junit.Assert.assertEquals;
@@ -14,7 +29,7 @@ public class ProcedureParameterTest {
@Test
public void testProcedureParameterStringObjectString() {
try {
new ProcedureParameter(null, "value", "expression");
} catch(IllegalArgumentException e) {
@@ -28,58 +43,58 @@ public class ProcedureParameterTest {
@Test
public void testConvertExpressions() {
List<ProcedureParameter> procedureParameters = getProcedureParameterList();
Map<String, String> expressionParameters =
Map<String, String> expressionParameters =
ProcedureParameter.convertExpressions(procedureParameters);
assertTrue("Expected 2 expression parameters.", expressionParameters.size() == 2);
}
@Test
public void testConvertStaticParameters() {
List<ProcedureParameter> procedureParameters = getProcedureParameterList();
Map<String, Object> staticParameters =
Map<String, Object> staticParameters =
ProcedureParameter.convertStaticParameters(procedureParameters);
assertTrue("Expected 3 static parameters.", staticParameters.size() == 3);
}
@Test
public void testConvertStaticParametersWithNullValueInList() {
List<ProcedureParameter> procedureParameters = getProcedureParameterList();
procedureParameters.add(1, null);
try {
ProcedureParameter.convertStaticParameters(procedureParameters);
} catch(IllegalArgumentException e) {
assertEquals("'procedureParameters' must not contain null values.", e.getMessage());
return;
}
fail("Expected Exception");
}
@Test
public void testConvertExpressionParametersWithNullValueInList() {
List<ProcedureParameter> procedureParameters = getProcedureParameterList();
procedureParameters.add(1, null);
try {
ProcedureParameter.convertExpressions(procedureParameters);
} catch(IllegalArgumentException e) {
assertEquals("'procedureParameters' must not contain null values.", e.getMessage());
return;
}
fail("Expected Exception");
}
private List<ProcedureParameter> getProcedureParameterList() {
List<ProcedureParameter> procedureParameterList = new ArrayList<ProcedureParameter>();
procedureParameterList.add(new ProcedureParameter("param1", "value1", null));
procedureParameterList.add(new ProcedureParameter("param2", "value1", null));