INT-2739: StoredProc: 'row-mapper' as a Bean Ref
* Convert `row-mapper` attribute of stored procedure components to bean reference * Class name is also supported for backward compatibility JIRA: https://jira.springsource.org/browse/INT-2739
This commit is contained in:
committed by
Gary Russell
parent
f42f6eca57
commit
7f34f8c919
@@ -13,7 +13,9 @@
|
||||
|
||||
package org.springframework.integration.jdbc.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -23,7 +25,6 @@ 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
|
||||
@@ -47,7 +48,8 @@ public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointPar
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(storedProcExecutorBuilder, element, "sql-parameter-source-factory");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(storedProcExecutorBuilder, element, "skip-undeclared-results");
|
||||
|
||||
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
|
||||
final ManagedMap<String, BeanMetadataElement> returningResultsetMap =
|
||||
StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
|
||||
|
||||
if (!returningResultsetMap.isEmpty()) {
|
||||
storedProcExecutorBuilder.addPropertyValue("returningResultSetRowMappers", returningResultsetMap);
|
||||
|
||||
@@ -19,9 +19,14 @@ package org.springframework.integration.jdbc.config;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
@@ -36,9 +41,9 @@ import org.springframework.jdbc.core.SqlInOutParameter;
|
||||
import org.springframework.jdbc.core.SqlOutParameter;
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
@@ -203,21 +208,31 @@ public final class StoredProcParserUtils {
|
||||
* @param storedProcComponent
|
||||
* @param parserContext
|
||||
*/
|
||||
public static ManagedMap<String, BeanDefinition> getReturningResultsetBeanDefinitions(
|
||||
public static ManagedMap<String, BeanMetadataElement> getReturningResultsetBeanDefinitions(
|
||||
Element storedProcComponent, ParserContext parserContext) {
|
||||
|
||||
List<Element> returningResultsetChildElements = DomUtils.getChildElementsByTagName(storedProcComponent, "returning-resultset");
|
||||
|
||||
ManagedMap<String, BeanDefinition> returningResultsetMap = new ManagedMap<String, BeanDefinition>();
|
||||
ManagedMap<String, BeanMetadataElement> returningResultsetMap = new ManagedMap<String, BeanMetadataElement>();
|
||||
|
||||
for (Element childElement : returningResultsetChildElements) {
|
||||
|
||||
String name = childElement.getAttribute("name");
|
||||
String rowMapperAsString = childElement.getAttribute("row-mapper");
|
||||
|
||||
BeanDefinitionBuilder rowMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(rowMapperAsString);
|
||||
BeanMetadataElement rowMapperBeanDefinition = null;
|
||||
|
||||
returningResultsetMap.put(name, rowMapperBuilder.getBeanDefinition());
|
||||
try {
|
||||
// Backward compatibility
|
||||
ClassUtils.forName(rowMapperAsString, parserContext.getReaderContext().getBeanClassLoader());
|
||||
rowMapperBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(rowMapperAsString).getBeanDefinition();
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
//Ignore it and fallback to bean reference
|
||||
rowMapperBeanDefinition = new RuntimeBeanReference(rowMapperAsString);
|
||||
}
|
||||
|
||||
returningResultsetMap.put(name, rowMapperBeanDefinition);
|
||||
}
|
||||
|
||||
return returningResultsetMap;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 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
|
||||
@@ -13,8 +13,9 @@
|
||||
|
||||
package org.springframework.integration.jdbc.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -23,7 +24,6 @@ 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
|
||||
@@ -51,7 +51,8 @@ public class StoredProcPollingChannelAdapterParser extends AbstractPollingInboun
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(storedProcExecutorBuilder, element, "is-function");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(storedProcExecutorBuilder, element, "skip-undeclared-results");
|
||||
|
||||
final ManagedMap<String, BeanDefinition> returningResultsetMap = StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
|
||||
final ManagedMap<String, BeanMetadataElement> returningResultsetMap =
|
||||
StoredProcParserUtils.getReturningResultsetBeanDefinitions(element, parserContext);
|
||||
|
||||
if (!returningResultsetMap.isEmpty()) {
|
||||
storedProcExecutorBuilder.addPropertyValue("returningResultSetRowMappers", returningResultsetMap);
|
||||
|
||||
@@ -1274,9 +1274,15 @@
|
||||
</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:appinfo>
|
||||
<xsd:documentation>
|
||||
Reference to a row mapper to use to convert
|
||||
JDBC result set rows to message payloads.
|
||||
</xsd:documentation>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.jdbc.core.RowMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<int:channel id="target"/>
|
||||
<jdbc:embedded-database id="dataSource" type="HSQL"/>
|
||||
|
||||
<int-jdbc:stored-proc-inbound-channel-adapter id="storedProcedurePollingChannelAdapter"
|
||||
data-source="dataSource" channel="target"
|
||||
stored-procedure-name="GET_PRIME_NUMBERS"
|
||||
is-function="false">
|
||||
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR"/>
|
||||
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
|
||||
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5"/>
|
||||
<int-jdbc:sql-parameter-definition name="description" />
|
||||
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
|
||||
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
|
||||
<int-jdbc:parameter name="password" expression="payload.username"/>
|
||||
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
|
||||
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
|
||||
|
||||
</int-jdbc:stored-proc-inbound-channel-adapter>
|
||||
|
||||
<int:poller default="true" fixed-rate="10000"/>
|
||||
|
||||
<int-jdbc:stored-proc-inbound-channel-adapter id="autoChannel"
|
||||
data-source="dataSource"
|
||||
stored-procedure-name="GET_PRIME_NUMBERS"
|
||||
is-function="false">
|
||||
<int-jdbc:sql-parameter-definition name="username" direction="IN" type="VARCHAR" />
|
||||
<int-jdbc:sql-parameter-definition name="password" direction="OUT" />
|
||||
<int-jdbc:sql-parameter-definition name="age" direction="INOUT" type="INTEGER" scale="5" />
|
||||
<int-jdbc:sql-parameter-definition name="description" />
|
||||
<int-jdbc:parameter name="username" value="kenny" type="java.lang.String"/>
|
||||
<int-jdbc:parameter name="description" value="Who killed Kenny?"/>
|
||||
<int-jdbc:parameter name="password" expression="payload.username"/>
|
||||
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
|
||||
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
|
||||
|
||||
</int-jdbc:stored-proc-inbound-channel-adapter>
|
||||
|
||||
<int:bridge input-channel="autoChannel" output-channel="nullChannel" />
|
||||
|
||||
</beans>
|
||||
@@ -21,12 +21,14 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
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;
|
||||
@@ -40,10 +42,13 @@ import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.SqlInOutParameter;
|
||||
import org.springframework.jdbc.core.SqlOutParameter;
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.core.simple.ParameterizedSingleColumnRowMapper;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
@@ -200,12 +205,18 @@ public class StoredProcPollingChannelAdapterParserTests {
|
||||
|
||||
Map<String, RowMapper<?>> returningResultSetRowMappersAsMap = (Map<String, RowMapper<?>>) returningResultSetRowMappers;
|
||||
|
||||
assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 1", returningResultSetRowMappersAsMap.size() == 1);
|
||||
assertTrue("The rowmapper was not set. Expected returningResultSetRowMappersAsMap.size() == 2",
|
||||
returningResultSetRowMappersAsMap.size() == 2);
|
||||
|
||||
Entry<String, ?> mapEntry1 = returningResultSetRowMappersAsMap.entrySet().iterator().next();
|
||||
Iterator<Entry<String,RowMapper<?>>> iterator = returningResultSetRowMappersAsMap.entrySet().iterator();
|
||||
|
||||
assertEquals("out", mapEntry1.getKey());
|
||||
assertTrue(mapEntry1.getValue() instanceof PrimeMapper);
|
||||
Entry<String, ?> mapEntry = iterator.next();
|
||||
assertEquals("out", mapEntry.getKey());
|
||||
assertTrue(mapEntry.getValue() instanceof PrimeMapper);
|
||||
|
||||
mapEntry = iterator.next();
|
||||
assertEquals("out2", mapEntry.getKey());
|
||||
assertTrue(mapEntry.getValue() instanceof ParameterizedSingleColumnRowMapper);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,14 @@
|
||||
<int-jdbc:parameter name="password" expression="payload.username"/>
|
||||
<int-jdbc:parameter name="age" value="30" type="java.lang.Integer"/>
|
||||
<int-jdbc:returning-resultset name="out" row-mapper="org.springframework.integration.jdbc.storedproc.PrimeMapper"/>
|
||||
|
||||
<int-jdbc:returning-resultset name="out2" row-mapper="longSingleColumnRowMapper"/>
|
||||
</int-jdbc:stored-proc-inbound-channel-adapter>
|
||||
|
||||
<bean id="longSingleColumnRowMapper" class="org.springframework.jdbc.core.simple.ParameterizedSingleColumnRowMapper"
|
||||
factory-method="newInstance">
|
||||
<constructor-arg value="java.lang.Long"/>
|
||||
</bean>
|
||||
|
||||
<int:poller default="true" fixed-rate="10000"/>
|
||||
|
||||
<int-jdbc:stored-proc-inbound-channel-adapter id="autoChannel"
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-stored-proc-sql-return-type">
|
||||
<title>SqlReturnType support for Stored Procedure components</title>
|
||||
<title>Stored Procedure Components Improvements</title>
|
||||
<para>
|
||||
For more complex database-specific types, not supported by the standard
|
||||
<code>CallableStatement.getObject</code> method, 2 new additional
|
||||
@@ -270,7 +270,15 @@
|
||||
<listitem><emphasis>return-type</emphasis></listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
For more information see <xref linkend="stored-procedures"/>.
|
||||
<para>
|
||||
The <code>row-mapper</code> attribute of the Stored Procedure Inbound Channel Adapter
|
||||
<code><returning-resultset/></code> sub-element
|
||||
now supports a reference to a <interfacename>RowMapper</interfacename> bean
|
||||
definition. Previously, it contained just a class name (which is still supported).
|
||||
</para>
|
||||
<para>
|
||||
For more information see <xref linkend="stored-procedures"/>.
|
||||
</para>
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-event-for-imap-idle">
|
||||
|
||||
Reference in New Issue
Block a user