INT-1983 - Add JPA Adapter
For reference see: https://jira.springsource.org/browse/INT-1983 * INT-2435 - Add the ability to automatically resolve the entity-class from the payload as fallback * Add <transactional/> support for **Jpa Outbound Gateway** and **Jpa Outbound Channel Adapter** * Merging Documentation from: https://github.com/amolnayak311/spring-integration/blob/INT-2440/src/reference/docbook/jpa.xml * Provide JPA Tests against Hibernate, EclipseLink and OpenJPA * Improve Documentation * Remove trailing white-space, convert white-space to tabs, remove @transactional from DefaultJpaOperations * INT-2440 Adding the documentation for the JPA adapters INT-1983 - Code Review based Fixes * Fix indentation in XML Schema * Remove *transactional* sub-element definition from JPA Inbound Channel Adapter in XML Schema * Fix enumeration *gatewayType* INT-1983 - Based on Code Review * Remove '/** {@inheritDoc} */' from DefaultJpaOperations * Remove JavaDoc parameters that don't contains details * Cleanup *JpaUtils* * Remove "transaction-manager-ref" from *spring-integration-jpa-2.2.xsd* * Cleanup *spring-integration-jpa-2.2.xsd* * Provide documentation to *EclipseLinkJpaOperationsTests* on how to run tests in IDE * Provide documentation to *OpenJpaJpaOperationsTests* on how to run tests in IDE * Refactor JPA Reference Doc Chapter (work in progress) INT-1983 - Code Review: provide better JavaDoc
This commit is contained in:
committed by
Oleg Zhurakousky
parent
6c2f3d8dd0
commit
16f48a12e6
47
build.gradle
47
build.gradle
@@ -74,6 +74,8 @@ subprojects { subproject ->
|
||||
// and http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.ConfigurationContainer.html
|
||||
configurations {
|
||||
jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
|
||||
javaAgentSpringInstrument //Configuration Group used by the JPA Adapter during test execution
|
||||
javaAgentOpenJpa //Configuration Group used by the JPA Adapter during test execution
|
||||
}
|
||||
|
||||
// dependencies that are common across all java projects
|
||||
@@ -491,6 +493,51 @@ project('spring-integration-jmx') {
|
||||
}
|
||||
}
|
||||
|
||||
project('spring-integration-jpa') {
|
||||
description = 'Spring Integration JPA Support'
|
||||
dependencies {
|
||||
compile project(":spring-integration-core")
|
||||
compile "org.springframework:spring-aop:$springVersion"
|
||||
compile "org.springframework:spring-orm:$springVersion"
|
||||
compile "org.springframework:spring-tx:$springVersion"
|
||||
compile "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final"
|
||||
|
||||
testCompile project(":spring-integration-test")
|
||||
testCompile "com.h2database:h2:1.3.166"
|
||||
testCompile "hsqldb:hsqldb:1.8.0.10"
|
||||
testCompile "org.apache.derby:derby:10.5.3.0_1"
|
||||
testCompile "org.aspectj:aspectjrt:$aspectjVersion"
|
||||
testCompile "org.aspectj:aspectjweaver:$aspectjVersion"
|
||||
|
||||
testCompile "org.hibernate:hibernate-entitymanager:4.0.1.Final"
|
||||
testCompile "org.eclipse.persistence:org.eclipse.persistence.jpa:2.3.2"
|
||||
testCompile "org.apache.openjpa:openjpa:2.2.0"
|
||||
|
||||
javaAgentSpringInstrument "org.springframework:spring-instrument:$springVersion"
|
||||
javaAgentOpenJpa "org.apache.openjpa:openjpa:2.2.0"
|
||||
}
|
||||
|
||||
bundlor {
|
||||
bundleSymbolicName = 'org.springframework.integration.jpa'
|
||||
importTemplate += [
|
||||
'org.springframework.integration.*;version="[2.1.0, 2.1.1)"',
|
||||
'org.springframework.*;version="[3.0.5, 4.0.0)"',
|
||||
'org.apache.commons.logging;version="[1.1.1, 2.0.0)"',
|
||||
'org.aopalliance.*;version="[1.0.0, 2.0.0)"',
|
||||
'javax.persistence.*;version="[1.0.0, 2.0.0)"',
|
||||
'javax.sql.*;version="0"',
|
||||
'org.w3c.dom.*;version="0"'
|
||||
]
|
||||
}
|
||||
|
||||
test.doFirst {
|
||||
String jvmArgsSpringIntrument = "-javaagent:${configurations.javaAgentSpringInstrument.asPath}"
|
||||
String jvmArgsOpenJpa = "-javaagent:${configurations.javaAgentOpenJpa.files.iterator().next()}"
|
||||
jvmArgs jvmArgsSpringIntrument , jvmArgsOpenJpa
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
project('spring-integration-mail') {
|
||||
description = 'Spring Integration Mail Support'
|
||||
dependencies {
|
||||
|
||||
@@ -13,6 +13,7 @@ include 'spring-integration-ip'
|
||||
include 'spring-integration-jdbc'
|
||||
include 'spring-integration-jms'
|
||||
include 'spring-integration-jmx'
|
||||
include 'spring-integration-jpa'
|
||||
include 'spring-integration-mail'
|
||||
include 'spring-integration-mongodb'
|
||||
include 'spring-integration-redis'
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
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.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
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.jpa.inbound.JpaPollingChannelAdapter;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The JPA Inbound Channel adapter parser
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JpaInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser{
|
||||
|
||||
|
||||
protected BeanMetadataElement parseSource(Element element,
|
||||
ParserContext parserContext) {
|
||||
|
||||
final BeanDefinitionBuilder jpaExecutorBuilder = JpaParserUtils.getJpaExecutorBuilder(element, parserContext);
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "delete-after-poll");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "delete-per-row");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "expect-single-result");
|
||||
|
||||
final BeanDefinition jpaExecutorBuilderBeanDefinition = jpaExecutorBuilder.getBeanDefinition();
|
||||
final String jpaExecutorBeanName = BeanDefinitionReaderUtils.generateBeanName(jpaExecutorBuilderBeanDefinition, parserContext.getRegistry());
|
||||
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(jpaExecutorBuilderBeanDefinition, jpaExecutorBeanName));
|
||||
|
||||
final BeanDefinitionBuilder jpaPollingChannelAdapterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(JpaPollingChannelAdapter.class);
|
||||
|
||||
jpaPollingChannelAdapterBuilder.addConstructorArgReference(jpaExecutorBeanName);
|
||||
|
||||
return jpaPollingChannelAdapterBuilder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
|
||||
/**
|
||||
* The namespace handler for the JPA namespace
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaNamespaceHandler extends AbstractIntegrationNamespaceHandler {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
this.registerBeanDefinitionParser("inbound-channel-adapter", new JpaInboundChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("outbound-channel-adapter", new JpaOutboundChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("outbound-gateway", new JpaOutboundGatewayParser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
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;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
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.jpa.outbound.JpaOutboundGatewayFactoryBean;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The parser for JPA outbound channel adapter
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateIdAsFallback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
|
||||
final BeanDefinitionBuilder jpaExecutorBuilder = JpaParserUtils.getJpaExecutorBuilder(element, parserContext);
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "persist-mode");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "parameter-source-factory");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "use-payload-as-parameter-source");
|
||||
|
||||
|
||||
final BeanDefinition jpaExecutorBuilderBeanDefinition = jpaExecutorBuilder.getBeanDefinition();
|
||||
final String jpaExecutorBeanName = BeanDefinitionReaderUtils.generateBeanName(jpaExecutorBuilderBeanDefinition, parserContext.getRegistry());
|
||||
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(jpaExecutorBuilderBeanDefinition, jpaExecutorBeanName));
|
||||
|
||||
final BeanDefinitionBuilder jpaOutboundChannelAdapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(JpaOutboundGatewayFactoryBean.class);
|
||||
jpaOutboundChannelAdapterBuilder.addConstructorArgReference(jpaExecutorBeanName);
|
||||
jpaOutboundChannelAdapterBuilder.addPropertyValue("producesReply", Boolean.FALSE);
|
||||
|
||||
final Element transactionalElement = DomUtils.getChildElementByTagName(element, "transactional");
|
||||
|
||||
if(transactionalElement != null) {
|
||||
BeanDefinition txAdviceDefinition = JpaParserUtils.configureTransactionAttributes(transactionalElement);
|
||||
ManagedList<BeanDefinition> adviceChain = new ManagedList<BeanDefinition>();
|
||||
adviceChain.add(txAdviceDefinition);
|
||||
jpaOutboundChannelAdapterBuilder.addPropertyValue("adviceChain", adviceChain);
|
||||
}
|
||||
|
||||
return jpaOutboundChannelAdapterBuilder.getBeanDefinition();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
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.jpa.outbound.JpaOutboundGatewayFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The Parser for JPA Outbound Gateway, the MessageHandler implementation is same as the
|
||||
* outbound chanel adapter and hence we extend the class and setting the few additional
|
||||
* attributes that we wish to in the MessageSource
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
protected boolean shouldGenerateId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean shouldGenerateIdAsFallback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected BeanDefinitionBuilder parseHandler(Element gatewayElement, ParserContext parserContext) {
|
||||
|
||||
final BeanDefinitionBuilder jpaExecutorBuilder = JpaParserUtils.getJpaExecutorBuilder(gatewayElement, parserContext);
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "persist-mode");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "parameter-source-factory");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "use-payload-as-parameter-source");
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "delete-after-poll");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "delete-per-row");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, gatewayElement, "expect-single-result");
|
||||
|
||||
final BeanDefinition jpaExecutorBuilderBeanDefinition = jpaExecutorBuilder.getBeanDefinition();
|
||||
final String jpaExecutorBeanName = BeanDefinitionReaderUtils.generateBeanName(jpaExecutorBuilderBeanDefinition, parserContext.getRegistry());
|
||||
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(jpaExecutorBuilderBeanDefinition, jpaExecutorBeanName));
|
||||
|
||||
final BeanDefinitionBuilder jpaOutboundGatewayBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(JpaOutboundGatewayFactoryBean.class);
|
||||
|
||||
jpaOutboundGatewayBuilder.addConstructorArgReference(jpaExecutorBeanName);
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaOutboundGatewayBuilder, gatewayElement, "gateway-type");
|
||||
|
||||
final String replyChannel = gatewayElement.getAttribute("reply-channel");
|
||||
|
||||
if (StringUtils.hasText(replyChannel)) {
|
||||
jpaOutboundGatewayBuilder.addPropertyReference("outputChannel", replyChannel);
|
||||
}
|
||||
|
||||
final Element transactionalElement = DomUtils.getChildElementByTagName(gatewayElement, "transactional");
|
||||
|
||||
if(transactionalElement != null) {
|
||||
BeanDefinition txAdviceDefinition = JpaParserUtils.configureTransactionAttributes(transactionalElement);
|
||||
ManagedList<BeanDefinition> adviceChain = new ManagedList<BeanDefinition>();
|
||||
adviceChain.add(txAdviceDefinition);
|
||||
jpaOutboundGatewayBuilder.addPropertyValue("adviceChain", adviceChain);
|
||||
}
|
||||
|
||||
return jpaOutboundGatewayBuilder;
|
||||
|
||||
}
|
||||
|
||||
protected String getInputChannelAttributeName() {
|
||||
return "request-channel";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
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.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.endpoint.AbstractPollingEndpoint;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.support.JpaParameter;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The common method for generating the BeanDefinition for the common MessageHandler
|
||||
* is implemented in this class
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public final class JpaParserUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JpaParserUtils.class);
|
||||
|
||||
/** Prevent instantiation. */
|
||||
private JpaParserUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link BeanDefinitionBuilder} for the class {@link JpaExecutor}.
|
||||
* Initialize the wrapped {@link JpaExecutor} with common properties.
|
||||
*
|
||||
* @param element Must not be Null
|
||||
* @param parserContext Must not be Null
|
||||
* @return The BeanDefinitionBuilder for the JpaExecutor
|
||||
*/
|
||||
public static BeanDefinitionBuilder getJpaExecutorBuilder(final Element element,
|
||||
final ParserContext parserContext) {
|
||||
|
||||
Assert.notNull(element, "The provided element must not be Null.");
|
||||
Assert.notNull(parserContext, "The provided parserContext must not be Null.");
|
||||
|
||||
final Object source = parserContext.extractSource(element);
|
||||
|
||||
final BeanDefinitionBuilder jpaExecutorBuilder = BeanDefinitionBuilder.genericBeanDefinition(JpaExecutor.class);
|
||||
|
||||
int attributeCount = 0;
|
||||
|
||||
final String entityManagerRef = element.getAttribute("entity-manager");
|
||||
final String entityManagerFactoryRef = element.getAttribute("entity-manager-factory");
|
||||
final String jpaOperationsRef = element.getAttribute("jpa-operations");
|
||||
|
||||
if (StringUtils.hasText(jpaOperationsRef)) {
|
||||
attributeCount++;
|
||||
jpaExecutorBuilder.addConstructorArgReference(jpaOperationsRef);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(entityManagerRef)) {
|
||||
|
||||
if (attributeCount > 0) {
|
||||
parserContext.getReaderContext().error("Exactly only one of the attributes 'entity-manager' or " +
|
||||
"'entity-manager-factory' or 'jpa-operations' must be be set.", source);
|
||||
}
|
||||
|
||||
attributeCount++;
|
||||
jpaExecutorBuilder.addConstructorArgReference(entityManagerRef);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(entityManagerFactoryRef)) {
|
||||
|
||||
if (attributeCount > 0) {
|
||||
parserContext.getReaderContext().error("Exactly only one of the attributes 'entity-manager' or " +
|
||||
"'entity-manager-factory' or 'jpa-operations' must be be set.", source);
|
||||
}
|
||||
|
||||
attributeCount++;
|
||||
jpaExecutorBuilder.addConstructorArgReference(entityManagerFactoryRef);
|
||||
}
|
||||
|
||||
if (attributeCount == 0) {
|
||||
parserContext.getReaderContext().error("Exactly one of the attributes 'entity-manager' or " +
|
||||
"'entity-manager-factory' or 'jpa-operations' must be be set.", source);
|
||||
}
|
||||
|
||||
final ManagedList<BeanDefinition> jpaParameterList = JpaParserUtils.getJpaParameterBeanDefinitions(element, parserContext);
|
||||
|
||||
if (!jpaParameterList.isEmpty()) {
|
||||
jpaExecutorBuilder.addPropertyValue("jpaParameters", jpaParameterList);
|
||||
}
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "entity-class");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "jpa-query");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "native-query");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaExecutorBuilder, element, "named-query");
|
||||
|
||||
return jpaExecutorBuilder;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jpaComponent
|
||||
* @param parserContext
|
||||
*/
|
||||
public static ManagedList<BeanDefinition> getJpaParameterBeanDefinitions(
|
||||
Element jpaComponent, ParserContext parserContext) {
|
||||
|
||||
final ManagedList<BeanDefinition> parameterList = new ManagedList<BeanDefinition>();
|
||||
|
||||
final List<Element> parameterChildElements = DomUtils
|
||||
.getChildElementsByTagName(jpaComponent, "parameter");
|
||||
|
||||
for (Element childElement : parameterChildElements) {
|
||||
|
||||
final BeanDefinitionBuilder parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(JpaParameter.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);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(expression)) {
|
||||
parameterBuilder.addPropertyValue("expression", expression);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(value)) {
|
||||
|
||||
if (!StringUtils.hasText(type)) {
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String
|
||||
.format("Type attribute not set for parameter '%s'. Defaulting to "
|
||||
+ "'java.lang.String'.", value));
|
||||
}
|
||||
|
||||
parameterBuilder.addPropertyValue("value",
|
||||
new TypedStringValue(value, String.class));
|
||||
|
||||
} else {
|
||||
parameterBuilder.addPropertyValue("value",
|
||||
new TypedStringValue(value, type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parameterList.add(parameterBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
return parameterList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a "transactional" element and configure a TransactionInterceptor with "transactionManager"
|
||||
* and other "transactionDefinition" properties. This advisor will be applied on the Polling Task proxy
|
||||
* (see {@link AbstractPollingEndpoint}).
|
||||
*
|
||||
* FIXME Copied from {@link org.springframework.integration.config.xml.PollerParser} - should be refactored.
|
||||
*/
|
||||
public static BeanDefinition configureTransactionAttributes(Element txElement) {
|
||||
BeanDefinitionBuilder txDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultTransactionAttribute.class);
|
||||
txDefinitionBuilder.addPropertyValue("propagationBehaviorName", "PROPAGATION_" + txElement.getAttribute("propagation"));
|
||||
txDefinitionBuilder.addPropertyValue("isolationLevelName", "ISOLATION_" + txElement.getAttribute("isolation"));
|
||||
txDefinitionBuilder.addPropertyValue("timeout", txElement.getAttribute("timeout"));
|
||||
txDefinitionBuilder.addPropertyValue("readOnly", txElement.getAttribute("read-only"));
|
||||
BeanDefinitionBuilder attributeSourceBuilder = BeanDefinitionBuilder.genericBeanDefinition(MatchAlwaysTransactionAttributeSource.class);
|
||||
attributeSourceBuilder.addPropertyValue("transactionAttribute", txDefinitionBuilder.getBeanDefinition());
|
||||
BeanDefinitionBuilder txInterceptorBuilder = BeanDefinitionBuilder.genericBeanDefinition(TransactionInterceptor.class);
|
||||
txInterceptorBuilder.addPropertyReference("transactionManager", txElement.getAttribute("transaction-manager"));
|
||||
txInterceptorBuilder.addPropertyValue("transactionAttributeSource", attributeSourceBuilder.getBeanDefinition());
|
||||
return txInterceptorBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides parser classes to provide Xml namespace support for the Jpa components.
|
||||
*/
|
||||
package org.springframework.integration.jpa.config.xml;
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
abstract class AbstractJpaOperations implements JpaOperations, InitializingBean {
|
||||
|
||||
protected EntityManager entityManager;
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
Assert.notNull(entityManager, "The provided entitymanager must not be null.");
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
Assert.notNull(entityManagerFactory, "The provided entitymanagerFactory must not be null.");
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() {
|
||||
this.onInit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may implement this for initialization logic.
|
||||
*/
|
||||
|
||||
protected void onInit() {
|
||||
|
||||
if (this.entityManager == null && this.entityManagerFactory != null) {
|
||||
this.entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
|
||||
}
|
||||
|
||||
Assert.notNull(entityManager, "The entitymanager is null. Please set " +
|
||||
"either the entityManager or the entityManagerFactory.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Parameter;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.integration.jpa.support.JpaUtils;
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSource;
|
||||
import org.springframework.integration.jpa.support.parametersource.PositionSupportingParameterSource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Class similar to JPA template limited to the operations required for the JPA adapters/gateway
|
||||
* not using JpaTemplate as the class is deprecated since Spring 3.1
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class DefaultJpaOperations extends AbstractJpaOperations {
|
||||
|
||||
public void delete(Object entity) {
|
||||
Assert.notNull(entity, "The entity must not be null!");
|
||||
entityManager.remove(entity);
|
||||
}
|
||||
|
||||
public void deleteInBatch(Iterable<?> entities) {
|
||||
|
||||
Assert.notNull(entities, "entities must not be null.");
|
||||
|
||||
Iterator<?> iterator = entities.iterator();
|
||||
|
||||
if (!iterator.hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> entityClass = null;
|
||||
|
||||
for (Object object : entities) {
|
||||
if (entityClass == null) {
|
||||
entityClass = object.getClass();
|
||||
} else {
|
||||
if (entityClass != object.getClass()) {
|
||||
throw new IllegalArgumentException("entities must be of the same type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String entityName = JpaUtils.getEntityName(entityManager, entityClass);
|
||||
final String queryString = JpaUtils.getQueryString(JpaUtils.DELETE_ALL_QUERY_STRING, entityName);
|
||||
|
||||
JpaUtils.applyAndBind(queryString, entities, entityManager)
|
||||
.executeUpdate();
|
||||
|
||||
}
|
||||
|
||||
public int executeUpdate(String updateQuery, ParameterSource source) {
|
||||
Query query = entityManager.createQuery(updateQuery);
|
||||
setParametersIfRequired(updateQuery, source, query);
|
||||
return query.executeUpdate();
|
||||
}
|
||||
|
||||
public int executeUpdateWithNamedQuery(String updateQuery, ParameterSource source) {
|
||||
Query query = entityManager.createNamedQuery(updateQuery);
|
||||
setParametersIfRequired(updateQuery, source, query);
|
||||
return query.executeUpdate();
|
||||
}
|
||||
|
||||
public int executeUpdateWithNativeQuery(String updateQuery, ParameterSource source) {
|
||||
Query query = entityManager.createNativeQuery(updateQuery);
|
||||
setParametersIfRequired(updateQuery, source, query);
|
||||
return query.executeUpdate();
|
||||
}
|
||||
|
||||
public <T> T find(Class<T> entityType, Object id) {
|
||||
return entityManager.find(entityType, id);
|
||||
}
|
||||
|
||||
private Query getQuery(String queryString, ParameterSource source) {
|
||||
Query query = entityManager.createQuery(queryString);
|
||||
setParametersIfRequired(queryString, source, query);
|
||||
return query;
|
||||
}
|
||||
|
||||
public List<?> getResultListForClass(Class<?> entityClass, int maxNumberOfResults) {
|
||||
|
||||
final String entityName = JpaUtils.getEntityName(entityManager, entityClass);
|
||||
final Query query = entityManager.createQuery("select x from " + entityName + " x", entityClass);
|
||||
|
||||
if(maxNumberOfResults > 0) {
|
||||
query.setMaxResults(maxNumberOfResults);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
|
||||
}
|
||||
|
||||
public List<?> getResultListForNamedQuery(String selectNamedQuery,
|
||||
ParameterSource parameterSource, int maxNumberOfResults) {
|
||||
|
||||
final Query query = entityManager.createNamedQuery(selectNamedQuery);
|
||||
setParametersIfRequired(selectNamedQuery, parameterSource, query);
|
||||
|
||||
if(maxNumberOfResults > 0) {
|
||||
query.setMaxResults(maxNumberOfResults);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
|
||||
}
|
||||
|
||||
public List<?> getResultListForNativeQuery(String selectQuery, Class<?> entityClass,
|
||||
ParameterSource parameterSource, int maxNumberOfResults) {
|
||||
|
||||
final Query query;
|
||||
|
||||
if (entityClass == null) {
|
||||
query = entityManager.createNativeQuery(selectQuery);
|
||||
} else {
|
||||
query = entityManager.createNativeQuery(selectQuery, entityClass);
|
||||
}
|
||||
|
||||
setParametersIfRequired(selectQuery, parameterSource, query);
|
||||
|
||||
if(maxNumberOfResults > 0) {
|
||||
query.setMaxResults(maxNumberOfResults);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public List<?> getResultListForQuery(String query, ParameterSource source) {
|
||||
return getResultListForQuery(query,source, 0);
|
||||
}
|
||||
|
||||
public List<?> getResultListForQuery(String queryString, ParameterSource source,
|
||||
int maxNumberOfResults) {
|
||||
|
||||
Query query = getQuery(queryString,source);
|
||||
|
||||
if(maxNumberOfResults > 0) {
|
||||
query.setMaxResults(maxNumberOfResults);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
public Object getSingleResultForQuery(String queryString, ParameterSource source) {
|
||||
Query query = getQuery(queryString,source);
|
||||
return query.getSingleResult();
|
||||
}
|
||||
|
||||
public Object merge(Object entity) {
|
||||
return entityManager.merge(entity);
|
||||
}
|
||||
|
||||
public void persist(Object entity) {
|
||||
entityManager.persist(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a JPQL query, this method gets all parameters defined in this query and
|
||||
* use the {@link JPAQLParameterSource} to find their values and set them
|
||||
*
|
||||
*/
|
||||
private void setParametersIfRequired(String queryString,
|
||||
ParameterSource source, Query query) {
|
||||
Set<Parameter<?>> parameters = query.getParameters();
|
||||
|
||||
if(parameters != null && !parameters.isEmpty()) {
|
||||
if(source != null) {
|
||||
for(Parameter<?> param:parameters) {
|
||||
String paramName = param.getName();
|
||||
Integer position = param.getPosition();
|
||||
|
||||
final Object paramValue;
|
||||
|
||||
if (position != null) {
|
||||
|
||||
if (source instanceof PositionSupportingParameterSource) {
|
||||
paramValue = ((PositionSupportingParameterSource) source).getValueByPosition(position - 1);
|
||||
query.setParameter(position, paramValue);
|
||||
} else {
|
||||
throw new JpaOperationFailedException("Positional Parameters are only support "
|
||||
+ "for PositionSupportingParameterSources.")
|
||||
.withOffendingJPAQl(queryString);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if(StringUtils.hasText(paramName)) {
|
||||
paramValue = source.getValue(paramName);
|
||||
query.setParameter(paramName, paramValue);
|
||||
} else {
|
||||
throw new JpaOperationFailedException(
|
||||
"This parameter does not contain a parameter name. " +
|
||||
"Additionally it is not a postitional parameter, neither.")
|
||||
.withOffendingJPAQl(queryString);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Query has parameters but no parameter source provided");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.jpa.support.JpaParameter;
|
||||
import org.springframework.integration.jpa.support.PersistMode;
|
||||
import org.springframework.integration.jpa.support.parametersource.BeanPropertyParameterSourceFactory;
|
||||
import org.springframework.integration.jpa.support.parametersource.ExpressionEvaluatingParameterSourceFactory;
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSource;
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSourceFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Executes Jpa Operations that produce payload objects from the result of the provided:
|
||||
*
|
||||
* <ul>
|
||||
* <li>entityClass</li>
|
||||
* <li>JpQl Select Query</li>
|
||||
* <li>Sql Native Query</li>
|
||||
* <li>JpQl Named Query</li>
|
||||
* <li>Sql Native Named Query</li>
|
||||
* </ul>
|
||||
*
|
||||
* When objects are being retrieved, it also possibly to:
|
||||
*
|
||||
* <ul>
|
||||
* <li>delete the retrieved object</li>
|
||||
* </ul>
|
||||
*
|
||||
* If neither entityClass nor any other query is specified then the entity-class
|
||||
* is "guessed" from the {@link Message} payload.
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaExecutor implements InitializingBean {
|
||||
|
||||
private volatile JpaOperations jpaOperations;
|
||||
private volatile List<JpaParameter> jpaParameters;
|
||||
|
||||
private volatile Class<?> entityClass;
|
||||
private volatile String jpaQuery;
|
||||
private volatile String nativeQuery;
|
||||
private volatile String namedQuery;
|
||||
|
||||
/** 0 means all possible objects shall be retrieved. */
|
||||
private volatile int maxNumberOfResults = 0;
|
||||
|
||||
private volatile PersistMode persistMode = PersistMode.MERGE;
|
||||
|
||||
private volatile ParameterSourceFactory parameterSourceFactory = null;
|
||||
private volatile ParameterSource parameterSource;
|
||||
|
||||
private volatile boolean deleteAfterPoll = false;
|
||||
private volatile boolean deletePerRow = false;
|
||||
|
||||
private volatile boolean expectSingleResult = false;
|
||||
|
||||
/**
|
||||
* 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 BeanPropertyJpaParameterSourceFactory} implementation is
|
||||
* used for the sqlParameterSourceFactory property.
|
||||
*/
|
||||
private volatile Boolean usePayloadAsParameterSource = null;
|
||||
|
||||
//~~~~Constructors~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* Constructor taking an {@link EntityManagerFactory} from which the
|
||||
* {@link EntityManager} can be obtained.
|
||||
*
|
||||
* @param entityManagerFactory Must not be null.
|
||||
*/
|
||||
public JpaExecutor(EntityManagerFactory entityManagerFactory) {
|
||||
Assert.notNull(entityManagerFactory, "entityManagerFactory must not be null.");
|
||||
|
||||
DefaultJpaOperations defaultJpaOperations = new DefaultJpaOperations();
|
||||
defaultJpaOperations.setEntityManagerFactory(entityManagerFactory);
|
||||
defaultJpaOperations.afterPropertiesSet();
|
||||
|
||||
this.jpaOperations = defaultJpaOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor taking an {@link EntityManager} directly.
|
||||
*
|
||||
* @param entityManager Must not be null.
|
||||
*/
|
||||
public JpaExecutor(EntityManager entityManager) {
|
||||
Assert.notNull(entityManager, "entityManager must not be null.");
|
||||
|
||||
DefaultJpaOperations defaultJpaOperations = new DefaultJpaOperations();
|
||||
defaultJpaOperations.setEntityManager(entityManager);
|
||||
defaultJpaOperations.afterPropertiesSet();
|
||||
this.jpaOperations = defaultJpaOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* If custom behavior is required a custom implementation of {@link JpaOperations}
|
||||
* can be passed in. The implementations themselves typically provide access
|
||||
* to the {@link EntityManager}.
|
||||
*
|
||||
* See also {@link DefaultJpaOperations} and {@link AbstractJpaOperations}.
|
||||
*
|
||||
* @param jpaOperations Must not be null.
|
||||
*/
|
||||
public JpaExecutor(JpaOperations jpaOperations) {
|
||||
Assert.notNull(jpaOperations, "jpaOperations must not be null.");
|
||||
this.jpaOperations = jpaOperations;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Verifies and sets the parameters. E.g. initializes the to be used
|
||||
* {@link ParameterSourceFactory}.
|
||||
*
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
if (this.jpaParameters != null ) {
|
||||
|
||||
if (this.parameterSourceFactory == null) {
|
||||
ExpressionEvaluatingParameterSourceFactory expressionSourceFactory =
|
||||
new ExpressionEvaluatingParameterSourceFactory();
|
||||
expressionSourceFactory.setParameters(jpaParameters);
|
||||
this.parameterSourceFactory = expressionSourceFactory;
|
||||
|
||||
} else {
|
||||
|
||||
if (!(this.parameterSourceFactory instanceof ExpressionEvaluatingParameterSourceFactory)) {
|
||||
throw new IllegalStateException("You are providing 'JpaParameters'. "
|
||||
+ "Was expecting the the provided jpaParameterSourceFactory "
|
||||
+ "to be an instance of 'ExpressionEvaluatingJpaParameterSourceFactory', "
|
||||
+ "however the provided one is of type '" + this.parameterSourceFactory.getClass().getName() + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.usePayloadAsParameterSource == null) {
|
||||
this.usePayloadAsParameterSource = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (this.parameterSourceFactory == null) {
|
||||
this.parameterSourceFactory = new BeanPropertyParameterSourceFactory();
|
||||
}
|
||||
|
||||
if (this.usePayloadAsParameterSource == null) {
|
||||
this.usePayloadAsParameterSource = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the actual Jpa Operation. Call this method, if you need access to
|
||||
* process return values. This methods return a Map that contains either
|
||||
* the number of affected entities or the affected entity itself.
|
||||
*
|
||||
* Keep in mind that the number of entities effected by the operation may
|
||||
* not necessarily correlate with the number of rows effected in the database.
|
||||
*
|
||||
* @param message
|
||||
* @return Either the number of affected entities when using a JPAQL query. When using a merge/persist the updated/inserted itself is returned.
|
||||
*/
|
||||
public Object executeOutboundJpaOperation(final Message<?> message) {
|
||||
|
||||
final Object result;
|
||||
|
||||
if (this.jpaQuery != null) {
|
||||
|
||||
result = this.jpaOperations.executeUpdate(this.jpaQuery, parameterSourceFactory.createParameterSource(message));
|
||||
|
||||
} else if (this.nativeQuery != null) {
|
||||
|
||||
result = this.jpaOperations.executeUpdateWithNativeQuery(this.nativeQuery, parameterSourceFactory.createParameterSource(message));
|
||||
|
||||
} else if (this.namedQuery != null) {
|
||||
|
||||
result = this.jpaOperations.executeUpdateWithNamedQuery(this.namedQuery, parameterSourceFactory.createParameterSource(message));
|
||||
|
||||
} else {
|
||||
|
||||
if (PersistMode.PERSIST.equals(this.persistMode)) {
|
||||
this.jpaOperations.persist(message.getPayload());
|
||||
result = message.getPayload();
|
||||
} else if (PersistMode.MERGE.equals(this.persistMode)) {
|
||||
final Object mergedEntity = this.jpaOperations.merge(message.getPayload());
|
||||
result = mergedEntity;
|
||||
} else if (PersistMode.DELETE.equals(this.persistMode)) {
|
||||
this.jpaOperations.delete(message.getPayload());
|
||||
result = message.getPayload();
|
||||
} else {
|
||||
throw new IllegalStateException(String.format("Unsupported PersistMode: '%s'", this.persistMode.name()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a (typically retrieving) JPA operation. The <i>requestMessage</i>
|
||||
* can be used to provide additional query parameters using
|
||||
* {@link JpaExecutor#parameterSourceFactorymeterSourceFactory}. If the
|
||||
* <i>requestMessage</i> parameter is null then
|
||||
* {@link JpaExecutor#parameterSource} is being used for providing query parameters.
|
||||
*
|
||||
* @param requestMessage May be null.
|
||||
* @return The payload object, which may be null.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object poll(final Message<?> requestMessage) {
|
||||
|
||||
final Object payload;
|
||||
|
||||
final List<?> result;
|
||||
|
||||
if (requestMessage == null) {
|
||||
result = doPoll(this.parameterSource);
|
||||
} else {
|
||||
result = doPoll(this.parameterSourceFactory.createParameterSource(requestMessage));
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
payload = null;
|
||||
} else {
|
||||
|
||||
if (this.expectSingleResult) {
|
||||
if (result.size() == 1) {
|
||||
payload = result.iterator().next();
|
||||
} else {
|
||||
|
||||
throw new MessageHandlingException(requestMessage,
|
||||
"The Jpa operation returned more than "
|
||||
+ "1 result object but expectSingleResult was 'true'.");
|
||||
}
|
||||
|
||||
} else {
|
||||
payload = result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (payload != null && this.deleteAfterPoll) {
|
||||
|
||||
if (payload instanceof Iterable) {
|
||||
if (this.deletePerRow) {
|
||||
for (Object entity : (Iterable<?>) payload) {
|
||||
this.jpaOperations.delete(entity);
|
||||
}
|
||||
} else {
|
||||
this.jpaOperations.deleteInBatch((Iterable<Object>) payload);
|
||||
}
|
||||
} else {
|
||||
this.jpaOperations.delete(payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the JPA operation. Delegates to {@link JpaExecutor#poll(Message)}.
|
||||
*/
|
||||
public Object poll() {
|
||||
return poll(null);
|
||||
}
|
||||
|
||||
protected List<?> doPoll(ParameterSource jpaQLParameterSource) {
|
||||
|
||||
List<?> payload = null;
|
||||
|
||||
if (this.jpaQuery != null) {
|
||||
payload = jpaOperations.getResultListForQuery(this.jpaQuery, jpaQLParameterSource, maxNumberOfResults);
|
||||
} else if (this.nativeQuery != null) {
|
||||
payload = jpaOperations.getResultListForNativeQuery(this.nativeQuery, this.entityClass, jpaQLParameterSource, maxNumberOfResults);
|
||||
} else if (this.namedQuery != null) {
|
||||
payload = jpaOperations.getResultListForNamedQuery(this.namedQuery, jpaQLParameterSource, maxNumberOfResults);
|
||||
} else if (this.entityClass != null) {
|
||||
payload = jpaOperations.getResultListForClass(this.entityClass, maxNumberOfResults);
|
||||
} else {
|
||||
throw new IllegalStateException("For the polling operation, one of "
|
||||
+ "the following properties must be specified: "
|
||||
+ "query, namedQuery or entityClass.");
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
//~~~~Setters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* Sets the class type which is being used to poll the database or to also
|
||||
* update the persistence store.
|
||||
*
|
||||
* @param entityClass Must not be null.
|
||||
*/
|
||||
public void setEntityClass(Class<?> entityClass) {
|
||||
Assert.notNull(entityClass, "entityClass must not be null.");
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jpaQuery The provided JPA query must neither be null nor empty.
|
||||
*/
|
||||
public void setJpaQuery(String jpaQuery) {
|
||||
|
||||
if (this.nativeQuery != null || this.namedQuery != null) {
|
||||
throw new IllegalArgumentException("You can define only one of the " +
|
||||
"properties 'jpaQuery', 'nativeQuery', 'namedQuery'");
|
||||
}
|
||||
|
||||
Assert.hasText(jpaQuery, "jpaQuery must neither be null nor empty.");
|
||||
|
||||
this.jpaQuery = jpaQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* You can also use native Sql queries to poll data from the database. If set
|
||||
* this property will allow you to use native SQL. Optionally you can also set
|
||||
* the entityClass property at the same time. If specified the entityClass will
|
||||
* be used as the result class for the native query.
|
||||
*
|
||||
* @param nativeQuery The provided SQL query must neither be null nor empty.
|
||||
*/
|
||||
public void setNativeQuery(String nativeQuery) {
|
||||
|
||||
if (this.jpaQuery != null || this.namedQuery != null) {
|
||||
throw new IllegalArgumentException("You can define only one of the " +
|
||||
"properties 'jpaQuery', 'nativeQuery', 'namedQuery'");
|
||||
}
|
||||
|
||||
Assert.hasText(nativeQuery, "nativeQuery must neither be null nor empty.");
|
||||
|
||||
this.nativeQuery = nativeQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* A named query can either refer to a named JPQL based query or a native SQL
|
||||
* query.
|
||||
*
|
||||
* @param namedQuery Must neither be null nor empty
|
||||
*/
|
||||
public void setNamedQuery(String namedQuery) {
|
||||
|
||||
if (this.jpaQuery != null || this.nativeQuery != null) {
|
||||
throw new IllegalArgumentException("You can define only one of the " +
|
||||
"properties 'jpaQuery', 'nativeQuery', 'namedQuery'");
|
||||
}
|
||||
|
||||
Assert.hasText(namedQuery, "namedQuery must neither be null nor empty.");
|
||||
this.namedQuery = namedQuery;
|
||||
}
|
||||
|
||||
public void setPersistMode(PersistMode persistMode) {
|
||||
this.persistMode = persistMode;
|
||||
}
|
||||
|
||||
public void setJpaParameters(List<JpaParameter> jpaParameters) {
|
||||
this.jpaParameters = jpaParameters;
|
||||
}
|
||||
|
||||
public void setUsePayloadAsParameterSource(Boolean usePayloadAsParameterSource) {
|
||||
this.usePayloadAsParameterSource = usePayloadAsParameterSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* If not set, this property default to 'true', which means that deletion
|
||||
* occur on a per object basis.
|
||||
*
|
||||
* If set to 'false' the elements of the payload are deleted as a batch
|
||||
* operation. Be aware that this exhibit issues in regards to cascaded deletes. //TODO further information needed
|
||||
*
|
||||
* @param deletePerRow Defaults to 'true'.
|
||||
*/
|
||||
public void setDeletePerRow(boolean deletePerRow) {
|
||||
this.deletePerRow = deletePerRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to 'true', the retrieved objects are deleted from the database upon
|
||||
* being polled. May not work in all situations, e.g. for Native SQL Queries.
|
||||
*
|
||||
* @param deleteAfterPoll Defaults to 'false'.
|
||||
*/
|
||||
public void setDeleteAfterPoll(boolean deleteAfterPoll) {
|
||||
this.deleteAfterPoll = deleteAfterPoll;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param maxNumberOfResults Must not be negative.
|
||||
*/
|
||||
public void setMaxRows(int maxNumberOfResults) {
|
||||
Assert.isTrue(maxNumberOfResults >= 0, "maxRows must not be negative.");
|
||||
this.maxNumberOfResults = maxNumberOfResults;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param parameterSourceFactory
|
||||
*/
|
||||
public void setParameterSourceFactory(
|
||||
ParameterSourceFactory parameterSourceFactory) {
|
||||
Assert.notNull(parameterSourceFactory, "parameterSourceFactory must not be null.");
|
||||
this.parameterSourceFactory = parameterSourceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param parameterSource
|
||||
*/
|
||||
public void setParameterSource(ParameterSource parameterSource) {
|
||||
Assert.notNull(parameterSource, "parameterSource must not be null.");
|
||||
this.parameterSource = parameterSource;
|
||||
}
|
||||
|
||||
public void setExpectSingleResult(boolean expectSingleResult) {
|
||||
this.expectSingleResult = expectSingleResult;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
/**
|
||||
* An Exception that would be thrown if any of the Operations from {@link JpaOperations} fails
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOperationFailedException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String offendingJPAQl;
|
||||
|
||||
public JpaOperationFailedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JpaOperationFailedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public JpaOperationFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JpaOperationFailedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* If execution of a JPA QL fails, we can set that query using this convenience method.
|
||||
* @param offendingJPAQl
|
||||
* @return JpaOperationFailedException
|
||||
*/
|
||||
public JpaOperationFailedException withOffendingJPAQl(String offendingJPAQl) {
|
||||
setOffendingJPAQl(offendingJPAQl);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getOffendingJPAQl() {
|
||||
return offendingJPAQl;
|
||||
}
|
||||
|
||||
public void setOffendingJPAQl(String offendingJPAQl) {
|
||||
this.offendingJPAQl = offendingJPAQl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSource;
|
||||
|
||||
/**
|
||||
* The Interface containing all the JpaOperations those will be executed by
|
||||
* the Jpa Spring Integration components.
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface JpaOperations {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
void delete(Object entity);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entities
|
||||
*/
|
||||
void deleteInBatch(Iterable<?> entities);
|
||||
|
||||
/**
|
||||
* Executes the given update statement and uses the given parameter source to
|
||||
* set the required query parameters.
|
||||
*
|
||||
* @param updateQuery Must Not be empty.
|
||||
* @param source Must Not be null.
|
||||
* @return The number of entities updated
|
||||
*/
|
||||
int executeUpdate(String updateQuery, ParameterSource source);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param updateQuery
|
||||
* @param source
|
||||
* @return The number of entities updated
|
||||
*/
|
||||
int executeUpdateWithNamedQuery(String updateQuery, ParameterSource source);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param updateQuery
|
||||
* @param source
|
||||
* @return The number of entities updated
|
||||
*/
|
||||
int executeUpdateWithNativeQuery(String updateQuery, ParameterSource source);
|
||||
|
||||
|
||||
/**
|
||||
* Find an Entity of given type with the given primary key type.
|
||||
*
|
||||
* @param <T>
|
||||
* @param entityType
|
||||
* @param id
|
||||
* @return The entity if it exist, null is returned otherwise
|
||||
*/
|
||||
<T> T find(Class<T> entityType, Object id);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entityClass
|
||||
* @param maxNumberOfReturnedObjects
|
||||
* @return List of found entities
|
||||
*/
|
||||
List<?> getResultListForClass(Class<?> entityClass,
|
||||
int maxNumberOfReturnedObjects);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param selectNamedQuery
|
||||
* @param jpaQLParameterSource
|
||||
* @param maxNumberOfResults
|
||||
* @return List of found entities
|
||||
*/
|
||||
List<?> getResultListForNamedQuery(String selectNamedQuery, ParameterSource jpaQLParameterSource,
|
||||
int maxNumberOfResults);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param selectQuery
|
||||
* @param entityClass
|
||||
* @param jpaQLParameterSource
|
||||
* @param maxNumberOfResults
|
||||
* @return List of found entities
|
||||
*/
|
||||
List<?> getResultListForNativeQuery(String selectQuery,
|
||||
Class<?> entityClass, ParameterSource jpaQLParameterSource, int maxNumberOfResults);
|
||||
|
||||
/**
|
||||
* Executes the provided query to return a list of results
|
||||
* @param query
|
||||
* @param source the Parameter source for this query to be executed, if none then set as null
|
||||
* @return List of found entities
|
||||
*/
|
||||
List<?> getResultListForQuery(String query, ParameterSource source);
|
||||
|
||||
/**
|
||||
* Executes the provided query to return a list of results.
|
||||
*
|
||||
* @param query Must not be null or empty
|
||||
* @param maxNumberOfResults Must be a non-negative value
|
||||
* @param source the Parameter source for this query to be executed, if none then set null
|
||||
* @return List of found entities
|
||||
*/
|
||||
List<?> getResultListForQuery(String query, ParameterSource source, int maxNumberOfResults);
|
||||
|
||||
/**
|
||||
* Executes the provided query to return a single element
|
||||
*
|
||||
* @param query Must not be empty
|
||||
* @param source the Parameter source for this query to be executed, if none then set as null
|
||||
* @return Will always return a result. If no object was found in the database an exception is raised.
|
||||
*/
|
||||
Object getSingleResultForQuery(String query, ParameterSource source);
|
||||
|
||||
/**
|
||||
* The entity to be merged with the entity manager
|
||||
*
|
||||
* @param entity Must not be null.
|
||||
* @return The merged managed instance of the entity.
|
||||
*/
|
||||
Object merge(Object entity);
|
||||
|
||||
/**
|
||||
* Persists the entity
|
||||
* @param entity Must not be null
|
||||
*
|
||||
*/
|
||||
void persist(Object entity);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides core classes of the JPA module.
|
||||
*/
|
||||
package org.springframework.integration.jpa.core;
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.inbound;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Polling message source that produces messages from the result of the provided:
|
||||
*
|
||||
* <ul>
|
||||
* <li>entityClass</li>
|
||||
* <li>JpQl Select Query</li>
|
||||
* <li>Sql Native Query</li>
|
||||
* <li>JpQl Named Query</li>
|
||||
* <li>Sql Native Named Query</li>
|
||||
* </ul>
|
||||
*
|
||||
* After the objects have been polled, it also possibly to either:
|
||||
*
|
||||
* executes an update after the select possibly to updated the state of selected records
|
||||
*
|
||||
* <ul>
|
||||
* <li>executes an update (per retrieved object or for the entire payload)</li>
|
||||
* <li>delete the retrieved object</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaPollingChannelAdapter extends IntegrationObjectSupport implements MessageSource<Object>{
|
||||
|
||||
private final JpaExecutor jpaExecutor;
|
||||
|
||||
/**
|
||||
* Constructor taking a {@link JpaExecutor} that provide all required JPA
|
||||
* functionality.
|
||||
*
|
||||
* @param jpaExecutor Must not be null.
|
||||
*/
|
||||
public JpaPollingChannelAdapter(JpaExecutor jpaExecutor) {
|
||||
super();
|
||||
Assert.notNull(jpaExecutor, "jpaExecutor must not be null.");
|
||||
this.jpaExecutor = jpaExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for mandatory attributes
|
||||
*/
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@link JpaExecutor#poll()} to executes the JPA operation.
|
||||
*
|
||||
* If {@link JpaExecutor#poll()} returns null, this method will return
|
||||
* <code>null</code>. Otherwise, a new {@link Message} is constructed and returned.
|
||||
*/
|
||||
public Message<Object> receive() {
|
||||
|
||||
final Object payload = jpaExecutor.poll();
|
||||
|
||||
if (payload == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MessageBuilder.withPayload(payload).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType(){
|
||||
return "jpa:inbound-channel-adapter";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides inbound Spring Integration Jpa components.
|
||||
*/
|
||||
package org.springframework.integration.jpa.inbound;
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.support.OutboundGatewayType;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The Jpa Outbound Gateway will allow you to make outbound operations to either:
|
||||
*
|
||||
* <ul>
|
||||
* <li>submit (insert, delete) data to a database using JPA</li>
|
||||
* <li>retrieve (select) data from a database</li>
|
||||
* </ul>
|
||||
*
|
||||
* Depending on the selected {@link OutboundGatewayType}, the outbound gateway
|
||||
* will use either the {@link JpaExecutor}'s poll method or its
|
||||
* executeOutboundJpaOperation method.
|
||||
*
|
||||
* In order to initialize the adapter, you must provide a {@link JpaExecutor} as
|
||||
* constructor.
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOutboundGateway extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
private final JpaExecutor jpaExecutor;
|
||||
private OutboundGatewayType gatewayType = OutboundGatewayType.UPDATING;
|
||||
private boolean producesReply = true; //false for outbound-channel-adapter, true for outbound-gateway
|
||||
|
||||
/**
|
||||
* Constructor taking an {@link JpaExecutor} that wraps all JPA Operations.
|
||||
*
|
||||
* @param jpaExecutor Must not be null
|
||||
*
|
||||
*/
|
||||
public JpaOutboundGateway(JpaExecutor jpaExecutor) {
|
||||
Assert.notNull(jpaExecutor, "jpaExecutor must not be null.");
|
||||
this.jpaExecutor = jpaExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
|
||||
final Object result;
|
||||
|
||||
if (OutboundGatewayType.RETRIEVING.equals(this.gatewayType)) {
|
||||
|
||||
result = this.jpaExecutor.poll(requestMessage);
|
||||
|
||||
} else if (OutboundGatewayType.UPDATING.equals(this.gatewayType)) {
|
||||
|
||||
result = this.jpaExecutor.executeOutboundJpaOperation(requestMessage);
|
||||
|
||||
} else {
|
||||
|
||||
throw new IllegalArgumentException(String.format("GatewayType '%s' is not supported.", this.gatewayType));
|
||||
|
||||
}
|
||||
|
||||
if (result == null || !producesReply) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MessageBuilder.withPayload(result).copyHeaders(requestMessage.getHeaders()).build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param gatewayType
|
||||
*/
|
||||
public void setGatewayType(OutboundGatewayType gatewayType) {
|
||||
Assert.notNull(gatewayType, "gatewayType must not be null.");
|
||||
this.gatewayType = gatewayType;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to 'false', this component will act as an Outbound Channel Adapter.
|
||||
* If not explicitly set this property will default to 'true'.
|
||||
*
|
||||
* @param producesReply Defaults to 'true'.
|
||||
*
|
||||
*/
|
||||
public void setProducesReply(boolean producesReply) {
|
||||
this.producesReply = producesReply;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.support.OutboundGatewayType;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* The {@link JpaOutboundGatewayFactoryBean} creates instances of the
|
||||
* {@link JpaOutboundGateway}. Optionally this {@link FactoryBean} will add Aop
|
||||
* Advices (e.g. {@link TransactionInterceptor} to the {@link JpaOutboundGateway}
|
||||
* instance.
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean<MessageHandler> {
|
||||
|
||||
private final JpaExecutor jpaExecutor;
|
||||
private OutboundGatewayType gatewayType = OutboundGatewayType.UPDATING;
|
||||
|
||||
private volatile List<Advice> adviceChain;
|
||||
private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
private boolean producesReply = true;
|
||||
private MessageChannel outputChannel;
|
||||
private int order;
|
||||
|
||||
/**
|
||||
* Constructor taking an {@link JpaExecutor} that wraps all JPA Operations.
|
||||
*
|
||||
* @param jpaExecutor Must not be null
|
||||
*
|
||||
*/
|
||||
public JpaOutboundGatewayFactoryBean(JpaExecutor jpaExecutor) {
|
||||
Assert.notNull(jpaExecutor, "jpaExecutor must not be null.");
|
||||
this.jpaExecutor = jpaExecutor;
|
||||
}
|
||||
|
||||
public void setGatewayType(OutboundGatewayType gatewayType) {
|
||||
this.gatewayType = gatewayType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return MessageHandler.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MessageHandler createInstance() {
|
||||
|
||||
JpaOutboundGateway jpaOutboundGateway = new JpaOutboundGateway(jpaExecutor);
|
||||
jpaOutboundGateway.setGatewayType(this.gatewayType);
|
||||
jpaOutboundGateway.setProducesReply(this.producesReply);
|
||||
jpaOutboundGateway.setOutputChannel(this.outputChannel);
|
||||
jpaOutboundGateway.setOrder(this.order);
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.adviceChain)) {
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory(jpaOutboundGateway);
|
||||
if (!CollectionUtils.isEmpty(adviceChain)) {
|
||||
for (Advice advice : adviceChain) {
|
||||
proxyFactory.addAdvice(advice);
|
||||
}
|
||||
}
|
||||
|
||||
return (MessageHandler) proxyFactory.getProxy(this.beanClassLoader);
|
||||
}
|
||||
|
||||
return jpaOutboundGateway;
|
||||
}
|
||||
|
||||
public void setAdviceChain(List<Advice> adviceChain) {
|
||||
this.adviceChain = adviceChain;
|
||||
}
|
||||
|
||||
public void setProducesReply(boolean producesReply) {
|
||||
this.producesReply = producesReply;
|
||||
}
|
||||
|
||||
public void setOutputChannel(MessageChannel outputChannel) {
|
||||
this.outputChannel = outputChannel;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides Spring Integration components for doing outbound operations.
|
||||
*/
|
||||
package org.springframework.integration.jpa.outbound;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Root package of the JPA Module.
|
||||
*/
|
||||
package org.springframework.integration.jpa;
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstraction of Jpa parameters allowing to provide static parameters
|
||||
* and SpEl Expression based parameters.
|
||||
*
|
||||
* TODO Should we combine ProcedureParameter class and this class?
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaParameter {
|
||||
|
||||
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 Jpa Parameter.
|
||||
*
|
||||
* @param name Name of the JPA 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 JpaParameter(String name, Object value, String expression) {
|
||||
super();
|
||||
|
||||
Assert.hasText(name, "'name' must not be empty.");
|
||||
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Jpa Parameter without a name. This is useful for specifying
|
||||
* positional Jpa parameters.
|
||||
*
|
||||
* @param value If null, the expression property must be set
|
||||
* @param expression If null, the value property must be set
|
||||
*/
|
||||
public JpaParameter(Object value, String expression) {
|
||||
super();
|
||||
this.value = value;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public JpaParameter() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("JpaParameter [name=").append(this.name)
|
||||
.append(", value=").append(this.value)
|
||||
.append(", expression=").append(this.expression)
|
||||
.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* This Utility contains a sub-set of utility methods from the Spring Data JPA Project.
|
||||
* As the Spring Integration JPA adapter uses only these utility methods, they
|
||||
* were copied into this class in order to prevent having to declare a dependency
|
||||
* on Spring Data JPA.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public final class JpaUtils {
|
||||
|
||||
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
|
||||
|
||||
private static final Pattern ALIAS_MATCH;
|
||||
|
||||
private static final String IDENTIFIER = "[\\p{Alnum}._$]+";
|
||||
private static final String IDENTIFIER_GROUP = String.format("(%s)", IDENTIFIER);
|
||||
|
||||
static {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("(?<=from)"); // from as starting delimiter
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append(IDENTIFIER_GROUP); // Entity name, can be qualified (any
|
||||
builder.append("(?: as)*"); // exclude possible "as" keyword
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append("(\\w*)"); // the actual alias
|
||||
|
||||
ALIAS_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
|
||||
|
||||
builder = new StringBuilder();
|
||||
builder.append("(select\\s+((distinct )?.+?)\\s+)?(from\\s+");
|
||||
builder.append(IDENTIFIER);
|
||||
builder.append("(?:\\s+as)?\\s+)");
|
||||
builder.append(IDENTIFIER_GROUP);
|
||||
builder.append("(.*)");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private JpaUtils() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the alias for the entity to be retrieved from the given JPA query.
|
||||
*
|
||||
*/
|
||||
public static String detectAlias(String query) {
|
||||
|
||||
Matcher matcher = ALIAS_MATCH.matcher(query);
|
||||
|
||||
return matcher.find() ? matcher.group(2) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a where-clause referencing the given entities and appends it to the given query string. Binds the given
|
||||
* entities to the query.
|
||||
*
|
||||
*/
|
||||
public static <T> Query applyAndBind(String queryString, Iterable<T> entities, EntityManager entityManager) {
|
||||
|
||||
Assert.notNull(queryString);
|
||||
Assert.notNull(entities);
|
||||
Assert.notNull(entityManager);
|
||||
|
||||
Iterator<T> iterator = entities.iterator();
|
||||
|
||||
if (!iterator.hasNext()) {
|
||||
return entityManager.createQuery(queryString);
|
||||
}
|
||||
|
||||
String alias = detectAlias(queryString);
|
||||
StringBuilder builder = new StringBuilder(queryString);
|
||||
builder.append(" where");
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
iterator.next();
|
||||
|
||||
builder.append(String.format(" %s = ?%d", alias, ++i));
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(" or");
|
||||
}
|
||||
}
|
||||
|
||||
Query query = entityManager.createQuery(builder.toString());
|
||||
|
||||
iterator = entities.iterator();
|
||||
i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
query.setParameter(++i, iterator.next());
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string for the given class name.
|
||||
*/
|
||||
public static String getQueryString(String template, String entityName) {
|
||||
|
||||
Assert.hasText(entityName, "Entity name must not be null or empty!");
|
||||
|
||||
return String.format(template, entityName);
|
||||
}
|
||||
|
||||
public static String getEntityName(EntityManager em, Class<?> entityClass) {
|
||||
|
||||
return em.getMetamodel().entity(entityClass).getName();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support;
|
||||
|
||||
/**
|
||||
* Indicates the mode of operation for the outbound Jpa Gateway.
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public enum OutboundGatewayType {
|
||||
UPDATING, RETRIEVING
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support;
|
||||
|
||||
/**
|
||||
* Indicates how entities shall be persisted to the underlying persistence store.
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public enum PersistMode {
|
||||
PERSIST, MERGE, DELETE
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides various support classes used across Spring Integration Jpa Components.
|
||||
*/
|
||||
package org.springframework.integration.jpa.support;
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.NotReadablePropertyException;
|
||||
import org.springframework.beans.PropertyAccessor;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class BeanPropertyParameterSource implements ParameterSource {
|
||||
|
||||
private final BeanWrapper beanWrapper;
|
||||
|
||||
private String[] propertyNames;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new BeanPropertySqlParameterSource for the given bean.
|
||||
* @param object the bean instance to wrap
|
||||
*/
|
||||
public BeanPropertyParameterSource(Object object) {
|
||||
this.beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(object);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasValue(String paramName) {
|
||||
return this.beanWrapper.isReadableProperty(paramName);
|
||||
}
|
||||
|
||||
public Object getValue(String paramName) {
|
||||
try {
|
||||
return this.beanWrapper.getPropertyValue(paramName);
|
||||
}
|
||||
catch (NotReadablePropertyException ex) {
|
||||
throw new IllegalArgumentException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to the property names of the wrapped bean.
|
||||
* Uses support provided in the {@link PropertyAccessor} interface.
|
||||
* @return an array containing all the known property names
|
||||
*/
|
||||
public String[] getReadablePropertyNames() {
|
||||
if (this.propertyNames == null) {
|
||||
final List<String> names = new ArrayList<String>();
|
||||
PropertyDescriptor[] props = this.beanWrapper.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd : props) {
|
||||
if (this.beanWrapper.isReadableProperty(pd.getName())) {
|
||||
names.add(pd.getName());
|
||||
}
|
||||
}
|
||||
this.propertyNames = names.toArray(new String[names.size()]);
|
||||
}
|
||||
return this.propertyNames;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class BeanPropertyParameterSourceFactory implements ParameterSourceFactory {
|
||||
|
||||
private volatile Map<String, Object> staticParameters;
|
||||
|
||||
public BeanPropertyParameterSourceFactory() {
|
||||
this.staticParameters = Collections.unmodifiableMap(new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the input is a List or a Map, the output is a map parameter source, and in that case some static parameters
|
||||
* can be added (default is empty). If the input is not a List or a Map then this value is ignored.
|
||||
*
|
||||
* @param staticParameters the static parameters to set
|
||||
*/
|
||||
public void setStaticParameters(Map<String, Object> staticParameters) {
|
||||
this.staticParameters = staticParameters;
|
||||
}
|
||||
|
||||
public ParameterSource createParameterSource(Object input) {
|
||||
ParameterSource toReturn = new StaticBeanPropertyParameterSource(input, staticParameters);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
private static class StaticBeanPropertyParameterSource implements
|
||||
ParameterSource {
|
||||
|
||||
private final BeanPropertyParameterSource input;
|
||||
|
||||
private final Map<String, Object> staticParameters;
|
||||
|
||||
public StaticBeanPropertyParameterSource(Object input, Map<String, Object> staticParameters) {
|
||||
this.input = new BeanPropertyParameterSource(input);
|
||||
this.staticParameters = staticParameters;
|
||||
}
|
||||
|
||||
public Object getValue(String paramName) {
|
||||
return staticParameters.containsKey(paramName) ? staticParameters.get(paramName) : input
|
||||
.getValue(paramName);
|
||||
}
|
||||
|
||||
public boolean hasValue(String paramName) {
|
||||
return staticParameters.containsKey(paramName) || input.hasValue(paramName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.springframework.integration.jpa.support.parametersource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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.jpa.support.JpaParameter;
|
||||
import org.springframework.integration.jpa.support.parametersource.ExpressionEvaluatingParameterSourceFactory.ParameterExpressionEvaluator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
class ExpressionEvaluatingParameterSource implements PositionSupportingParameterSource {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExpressionEvaluatingParameterSource.class);
|
||||
|
||||
private static final Object ERROR = new Object();
|
||||
|
||||
private final Object input;
|
||||
|
||||
private volatile Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
private final Map<String, String> parameterExpressions;
|
||||
|
||||
private final List<JpaParameter> parameters;
|
||||
|
||||
private final ParameterExpressionEvaluator expressionEvaluator;
|
||||
|
||||
ExpressionEvaluatingParameterSource(Object input, List<JpaParameter> parameters, ParameterExpressionEvaluator expressionEvaluator) {
|
||||
|
||||
this.input = input;
|
||||
this.expressionEvaluator = expressionEvaluator;
|
||||
this.parameters = parameters;
|
||||
this.parameterExpressions = ExpressionEvaluatingParameterSourceFactory.convertExpressions(parameters);
|
||||
this.values.putAll(ExpressionEvaluatingParameterSourceFactory.convertStaticParameters(parameters));
|
||||
|
||||
}
|
||||
|
||||
public Object getValueByPosition(int position) {
|
||||
|
||||
Assert.isTrue(position >= 0, "The position must be be non-negative.");
|
||||
|
||||
if (position <= parameters.size()) {
|
||||
|
||||
final JpaParameter parameter = parameters.get(position);
|
||||
|
||||
if (parameter.getValue() != null) {
|
||||
return parameter.getValue();
|
||||
}
|
||||
|
||||
if (parameter.getExpression() != null) {
|
||||
String expression = parameter.getExpression();
|
||||
|
||||
if (input instanceof Collection<?>) {
|
||||
expression = "#root.![" + expression + "]";
|
||||
}
|
||||
|
||||
final Object value = this.expressionEvaluator.evaluateExpression(expression, input);
|
||||
//FIXME values.put(paramName, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Resolved expression " + expression + " to " + value);
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public Object getValue(String paramName) {
|
||||
if (values.containsKey(paramName)) {
|
||||
return values.get(paramName);
|
||||
}
|
||||
String expression = paramName;
|
||||
if (parameterExpressions.containsKey(expression)) {
|
||||
expression = parameterExpressions.get(expression);
|
||||
}
|
||||
if (input instanceof Collection<?>) {
|
||||
expression = "#root.![" + expression + "]";
|
||||
}
|
||||
final Object value = this.expressionEvaluator.evaluateExpression(expression, input);
|
||||
values.put(paramName, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Resolved expression " + expression + " to " + value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean hasValue(String paramName) {
|
||||
try {
|
||||
final Object value = getValue(paramName);
|
||||
if (value == ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (ExpressionException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not evaluate expression", e);
|
||||
}
|
||||
values.put(paramName, ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.jpa.support.JpaParameter;
|
||||
import org.springframework.integration.util.AbstractExpressionEvaluator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingParameterSourceFactory implements ParameterSourceFactory {
|
||||
|
||||
private volatile List<JpaParameter> parameters;
|
||||
private ParameterExpressionEvaluator expressionEvaluator = new ParameterExpressionEvaluator();
|
||||
|
||||
public ExpressionEvaluatingParameterSourceFactory() {
|
||||
this.parameters = Collections.unmodifiableList(new ArrayList<JpaParameter>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the (optional) parameter values.
|
||||
*
|
||||
* @param parameters the parameters to be set
|
||||
*/
|
||||
public void setParameters(List<JpaParameter> parameters) {
|
||||
|
||||
Assert.notEmpty(parameters, "parameters must not be null or empty.");
|
||||
|
||||
for (JpaParameter parameter : parameters) {
|
||||
Assert.notNull(parameter, "The provided list (parameters) cannot contain null values.");
|
||||
}
|
||||
|
||||
this.parameters = parameters;
|
||||
expressionEvaluator.getEvaluationContext().setVariable("staticParameters", convertStaticParameters(parameters));
|
||||
|
||||
}
|
||||
|
||||
public PositionSupportingParameterSource createParameterSource(final Object input) {
|
||||
return new ExpressionEvaluatingParameterSource(input, this.parameters, expressionEvaluator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that converts a Collection of {@link JpaParameter} to
|
||||
* a Map containing only expression parameters.
|
||||
*
|
||||
* @param jpaParameters Must not be null.
|
||||
* @return Map containing only the Expression bound parameters. Will never be null.
|
||||
*/
|
||||
public static Map<String, String> convertExpressions(Collection<JpaParameter> jpaParameters) {
|
||||
|
||||
Assert.notNull(jpaParameters, "The Collection of jpaParameters must not be null.");
|
||||
|
||||
for (JpaParameter parameter : jpaParameters) {
|
||||
Assert.notNull(parameter, "'jpaParameters' must not contain null values.");
|
||||
}
|
||||
|
||||
final Map<String, String> staticParameters = new HashMap<String, String>();
|
||||
|
||||
for (JpaParameter parameter : jpaParameters) {
|
||||
if (parameter.getExpression() != null) {
|
||||
staticParameters.put(parameter.getName(), parameter.getExpression());
|
||||
}
|
||||
}
|
||||
|
||||
return staticParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that converts a Collection of {@link JpaParameter} to
|
||||
* a Map containing only static parameters.
|
||||
*
|
||||
* @param jpaParameters Must not be null.
|
||||
* @return Map containing only the static parameters. Will never be null.
|
||||
*/
|
||||
public static Map<String, Object> convertStaticParameters(Collection<JpaParameter> jpaParameters) {
|
||||
|
||||
Assert.notNull(jpaParameters, "The Collection of jpaParameters must not be null.");
|
||||
|
||||
for (JpaParameter parameter : jpaParameters) {
|
||||
Assert.notNull(parameter, "'jpaParameters' must not contain null values.");
|
||||
}
|
||||
|
||||
final Map<String, Object> staticParameters = new HashMap<String, Object>();
|
||||
|
||||
for (JpaParameter parameter : jpaParameters) {
|
||||
if (parameter.getValue() != null) {
|
||||
staticParameters.put(parameter.getName(), parameter.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return staticParameters;
|
||||
}
|
||||
|
||||
public class ParameterExpressionEvaluator extends AbstractExpressionEvaluator {
|
||||
|
||||
@Override
|
||||
public StandardEvaluationContext getEvaluationContext() {
|
||||
return super.getEvaluationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluateExpression(String expression, Object input) {
|
||||
return super.evaluateExpression(expression, input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface ParameterSource {
|
||||
|
||||
/**
|
||||
* Determine whether there is a value for the specified named parameter.
|
||||
* @param paramName the name of the parameter
|
||||
* @return whether there is a value defined
|
||||
*/
|
||||
boolean hasValue(String paramName);
|
||||
|
||||
/**
|
||||
* Return the parameter value for the requested named parameter.
|
||||
* @param paramName the name of the parameter
|
||||
* @return the value of the specified parameter
|
||||
*/
|
||||
Object getValue(String paramName);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface ParameterSourceFactory {
|
||||
|
||||
/**
|
||||
* Return a new {@link ParameterSource}.
|
||||
* @param input the raw message or query result to be transformed into a {@link ParameterSource}
|
||||
*/
|
||||
ParameterSource createParameterSource(Object input);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface PositionSupportingParameterSource extends ParameterSource {
|
||||
|
||||
Object getValueByPosition(int position);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Provides generic support for ParameterSources and ParameterSource Factories.
|
||||
* This classes are modeled after the equivalent classes in the JDBC Module. However,
|
||||
* the provided classes here do not have any SQL or JPA specific dependencies.
|
||||
*/
|
||||
package org.springframework.integration.jpa.support.parametersource;
|
||||
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/integration/jpa=org.springframework.integration.jpa.config.xml.JpaNamespaceHandler
|
||||
@@ -0,0 +1,2 @@
|
||||
http\://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd=org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd
|
||||
http\://www.springframework.org/schema/integration/jpa/spring-integration-jpa.xsd=org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd
|
||||
@@ -0,0 +1,4 @@
|
||||
# Tooling related information for the integration jpa namespace
|
||||
http\://www.springframework.org/schema/integration/jpa@name=integration JPA Namespace
|
||||
http\://www.springframework.org/schema/integration/jpa@prefix=int-jpa
|
||||
http\://www.springframework.org/schema/integration/jpa@icon=org/springframework/integration/jdbc/config/xml/spring-integration-jpa.gif
|
||||
@@ -0,0 +1,578 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/jpa"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/jpa"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.1.xsd" />
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements for Spring Integration's JPA Adapter.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The definition for the Spring Integration JPA Inbound Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="coreJpaComponentAttributes"/>
|
||||
<xsd:attribute name="channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="parameter-source" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.jpa.core.JpaQLParameterSource" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
specifies the parameter source that would be used to
|
||||
provide additional parameters.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</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 as a result from the executed JPA operation.
|
||||
|
||||
If set to 'true' and the result list from the JPA operations
|
||||
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.
|
||||
|
||||
If set to 'false', the complete result list is returned
|
||||
as the payload.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="delete-after-poll" default="false" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Once entities have been retrieved from the database, shall
|
||||
they be removed from the database?
|
||||
|
||||
If instead of deleting the retrieved entities, you would
|
||||
rather like to updated them, e.g. setting a flag in a
|
||||
column marking the record as retrieved, please consider
|
||||
using a subsequent Outbound Gateway (coupled with a payload enricher).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="delete-per-row" default="false" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
If you want to automatically remove retrieved entities from
|
||||
the database you can also specify using the 'delete-per-row'
|
||||
attribute, whether the list of retrieved objects shall be
|
||||
deleted on a 'per-object-basis (true) or whether the objects
|
||||
shall be removed using a batch operation (false). The
|
||||
attribute defaults to 'false'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="send-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Allows you to specify how long this inbound-channel-adapter
|
||||
will wait for the message (containing the retrieved entities)
|
||||
to be sent successfully to the message channel, before throwing
|
||||
an exception.
|
||||
|
||||
Keep in mind that when sending to a DirectChannel, the
|
||||
invocation will occur in the sender's thread so the failing
|
||||
of the send operation may be caused by other components
|
||||
further downstream. By default the Inbound Channel Adapter
|
||||
will wait indefinitely. The value is specified in milliseconds.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound Channel Adapter for updating a
|
||||
database using the Java Persistence API (JPA).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="transactional" type="integration:transactionalType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="parameterSubElementType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Provides a mechanism to provide
|
||||
parameters for the queries that are either based
|
||||
on the Java Persistence Query Language (JPQL) or
|
||||
native SQL queries.
|
||||
|
||||
Parameters can also be provided for Named Queries.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="coreJpaComponentAttributes"/>
|
||||
<xsd:attribute name="persist-mode" use="optional" default="MERGE">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the persistence mode which is used when soley using
|
||||
the entity-class. This attribute instructs to either Merge
|
||||
entities, to Persist them. Furthermore and entity can also
|
||||
be deleted. By Default 'MERGE' is used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="persistMode xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="use-payload-as-parameter-source">
|
||||
<xsd:annotation>
|
||||
<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 JPA Parameters are passed in, this property
|
||||
will default to 'true'. This means that using a default
|
||||
BeanPropertyParameterSourceFactory, the bean properties
|
||||
of the payload will be used as a source for parameter
|
||||
values for the to-be-executed JPA query.
|
||||
|
||||
However, if JPA Parameters are passed in, then this
|
||||
property will by default evaluate to 'false'. JPA Parameters
|
||||
allow for SpEL Expressions to be provided and therefore
|
||||
it is highly beneficial to have access to the entire Message.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="parameter-source-factory"
|
||||
type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Reference to a ParameterSourceFactory.
|
||||
</xsd:documentation>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.jpa.support.parametersource.ParameterSourceFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Channel from which messages will be output.
|
||||
When a message is sent to this channel it will
|
||||
cause the query
|
||||
to be executed.
|
||||
</xsd:documentation>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies the order for invocation when this endpoint is connected as a
|
||||
subscriber to a SubscribableChannel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines the Spring Integration JPA Outbound Gateway
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="transactional" type="integration:transactionalType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="parameterSubElementType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Provides a mechanism to provide
|
||||
parameters for the queries that are either based
|
||||
on the Java Persistence Query Language (JPQL) or
|
||||
native SQL queries.
|
||||
|
||||
Parameters can also be provided for Named Queries.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="coreJpaComponentAttributes" />
|
||||
<xsd:attribute name="gateway-type" use="optional" default="UPDATING">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The outbound JPA gateway basically wraps the functionality
|
||||
of the 'outbound-channel-adapter' and the 'inbound-channel-adapter'.
|
||||
By specifying the gateway-type, you bascially specify which
|
||||
set of functionlity you would like to use. The attribute defaults
|
||||
to 'UPDATING'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="gatewayType xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="persist-mode" use="optional" default="MERGE">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the persistence mode which is used when soley using
|
||||
the entity-class. This attribute instructs to either Merge
|
||||
entities, to Persist them. Furthermore and entity can also
|
||||
be deleted. By Default 'MERGE' is used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="persistMode xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="use-payload-as-parameter-source">
|
||||
<xsd:annotation>
|
||||
<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 JPA Parameters are passed in, this property
|
||||
will default to 'true'. This means that using a default
|
||||
BeanPropertyParameterSourceFactory, the bean properties
|
||||
of the payload will be used as a source for parameter
|
||||
values for the to-be-executed JPA query.
|
||||
|
||||
However, if JPA Parameters are passed in, then this
|
||||
property will by default evaluate to 'false'. JPA Parameters
|
||||
allow for SpEL Expressions to be provided and therefore
|
||||
it is highly beneficial to have access to the entire Message.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-channel" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The receiving Message Channel of this endpoint.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Message Channel to which replies should be
|
||||
sent, after receiving the database response.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Allows you to specify how long this gateway will wait for
|
||||
the reply message to be sent successfully before throwing
|
||||
an exception. Keep in mind that when sending to a
|
||||
DirectChannel, the invocation will occur in the sender's thread
|
||||
so the failing of the send operation may be caused by other
|
||||
components further downstream. By default the Gateway will
|
||||
wait indefinitely. The value is specified in milliseconds.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="parameter-source-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.jpa.JPAQLParameterSourceFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The parameter source factory that would be used for evaluating the
|
||||
parameters of the response JPA QL that would be evaluated
|
||||
JPA outbound gateway
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies the order for invocation when this endpoint is connected as a
|
||||
subscriber to a SubscribableChannel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-number-of-results">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies the maximum number of entities that shall be returned
|
||||
by a JPA Operation. Using this attribute you basically set
|
||||
the 'maxResults' property of the JPA Query object.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</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 as a result from the executed JPA operation.
|
||||
|
||||
If set to 'true' and the result list from the JPA operations
|
||||
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.
|
||||
|
||||
If set to 'false', the complete result list is returned
|
||||
as the payload.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="parameterSubElementType">
|
||||
<xsd:attribute name="name" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of Jpa parameter. This parameter can also be used for
|
||||
native SQL query parameters. The name attribute is optional.
|
||||
If the name is not provided, this parameter will act as a positional
|
||||
parameters, in which case the order of the parameter sub-element
|
||||
matters.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="value" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The value of the parameter. Either this or the 'expression'
|
||||
attribute must be provided.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The type of the value used. If nothing is provided this attribute
|
||||
will default to java.lang.String. This attribute is not used
|
||||
when the 'expression' attribute is used instead.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Expression to be evaluated to produce a parameter value.
|
||||
Either this or the 'value' attribute must be provided.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:attributeGroup name="coreJpaComponentAttributes">
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Identifies the underlying Spring bean definition, which is an
|
||||
instance of either 'EventDrivenConsumer' or 'PollingConsumer',
|
||||
depending on whether the component's input channel is a
|
||||
'SubscribableChannel' or 'PollableChannel'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="entity-manager-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The reference to the JPA Entity Manager Factory
|
||||
that will be used by the adapter to create the EntityManager.
|
||||
Either this attribute or the 'enity-manager' attribute or the
|
||||
'jpa-operations' attribute must be provided.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="javax.persistence.EntityManagerFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="entity-manager" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The reference to the JPA Entity Manager that will be used by
|
||||
the adapter. Either this attribute or the 'enity-manager-factory'
|
||||
attribute or the 'jpa-operations' attribute must be provided.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="javax.persistence.EntityManager" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="jpa-operations" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Reference to a bean implementing the JpaOperations interface.
|
||||
|
||||
In rare cases it might be advisable to provide your own implementation
|
||||
of the JpaOperations interface, instead of relying on the
|
||||
default implementation. As JpaOperations wraps the necessay
|
||||
datasource; the JPA Entity Manager or JPA Entity Manager Factory
|
||||
must not be provided if the 'jpa-operations' attribute is used.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.jpa.core.JpaOperations" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="entity-class">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The reference to the JPA Persistence Entity. If not specified the
|
||||
entity class will be retrieved from the Message's payload (for
|
||||
operation that involve an enityClass).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="value">
|
||||
<tool:expected-type type="java.lang.Class" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="jpa-query" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Defines the JPA query (Java Persistence Query Language) to be used.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="native-query" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the native SQL query to be used.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="named-query" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
This attribute refers to a named query. A named query can be
|
||||
either be defined in Native SQL or JPAQL but the underlying JPA
|
||||
persistence provider handles that distinction internally.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" default="true" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate that the component should start automatically
|
||||
on startup (default true).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:simpleType name="persistMode">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="DELETE"/>
|
||||
<xsd:enumeration value="MERGE"/>
|
||||
<xsd:enumeration value="PERSIST"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="gatewayType">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="UPDATING"/>
|
||||
<xsd:enumeration value="RETRIEVING"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:schema>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 572 B |
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.core.JpaOperations;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaInboundChannelAdapterParserTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private SourcePollingChannelAdapter consumer;
|
||||
|
||||
@Test
|
||||
public void testJpaInboundChannelAdapterParser() throws Exception {
|
||||
|
||||
setUp("JpaInboundChannelAdapterParserTests.xml", getClass());
|
||||
|
||||
final AbstractMessageChannel outputChannel = TestUtils.getPropertyValue(this.consumer, "outputChannel", AbstractMessageChannel.class);
|
||||
|
||||
assertEquals("out", outputChannel.getComponentName());
|
||||
|
||||
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "source.jpaExecutor", JpaExecutor.class);
|
||||
|
||||
assertNotNull(jpaExecutor);
|
||||
|
||||
final Class<?> entityClass = TestUtils.getPropertyValue(jpaExecutor, "entityClass", Class.class);
|
||||
|
||||
assertEquals("org.springframework.integration.jpa.test.entity.StudentDomain", entityClass.getName());
|
||||
|
||||
final JpaOperations jpaOperations = TestUtils.getPropertyValue(jpaExecutor, "jpaOperations", JpaOperations.class);
|
||||
|
||||
assertNotNull(jpaOperations);
|
||||
|
||||
assertTrue(TestUtils.getPropertyValue(jpaExecutor, "expectSingleResult", Boolean.class));
|
||||
|
||||
}
|
||||
|
||||
@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("jpaInboundChannelAdapter", SourcePollingChannelAdapter.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
<int:channel id="out"/>
|
||||
|
||||
<int-jpa:inbound-channel-adapter id="jpaInboundChannelAdapter"
|
||||
entity-manager-factory="entityManagerFactory"
|
||||
entity-class="org.springframework.integration.jpa.test.entity.StudentDomain"
|
||||
expect-single-result="true"
|
||||
channel="out">
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-jpa:inbound-channel-adapter>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
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.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.core.JpaOperations;
|
||||
import org.springframework.integration.jpa.support.JpaParameter;
|
||||
import org.springframework.integration.jpa.support.PersistMode;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaMessageHandlerParserTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private EventDrivenConsumer consumer;
|
||||
|
||||
@Test
|
||||
public void testJpaMessageHandlerParser() throws Exception {
|
||||
setUp("JpaMessageHandlerParserTests.xml", getClass());
|
||||
|
||||
|
||||
final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", AbstractMessageChannel.class);
|
||||
|
||||
assertEquals("target", inputChannel.getComponentName());
|
||||
|
||||
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
|
||||
|
||||
assertNotNull(jpaExecutor);
|
||||
|
||||
final String query = TestUtils.getPropertyValue(jpaExecutor, "jpaQuery", String.class);
|
||||
|
||||
assertEquals("from Student", query);
|
||||
|
||||
final JpaOperations jpaOperations = TestUtils.getPropertyValue(jpaExecutor, "jpaOperations", JpaOperations.class);
|
||||
|
||||
assertNotNull(jpaOperations);
|
||||
|
||||
final PersistMode persistMode = TestUtils.getPropertyValue(jpaExecutor, "persistMode", PersistMode.class);
|
||||
|
||||
assertEquals(PersistMode.PERSIST, persistMode);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<JpaParameter> jpaParameters = TestUtils.getPropertyValue(jpaExecutor, "jpaParameters", List.class);
|
||||
|
||||
assertNotNull(jpaParameters);
|
||||
assertTrue(jpaParameters.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpaMessageHandlerParserWithEntityManagerFactory() throws Exception {
|
||||
setUp("JpaMessageHandlerParserTestsWithEmFactory.xml", getClass());
|
||||
|
||||
|
||||
final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", AbstractMessageChannel.class);
|
||||
|
||||
assertEquals("target", inputChannel.getComponentName());
|
||||
|
||||
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
|
||||
|
||||
assertNotNull(jpaExecutor);
|
||||
|
||||
final String query = TestUtils.getPropertyValue(jpaExecutor, "jpaQuery", String.class);
|
||||
|
||||
assertEquals("select student from Student student", query);
|
||||
|
||||
final JpaOperations jpaOperations = TestUtils.getPropertyValue(jpaExecutor, "jpaOperations", JpaOperations.class);
|
||||
|
||||
assertNotNull(jpaOperations);
|
||||
|
||||
final PersistMode persistMode = TestUtils.getPropertyValue(jpaExecutor, "persistMode", PersistMode.class);
|
||||
|
||||
assertEquals(PersistMode.PERSIST, persistMode);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<JpaParameter> jpaParameters = TestUtils.getPropertyValue(jpaExecutor, "jpaParameters", List.class);
|
||||
|
||||
assertNotNull(jpaParameters);
|
||||
assertTrue(jpaParameters.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testProcedurepParametersAreSet() throws Exception {
|
||||
setUp("JpaMessageHandlerParserTestsWithEmFactory.xml", getClass());
|
||||
|
||||
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
|
||||
final List<JpaParameter> jpaParameters = TestUtils.getPropertyValue(jpaExecutor, "jpaParameters", List.class);
|
||||
|
||||
assertTrue(jpaParameters.size() == 3);
|
||||
|
||||
JpaParameter parameter1 = jpaParameters.get(0);
|
||||
JpaParameter parameter2 = jpaParameters.get(1);
|
||||
JpaParameter parameter3 = jpaParameters.get(2);
|
||||
|
||||
assertEquals("firstName", parameter1.getName());
|
||||
assertEquals("firstaName", parameter2.getName());
|
||||
assertEquals("updatedDateTime", parameter3.getName());
|
||||
|
||||
assertEquals("kenny", parameter1.getValue());
|
||||
assertEquals("cartman", parameter2.getValue());
|
||||
assertNull(parameter3.getValue());
|
||||
|
||||
assertNull(parameter1.getExpression());
|
||||
assertNull(parameter2.getExpression());
|
||||
assertEquals("new java.util.Date()", parameter3.getExpression());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionalSettings() throws Exception {
|
||||
|
||||
setUp("JpaMessageHandlerTransactionalParserTests.xml", getClass());
|
||||
|
||||
final Proxy proxy = TestUtils.getPropertyValue(this.consumer, "handler", Proxy.class);
|
||||
assertNotNull(proxy);
|
||||
|
||||
}
|
||||
|
||||
@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("jpaOutboundChannelAdapter", EventDrivenConsumer.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
<int:channel id="target"/>
|
||||
|
||||
<int-jpa:outbound-channel-adapter id="jpaOutboundChannelAdapter"
|
||||
entity-manager="entityManager"
|
||||
auto-startup="true"
|
||||
entity-class="org.springframework.integration.jpa.test.entity.StudentDomain"
|
||||
jpa-query="from Student"
|
||||
persist-mode="PERSIST"
|
||||
order="1"
|
||||
channel="target">
|
||||
<int-jpa:parameter name="firstName" value="kenny" type="java.lang.String"/>
|
||||
<int-jpa:parameter name="firstaName" value="cartman"/>
|
||||
<int-jpa:parameter name="updatedDateTime" expression="new java.util.Date()"/>
|
||||
</int-jpa:outbound-channel-adapter>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
<int:channel id="target"/>
|
||||
|
||||
<int-jpa:outbound-channel-adapter id="jpaOutboundChannelAdapter"
|
||||
entity-manager-factory="entityManagerFactory"
|
||||
auto-startup="true"
|
||||
entity-class="org.springframework.integration.jpa.test.entity.StudentDomain"
|
||||
jpa-query="select student from Student student"
|
||||
persist-mode="PERSIST"
|
||||
order="1"
|
||||
channel="target">
|
||||
<int-jpa:parameter name="firstName" value="kenny" type="java.lang.String"/>
|
||||
<int-jpa:parameter name="firstaName" value="cartman"/>
|
||||
<int-jpa:parameter name="updatedDateTime" expression="new java.util.Date()"/>
|
||||
</int-jpa:outbound-channel-adapter>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
<int:channel id="target"/>
|
||||
|
||||
<int-jpa:outbound-channel-adapter id="jpaOutboundChannelAdapter"
|
||||
entity-manager="entityManager"
|
||||
auto-startup="true"
|
||||
entity-class="org.springframework.integration.jpa.test.entity.StudentDomain"
|
||||
jpa-query="select student from Student student"
|
||||
persist-mode="PERSIST"
|
||||
order="1"
|
||||
channel="target">
|
||||
<int-jpa:transactional transaction-manager="transactionManager"/>
|
||||
<int-jpa:parameter name="firstName" value="kenny" type="java.lang.String"/>
|
||||
<int-jpa:parameter name="firstaName" value="cartman"/>
|
||||
<int-jpa:parameter name="updatedDateTime" expression="new java.util.Date()"/>
|
||||
</int-jpa:outbound-channel-adapter>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.core.JpaOperations;
|
||||
import org.springframework.integration.jpa.outbound.JpaOutboundGateway;
|
||||
import org.springframework.integration.jpa.support.OutboundGatewayType;
|
||||
import org.springframework.integration.jpa.support.PersistMode;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaOutboundGatewayParserTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private EventDrivenConsumer consumer;
|
||||
|
||||
@Test
|
||||
public void testJpaOutboundGatewayParser() throws Exception {
|
||||
setUp("JpaOutboundGatewayParserTests.xml", getClass());
|
||||
|
||||
|
||||
final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", AbstractMessageChannel.class);
|
||||
|
||||
assertEquals("in", inputChannel.getComponentName());
|
||||
|
||||
final JpaOutboundGateway jpaOutboundGateway = TestUtils.getPropertyValue(this.consumer, "handler", JpaOutboundGateway.class);
|
||||
|
||||
final OutboundGatewayType gatewayType = TestUtils.getPropertyValue(jpaOutboundGateway, "gatewayType", OutboundGatewayType.class);
|
||||
|
||||
assertEquals(OutboundGatewayType.RETRIEVING, gatewayType);
|
||||
|
||||
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
|
||||
|
||||
assertNotNull(jpaExecutor);
|
||||
|
||||
final Class<?> entityClass = TestUtils.getPropertyValue(jpaExecutor, "entityClass", Class.class);
|
||||
|
||||
assertEquals("org.springframework.integration.jpa.test.entity.StudentDomain", entityClass.getName());
|
||||
|
||||
final JpaOperations jpaOperations = TestUtils.getPropertyValue(jpaExecutor, "jpaOperations", JpaOperations.class);
|
||||
|
||||
assertNotNull(jpaOperations);
|
||||
|
||||
final PersistMode persistMode = TestUtils.getPropertyValue(jpaExecutor, "persistMode", PersistMode.class);
|
||||
|
||||
assertEquals(PersistMode.PERSIST, persistMode);
|
||||
|
||||
assertTrue(TestUtils.getPropertyValue(jpaExecutor, "expectSingleResult", Boolean.class));
|
||||
|
||||
}
|
||||
|
||||
@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("jpaOutboundGateway", EventDrivenConsumer.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?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="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
<int:channel id="in"/>
|
||||
<int:channel id="out"/>
|
||||
|
||||
<int-jpa:outbound-gateway id="jpaOutboundGateway"
|
||||
entity-manager-factory="entityManagerFactory"
|
||||
auto-startup="true"
|
||||
entity-class="org.springframework.integration.jpa.test.entity.StudentDomain"
|
||||
expect-single-result="true"
|
||||
persist-mode="PERSIST"
|
||||
gateway-type="RETRIEVING"
|
||||
order="1"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.jpa.support.parametersource.ExpressionEvaluatingParameterSourceFactory;
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSource;
|
||||
import org.springframework.integration.jpa.support.parametersource.ParameterSourceFactory;
|
||||
import org.springframework.integration.jpa.test.JpaTestUtils;
|
||||
import org.springframework.integration.jpa.test.entity.Gender;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@Transactional
|
||||
public class AbstractJpaOperationsTests {
|
||||
|
||||
@Autowired
|
||||
protected PlatformTransactionManager transactionManager;
|
||||
|
||||
@Autowired
|
||||
protected EntityManager entityManager;
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#executeUpdate(java.lang.String, org.springframework.integration.jpa.core.JpaQLParameterSource)}.
|
||||
*/
|
||||
public void testGetAllStudents() {
|
||||
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final List<?> students = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
Assert.assertTrue(students.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#executeUpdate(java.lang.String, org.springframework.integration.jpa.core.JpaQLParameterSource)}.
|
||||
*/
|
||||
public void testGetAllStudentsWithMaxResults() {
|
||||
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final List<?> students = jpaOperations.getResultListForClass(StudentDomain.class, 2);
|
||||
Assert.assertTrue(String.format("Was expecting 2 Students to be returned but got '%s'.", students.size()),
|
||||
students.size() == 2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#executeUpdate(java.lang.String, org.springframework.integration.jpa.core.JpaQLParameterSource)}.
|
||||
*/
|
||||
public void testExecuteUpdate() {
|
||||
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
List<?> students = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
Assert.assertTrue(students.size() == 3);
|
||||
|
||||
ParameterSourceFactory requestParameterSourceFactory = new ExpressionEvaluatingParameterSourceFactory();
|
||||
ParameterSource source = requestParameterSourceFactory.createParameterSource(student);
|
||||
|
||||
int updatedRecords = jpaOperations.executeUpdate("update Student s set s.lastName = :lastName, s.lastUpdated = :lastUpdated "
|
||||
+ "where s.rollNumber in (select max(a.rollNumber) from Student a)", source);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
Assert.assertTrue( 1 == updatedRecords);
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#executeUpdateWithNamedQuery(java.lang.String, org.springframework.integration.jpa.core.JpaQLParameterSource)}.
|
||||
*/
|
||||
public void testExecuteUpdateWithNamedQuery() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
ParameterSourceFactory requestParameterSourceFactory = new ExpressionEvaluatingParameterSourceFactory();
|
||||
ParameterSource source = requestParameterSourceFactory.createParameterSource(student);
|
||||
|
||||
int updatedRecords = jpaOperations.executeUpdateWithNamedQuery("updateStudent", source);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
Assert.assertTrue( 1 == updatedRecords);
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#executeUpdateWithNativeQuery(java.lang.String, org.springframework.integration.jpa.core.JpaQLParameterSource)}.
|
||||
*/
|
||||
public void testExecuteUpdateWithNativeQuery() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
ParameterSourceFactory requestParameterSourceFactory = new ExpressionEvaluatingParameterSourceFactory();
|
||||
ParameterSource source = requestParameterSourceFactory.createParameterSource(student);
|
||||
|
||||
int updatedRecords = jpaOperations.executeUpdateWithNativeQuery("update Student set lastName = :lastName, lastUpdated = :lastUpdated "
|
||||
+ "where rollNumber in (select max(a.rollNumber) from Student a)", source);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
Assert.assertTrue( 1 == updatedRecords);
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link DefaultJpaOperations#getResultListForNativeQuery(String, Class, JpaQLParameterSource, int, int)}.
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void testExecuteSelectWithNativeQueryReturningEntityClass() throws ParseException {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
String selectSqlQuery = "select * from Student where lastName = 'Last One'";
|
||||
|
||||
Class<?> entityClass = StudentDomain.class;
|
||||
|
||||
List<?> students = jpaOperations.getResultListForNativeQuery(selectSqlQuery, entityClass, null, 0);
|
||||
|
||||
Assert.assertTrue(students.size() == 1);
|
||||
|
||||
StudentDomain retrievedStudent = (StudentDomain) students.iterator().next();
|
||||
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
|
||||
|
||||
assertEquals(formatter.parse("1980/01/01"), retrievedStudent.getDateOfBirth());
|
||||
assertEquals("First One", retrievedStudent.getFirstName());
|
||||
assertEquals(Gender.MALE, retrievedStudent.getGender());
|
||||
assertEquals("Last One", retrievedStudent.getLastName());
|
||||
assertNotNull(retrievedStudent.getLastUpdated());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link DefaultJpaOperations#getResultListForNativeQuery(String, Class, JpaQLParameterSource, int, int)}.
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void testExecuteSelectWithNativeQuery() throws ParseException {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
String selectSqlQuery = "select rollNumber, firstName, lastName, gender, dateOfBirth, lastUpdated from Student where lastName = 'Last One'";
|
||||
|
||||
List<?> students = jpaOperations.getResultListForNativeQuery(selectSqlQuery, null, null, 0);
|
||||
|
||||
Assert.assertTrue(students.size() == 1);
|
||||
|
||||
Object[] retrievedStudent = (Object[]) students.iterator().next();
|
||||
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
|
||||
|
||||
assertNotNull(retrievedStudent[0]);
|
||||
assertEquals("First One", retrievedStudent[1]);
|
||||
assertEquals("Last One", retrievedStudent[2]);
|
||||
assertEquals("M", retrievedStudent[3]);
|
||||
assertEquals(formatter.parse("1980/01/01"), retrievedStudent[4]);
|
||||
assertNotNull(retrievedStudent[5]);
|
||||
|
||||
}
|
||||
|
||||
public void testExecuteUpdateWithNativeNamedQuery() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
ParameterSourceFactory requestParameterSourceFactory = new ExpressionEvaluatingParameterSourceFactory();
|
||||
ParameterSource source = requestParameterSourceFactory.createParameterSource(student);
|
||||
|
||||
int updatedRecords = jpaOperations.executeUpdateWithNamedQuery("updateStudentNativeQuery", source);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
Assert.assertTrue( 1 == updatedRecords);
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#merge(java.lang.Object)}.
|
||||
*/
|
||||
public void testMerge() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
final StudentDomain savedStudent = (StudentDomain) jpaOperations.merge(student);
|
||||
entityManager.flush();
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
Assert.assertNotNull(savedStudent);
|
||||
Assert.assertNotNull(savedStudent.getRollNumber());
|
||||
|
||||
Assert.assertTrue(student != savedStudent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#persist(java.lang.Object)}.
|
||||
*/
|
||||
public void testPersist() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
|
||||
Assert.assertNull(student.getRollNumber());
|
||||
jpaOperations.persist(student);
|
||||
entityManager.flush();
|
||||
Assert.assertNotNull(student.getRollNumber());
|
||||
}
|
||||
|
||||
|
||||
public void testDeleteInBatch() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final List<?> students = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(students);
|
||||
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeOtherTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
|
||||
jpaOperations.deleteInBatch(students);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
transactionManager.commit(status);
|
||||
|
||||
final List<?> studentsFromDb = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(studentsFromDb);
|
||||
Assert.assertTrue(studentsFromDb.size() == 0);
|
||||
|
||||
}
|
||||
|
||||
protected JpaOperations getJpaOperations(EntityManager entityManager) {
|
||||
|
||||
final DefaultJpaOperations jpaOperationsImpl = new DefaultJpaOperations();
|
||||
jpaOperationsImpl.setEntityManager(entityManager);
|
||||
jpaOperationsImpl.afterPropertiesSet();
|
||||
|
||||
return jpaOperationsImpl;
|
||||
}
|
||||
|
||||
public void testDelete() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final List<?> studentsFromDb = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(studentsFromDb);
|
||||
Assert.assertTrue(studentsFromDb.size() == 3);
|
||||
|
||||
|
||||
final StudentDomain student = jpaOperations.find(StudentDomain.class, 1001L);
|
||||
|
||||
Assert.assertNotNull(student);
|
||||
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeOtherTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
|
||||
jpaOperations.delete(student);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
transactionManager.commit(status);
|
||||
|
||||
final List<?> studentsFromDbAfterDelete = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(studentsFromDbAfterDelete);
|
||||
Assert.assertTrue(studentsFromDbAfterDelete.size() == 2);
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteInBatchWithEmptyCollection() {
|
||||
final JpaOperations jpaOperations = getJpaOperations(entityManager);
|
||||
|
||||
final List<?> students = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(students);
|
||||
Assert.assertTrue(students.size() == 3);
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeOtherTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
|
||||
jpaOperations.deleteInBatch(new ArrayList<StudentDomain>(0));
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
transactionManager.commit(status);
|
||||
|
||||
final List<?> studentsFromDb = jpaOperations.getResultListForClass(StudentDomain.class, 0);
|
||||
|
||||
Assert.assertNotNull(studentsFromDb);
|
||||
Assert.assertTrue(studentsFromDb.size() == 3); //Nothing should have happened
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
<import resource="classpath:/commonJpa-context.xml" />
|
||||
|
||||
<bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"
|
||||
parent="abstractVendorAdaptor">
|
||||
<property name="database" value="H2" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Tests the functionality of {@link JpaOperations} and {@link DefaultJpaOperations}
|
||||
* using the EclipseLink persistence provider.
|
||||
*
|
||||
* If you want to run these tests from your IDE, please ensure that you execute
|
||||
* the tests using a <i>javaagent</i>:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* -javaagent:/home/<user>/.m2/repository/org/springframework/spring-instrument/3.1.1.RELEASE/spring-instrument-3.1.1.RELEASE.jar
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class EclipseLinkJpaOperationsTests extends AbstractJpaOperationsTests {
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeQuery() {
|
||||
|
||||
try {
|
||||
super.testExecuteUpdateWithNativeQuery();
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting an Exception as OpenJPA does not support Native SQL Queries with Named Parameters.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeNamedQuery() {
|
||||
|
||||
try {
|
||||
super.testExecuteUpdateWithNativeNamedQuery();
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting an Exception as OpenJPA does not support Native SQL Queries with Named Parameters.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdate() {
|
||||
super.testExecuteUpdate();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNamedQuery() {
|
||||
super.testExecuteUpdateWithNamedQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQueryReturningEntityClass()
|
||||
throws ParseException {
|
||||
super.testExecuteSelectWithNativeQueryReturningEntityClass();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQuery() throws ParseException {
|
||||
super.testExecuteSelectWithNativeQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testMerge() {
|
||||
super.testMerge();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testPersist() {
|
||||
super.testPersist();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudents() {
|
||||
super.testGetAllStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudentsWithMaxResults() {
|
||||
super.testGetAllStudentsWithMaxResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatch() {
|
||||
super.testDeleteInBatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDelete() {
|
||||
super.testDelete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatchWithEmptyCollection() {
|
||||
super.testDeleteInBatchWithEmptyCollection();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?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:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class HibernateJpaOperationsTests extends AbstractJpaOperationsTests {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
private LocalContainerEntityManagerFactoryBean fb;
|
||||
|
||||
/**
|
||||
* Little helper that allows you to generate the DDL via Hibernate. The
|
||||
* DDL is printed to the console.
|
||||
*/
|
||||
@Test
|
||||
public void generateDdl() {
|
||||
|
||||
final Ejb3Configuration cfg = new Ejb3Configuration();
|
||||
|
||||
Map properties = fb.getJpaPropertyMap();
|
||||
|
||||
|
||||
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
|
||||
|
||||
final Ejb3Configuration configured = cfg.configure( fb.getPersistenceUnitInfo(), fb.getJpaPropertyMap() );
|
||||
final Configuration configuration = configured.getHibernateConfiguration();
|
||||
|
||||
final SchemaExport schemaExport;
|
||||
|
||||
try {
|
||||
schemaExport = new SchemaExport(configuration, dataSource.getConnection());
|
||||
} catch (HibernateException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (SQLException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
schemaExport.create(true, false);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdate() {
|
||||
super.testExecuteUpdate();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudents() {
|
||||
super.testGetAllStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudentsWithMaxResults() {
|
||||
super.testGetAllStudentsWithMaxResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNamedQuery() {
|
||||
super.testExecuteUpdateWithNamedQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeQuery() {
|
||||
super.testExecuteUpdateWithNativeQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQueryReturningEntityClass()
|
||||
throws ParseException {
|
||||
super.testExecuteSelectWithNativeQueryReturningEntityClass();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQuery() throws ParseException {
|
||||
super.testExecuteSelectWithNativeQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeNamedQuery() {
|
||||
super.testExecuteUpdateWithNativeNamedQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testMerge() {
|
||||
super.testMerge();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testPersist() {
|
||||
super.testPersist();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatch() {
|
||||
super.testDeleteInBatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDelete() {
|
||||
super.testDelete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatchWithEmptyCollection() {
|
||||
super.testDeleteInBatchWithEmptyCollection();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaExecutorTests {
|
||||
|
||||
/**
|
||||
* In this test, the {@link JpaExecutor}'s poll method will be called without
|
||||
* specifying a 'query', 'namedQuery' or 'entityClass' property. This should
|
||||
* result in an {@link IllegalArgumentException}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testExecutePollWithNoEntityClassSpecified() throws Exception {
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(mock(EntityManager.class));
|
||||
|
||||
try {
|
||||
jpaExecutor.poll();
|
||||
} catch (IllegalStateException e) {
|
||||
Assert.assertEquals("Exception Message does not match.",
|
||||
"For the polling operation, one of "
|
||||
+ "the following properties must be specified: "
|
||||
+ "query, namedQuery or entityClass.", e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting an IllegalStateException to be thrown.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Test
|
||||
public void testInstatiateJpaExecutorWithNullJpaOperations() {
|
||||
|
||||
JpaOperations jpaOperations = null;
|
||||
|
||||
try {
|
||||
new JpaExecutor(jpaOperations);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("jpaOperations must not be null.", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
<import resource="classpath:/commonJpa-context.xml" />
|
||||
|
||||
<!-- EclipseLink vendor adaptor with workaround platform class for HSQL usage -->
|
||||
<bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"
|
||||
parent="abstractVendorAdaptor">
|
||||
<property name="database" value="H2" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
|
||||
import org.apache.openjpa.jdbc.meta.MappingTool;
|
||||
import org.apache.openjpa.lib.conf.Configurations;
|
||||
import org.apache.openjpa.lib.util.Options;
|
||||
import org.apache.openjpa.persistence.InvalidStateException;
|
||||
import org.apache.openjpa.persistence.PersistenceException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Tests the functionality of {@link JpaOperations} and {@link DefaultJpaOperations}
|
||||
* using the OpenJPA persistence provider.
|
||||
*
|
||||
* If you want to run these tests from your IDE, please ensure that you execute
|
||||
* the tests using a <i>javaagent</i>:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* -javaagent:/<path_to>/openjpa-2.1.1.jar
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class OpenJpaJpaOperationsTests extends AbstractJpaOperationsTests {
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeQuery() {
|
||||
|
||||
try {
|
||||
super.testExecuteUpdateWithNativeQuery();
|
||||
} catch (PersistenceException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting an Exception as OpenJPA does not support Native SQL Queries with Named Parameters.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNativeNamedQuery() {
|
||||
|
||||
try {
|
||||
super.testExecuteUpdateWithNativeNamedQuery();
|
||||
} catch (InvalidStateException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting an Exception as OpenJPA does not support Native SQL Queries with Named Parameters.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.jpa.core.DefaultJpaOperations#persist(java.lang.Object)}.
|
||||
*
|
||||
* http://openjpa.apache.org/builds/1.0.4/apache-openjpa-1.0.4/docs/manual/manual.html#ref_guide_ddl_examples
|
||||
*/
|
||||
//@Test
|
||||
public void testGenerateSchema() {
|
||||
|
||||
String[] arguments = {};
|
||||
|
||||
Options opts = new Options();
|
||||
opts.put("schemaAction", "build");
|
||||
opts.put("sql", "build/database/openjpa-h2.sql");
|
||||
opts.put("org.springframework.integration.jpa.test.entity.Student", "true");
|
||||
|
||||
final String[] args = opts.setFromCmdLine(arguments);
|
||||
|
||||
boolean ret = Configurations.runAgainstAllAnchors(opts,
|
||||
new Configurations.Runnable() {
|
||||
public boolean run(Options opts) throws IOException, SQLException {
|
||||
JDBCConfiguration conf = new JDBCConfigurationImpl();
|
||||
conf.setConnectionDriverName("org.h2.Driver");
|
||||
conf.setConnectionURL("jdbc:h2:~/test");
|
||||
conf.setConnectionUserName("sa");
|
||||
conf.setConnectionPassword("");
|
||||
|
||||
try {
|
||||
return MappingTool.run(conf, args, opts);
|
||||
} finally {
|
||||
conf.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdate() {
|
||||
super.testExecuteUpdate();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteUpdateWithNamedQuery() {
|
||||
super.testExecuteUpdateWithNamedQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQueryReturningEntityClass()
|
||||
throws ParseException {
|
||||
super.testExecuteSelectWithNativeQueryReturningEntityClass();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testExecuteSelectWithNativeQuery() throws ParseException {
|
||||
super.testExecuteSelectWithNativeQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testMerge() {
|
||||
super.testMerge();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testPersist() {
|
||||
super.testPersist();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudents() {
|
||||
super.testGetAllStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testGetAllStudentsWithMaxResults() {
|
||||
super.testGetAllStudentsWithMaxResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatch() {
|
||||
super.testDeleteInBatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDelete() {
|
||||
super.testDelete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testDeleteInBatchWithEmptyCollection() {
|
||||
super.testDeleteInBatchWithEmptyCollection();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.2.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="H2"/>
|
||||
|
||||
<tx:annotation-driven transaction-manager="transactionManager"/>
|
||||
|
||||
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS" >
|
||||
<jdbc:script location="classpath:H2-DropTables.sql" />
|
||||
<jdbc:script location="classpath:H2-CreateTables.sql" />
|
||||
<jdbc:script location="classpath:H2-PopulateData.sql" />
|
||||
</jdbc:initialize-database>
|
||||
|
||||
<bean id="lc"
|
||||
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
|
||||
<property name="showSql" value="true"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="em"
|
||||
class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
|
||||
<property name="entityManagerFactory" ref="lc" />
|
||||
</bean>
|
||||
|
||||
|
||||
<!-- Define the JPA transaction mgr -->
|
||||
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<constructor-arg ref="lc" />
|
||||
</bean>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<int:service-activator id="consumerEndpoint" input-channel="outputChannel" ref="consumer" method="receive" />
|
||||
|
||||
<bean id="consumer" class="org.springframework.integration.jpa.test.Consumer" />
|
||||
|
||||
<bean id="testtrigger" class="org.springframework.integration.jpa.test.TestTrigger" />
|
||||
|
||||
<int:poller id="defaultPoller" default="true" fixed-rate="10000" />
|
||||
|
||||
<int:poller id="jpaPoller" trigger="testtrigger">
|
||||
<int:transactional transaction-manager="transactionManager"/>
|
||||
</int:poller>
|
||||
</beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation=
|
||||
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.2.xsd
|
||||
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<import resource="BaseJpaPollingChannelAdapterTests-context.xml"/>
|
||||
|
||||
<bean id="jpaOperations" class="org.springframework.integration.jpa.core.DefaultJpaOperations">
|
||||
<property name="entityManager" ref="em"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.inbound;
|
||||
|
||||
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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
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.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.core.JpaOperations;
|
||||
import org.springframework.integration.jpa.test.Consumer;
|
||||
import org.springframework.integration.jpa.test.JpaTestUtils;
|
||||
import org.springframework.integration.jpa.test.TestTrigger;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.TransactionConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the Jpa Polling Channel Adapter {@link JpaPollingChannelAdapter}.
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
|
||||
public class JpaPollingChannelAdapterTests {
|
||||
|
||||
@Autowired
|
||||
private GenericApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
JpaOperations jpaOperations;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jpaPoller")
|
||||
PollerMetadata poller;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("outputChannel")
|
||||
private MessageChannel outputChannel;
|
||||
|
||||
@Autowired
|
||||
TestTrigger testTrigger;
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use a plain entity class
|
||||
* to retrieve a list of records from the database.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testWithEntityClass() throws Exception {
|
||||
testTrigger.reset();
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setEntityClass(StudentDomain.class);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> primeNumbers = message.getPayload();
|
||||
|
||||
assertTrue(primeNumbers.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use JpQL query
|
||||
* to retrieve a list of records from the database.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWithJpaQuery() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setJpaQuery("from Student");
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> primeNumbers = message.getPayload();
|
||||
|
||||
assertTrue(primeNumbers.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use JpQL query
|
||||
* to retrieve a list of records from the database with a maxRows value of 1.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWithJpaQueryAndMaxResults() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setJpaQuery("from Student");
|
||||
jpaExecutor.setMaxRows(1);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> primeNumbers = message.getPayload();
|
||||
|
||||
assertTrue(primeNumbers.size() == 1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use JpQL query
|
||||
* to retrieve a list of records from the database.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWithJpaQueryOneResultOnly() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setJpaQuery("from Student s where s.firstName = 'First Two'");
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> students = message.getPayload();
|
||||
|
||||
assertTrue(students.size() == 1);
|
||||
|
||||
StudentDomain student = (StudentDomain) students.iterator().next();
|
||||
|
||||
assertEquals("Last Two", student.getLastName());
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use JpQL query
|
||||
* to retrieve a list of records from the database. Additionaly, the records
|
||||
* will be deleted after the polling.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Transactional
|
||||
public void testWithJpaQueryAndDelete() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setJpaQuery("from Student s");
|
||||
jpaExecutor.setDeleteAfterPoll(true);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull("Message is null.", message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> students = message.getPayload();
|
||||
|
||||
assertTrue(students.size() == 3);
|
||||
|
||||
Long studentCount = entityManager.createQuery("select count(*) from Student", Long.class).getSingleResult();
|
||||
|
||||
assertEquals(Long.valueOf(0), studentCount);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Transactional
|
||||
public void testWithJpaQueryButNoResultsAndDelete() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setJpaQuery("from Student s where s.lastName = 'Something Else'");
|
||||
jpaExecutor.setDeleteAfterPoll(true);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNull(message);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use JpQL query
|
||||
* to retrieve a list of records from the database. Additionaly, the records
|
||||
* will be deleted after the polling.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testWithJpaQueryAndDeletePerRow() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(jpaOperations);
|
||||
jpaExecutor.setJpaQuery("from Student s");
|
||||
jpaExecutor.setDeleteAfterPoll(true);
|
||||
jpaExecutor.setDeletePerRow(true);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
//adapter.stop();
|
||||
|
||||
assertNotNull("Message is null.", message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> students = message.getPayload();
|
||||
|
||||
assertTrue(students.size() == 3);
|
||||
|
||||
Long studentCount = entityManager.createQuery("select count(*) from Student", Long.class).getSingleResult();
|
||||
|
||||
assertEquals(Long.valueOf(0), studentCount);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use a Native SQL query
|
||||
* to retrieve a list of records from the database.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWithNativeSqlQuery() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setNativeQuery("select * from Student where lastName = 'Last One'");
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> students = message.getPayload();
|
||||
|
||||
assertTrue(students.size() == 1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, a Jpa Polling Channel Adapter will use Named query
|
||||
* to retrieve a list of records from the database.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testWithNamedQuery() throws Exception {
|
||||
testTrigger.reset();
|
||||
|
||||
//~~~~SETUP~~~~~
|
||||
|
||||
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setNamedQuery("selectStudent");
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
|
||||
final SourcePollingChannelAdapter adapter = JpaTestUtils.getSourcePollingChannelAdapter(
|
||||
jpaPollingChannelAdapter, this.outputChannel, this.poller, this.context, this.getClass().getClassLoader());
|
||||
adapter.start();
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
final List<Message<Collection<?>>> received = new ArrayList<Message<Collection<?>>>();
|
||||
|
||||
final Consumer consumer = new Consumer();
|
||||
|
||||
received.add(consumer.poll(5000));
|
||||
|
||||
Message<Collection<?>> message = received.get(0);
|
||||
|
||||
adapter.stop();
|
||||
|
||||
assertNotNull(message);
|
||||
assertNotNull(message.getPayload());
|
||||
assertNotNull(message.getPayload() instanceof Collection<?>);
|
||||
|
||||
Collection<?> students = message.getPayload();
|
||||
|
||||
assertTrue(students.size() == 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.inbound;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
|
||||
/**
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class JpaPollingChannelAdapterUnitTests {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testReceiveNull() {
|
||||
|
||||
JpaExecutor jpaExecutor = mock(JpaExecutor.class);
|
||||
|
||||
when(jpaExecutor.poll()).thenReturn(null);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
assertNull(jpaPollingChannelAdapter.receive());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testReceiveNotNull() {
|
||||
|
||||
JpaExecutor jpaExecutor = mock(JpaExecutor.class);
|
||||
|
||||
when(jpaExecutor.poll()).thenReturn("Spring");
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
assertNotNull("Expecting a Message to be returned.", jpaPollingChannelAdapter.receive());
|
||||
assertEquals("Spring", jpaPollingChannelAdapter.receive().getPayload());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetComponentType() {
|
||||
|
||||
JpaExecutor jpaExecutor = mock(JpaExecutor.class);
|
||||
|
||||
final JpaPollingChannelAdapter jpaPollingChannelAdapter = new JpaPollingChannelAdapter(jpaExecutor);
|
||||
assertEquals("jpa:inbound-channel-adapter", jpaPollingChannelAdapter.getComponentType());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation=
|
||||
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.2.xsd
|
||||
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<import resource="classpath:/hibernateJpa-context.xml" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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:jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation=
|
||||
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.1.xsd
|
||||
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<import resource="BaseJpaPollingChannelAdapterTests-context.xml"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.jpa.core.JpaExecutor;
|
||||
import org.springframework.integration.jpa.support.PersistMode;
|
||||
import org.springframework.integration.jpa.test.JpaTestUtils;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.TransactionConfiguration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
|
||||
public class JpaOutboundChannelAdapterTests {
|
||||
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void saveEntityWithMerge() throws InterruptedException {
|
||||
|
||||
List<?> results1 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results1);
|
||||
Assert.assertTrue(results1.size() == 3);
|
||||
|
||||
JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setEntityClass(StudentDomain.class);
|
||||
jpaExecutor.afterPropertiesSet();
|
||||
|
||||
JpaOutboundGateway jpaOutboundChannelAdapter = new JpaOutboundGateway(jpaExecutor);
|
||||
jpaOutboundChannelAdapter.setProducesReply(false);
|
||||
|
||||
StudentDomain testStudent = JpaTestUtils.getTestStudent();
|
||||
Message<StudentDomain> message = MessageBuilder.withPayload(testStudent).build();
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
jpaOutboundChannelAdapter.handleMessage(message);
|
||||
transactionManager.commit(status);
|
||||
|
||||
List<?> results2 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results2);
|
||||
Assert.assertTrue(results2.size() == 4);
|
||||
|
||||
Assert.assertNull(testStudent.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void saveEntityWithMergeWithoutSpecifyingEntityClass() throws InterruptedException {
|
||||
|
||||
List<?> results1 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results1);
|
||||
Assert.assertTrue(results1.size() == 3);
|
||||
|
||||
JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.afterPropertiesSet();
|
||||
|
||||
JpaOutboundGateway jpaOutboundChannelAdapter = new JpaOutboundGateway(jpaExecutor);
|
||||
jpaOutboundChannelAdapter.setProducesReply(false);
|
||||
|
||||
StudentDomain testStudent = JpaTestUtils.getTestStudent();
|
||||
Message<StudentDomain> message = MessageBuilder.withPayload(testStudent).build();
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
jpaOutboundChannelAdapter.handleMessage(message);
|
||||
transactionManager.commit(status);
|
||||
|
||||
List<?> results2 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results2);
|
||||
Assert.assertTrue(results2.size() == 4);
|
||||
|
||||
Assert.assertNull(testStudent.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveEntityWithPersist() throws InterruptedException {
|
||||
|
||||
List<?> results1 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results1);
|
||||
Assert.assertTrue(results1.size() == 3);
|
||||
|
||||
JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
|
||||
jpaExecutor.setEntityClass(StudentDomain.class);
|
||||
jpaExecutor.setPersistMode(PersistMode.PERSIST);
|
||||
jpaExecutor.afterPropertiesSet();
|
||||
|
||||
JpaOutboundGateway jpaOutboundChannelAdapter = new JpaOutboundGateway(jpaExecutor);
|
||||
jpaOutboundChannelAdapter.setProducesReply(false);
|
||||
|
||||
StudentDomain testStudent = JpaTestUtils.getTestStudent();
|
||||
|
||||
Assert.assertNull(testStudent.getRollNumber());
|
||||
|
||||
Message<StudentDomain> message = MessageBuilder.withPayload(testStudent).build();
|
||||
|
||||
jpaOutboundChannelAdapter.afterPropertiesSet();
|
||||
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
// explicitly setting the transaction name is something that can only be done programmatically
|
||||
def.setName("SomeTxName");
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(def);
|
||||
jpaOutboundChannelAdapter.handleMessage(message);
|
||||
transactionManager.commit(status);
|
||||
|
||||
List<?> results2 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results2);
|
||||
Assert.assertTrue(results2.size() == 4);
|
||||
|
||||
Assert.assertNotNull(testStudent.getRollNumber());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa.xsd">
|
||||
|
||||
<import resource="BaseJpaPollingChannelAdapterTests-context.xml"/>
|
||||
|
||||
<int:channel id="input"/>
|
||||
|
||||
<int-jpa:outbound-channel-adapter id="jpaAdapter" channel="input" entity-manager-factory="entityManagerFactory">
|
||||
<int-jpa:transactional transaction-manager="transactionManager"/>
|
||||
</int-jpa:outbound-channel-adapter>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
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.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.jpa.test.JpaTestUtils;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class JpaOutboundChannelAdapterTransactionalTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("input")
|
||||
private MessageChannel channel;
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void saveEntityWithTransaction() throws InterruptedException {
|
||||
|
||||
List<?> results1 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results1);
|
||||
Assert.assertTrue(results1.size() == 3);
|
||||
|
||||
StudentDomain testStudent = JpaTestUtils.getTestStudent();
|
||||
Message<StudentDomain> message = MessageBuilder.withPayload(testStudent).build();
|
||||
|
||||
channel.send(message);
|
||||
|
||||
List<?> results2 = new JdbcTemplate(dataSource).queryForList("Select * from Student");
|
||||
Assert.assertNotNull(results2);
|
||||
Assert.assertTrue(results2.size() == 4);
|
||||
|
||||
Assert.assertNull(testStudent.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
<?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:jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation=
|
||||
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.2.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.2.xsd
|
||||
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<import resource="BaseJpaPollingChannelAdapterTests-context.xml"/>
|
||||
|
||||
<int:poller default="true" fixed-rate="2000"/>
|
||||
|
||||
<int:gateway default-reply-channel="studentReplyChannel"
|
||||
service-interface="org.springframework.integration.jpa.outbound.StudentService" default-reply-timeout="3000">
|
||||
<int:method name="deleteStudent" request-channel="deleteStudentChannel" />
|
||||
<int:method name="getStudent" request-channel="getStudentChannel" />
|
||||
<int:method name="getStudentWithException" request-channel="getStudentEndpointWithExceptionChannel"/>
|
||||
<int:method name="getStudentWithParameters" request-channel="getStudentWithParametersChannel"/>
|
||||
<int:method name="getAllStudents" request-channel="getAllStudentsChannel" />
|
||||
<int:method name="persistStudent" request-channel="persistStudentChannel" />
|
||||
<int:method name="persistStudentUsingMerge" request-channel="persistStudentUsingMergeChannel" />
|
||||
</int:gateway>
|
||||
|
||||
<int:channel id="deleteStudentChannel"/>
|
||||
<int:channel id="getStudentChannel"/>
|
||||
<int:channel id="getStudentWithParametersChannel"/>
|
||||
<int:channel id="getAllStudentsChannel"/>
|
||||
<int:channel id="persistStudentChannel"/>
|
||||
<int:channel id="persistStudentUsingMergeChannel"/>
|
||||
<int:channel id="studentReplyChannel"/>
|
||||
<int:channel id="getStudentEndpointWithExceptionChannel"/>
|
||||
|
||||
<bean id="deleteStudentEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="deleteStudentChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
<property name="persistMode" value="DELETE"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="UPDATING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="getStudentEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="getStudentChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
<property name="jpaQuery" value="from Student s where s.id = :id"/>
|
||||
<property name="expectSingleResult" value="true"/>
|
||||
<property name="jpaParameters" >
|
||||
<util:list>
|
||||
<bean class="org.springframework.integration.jpa.support.JpaParameter">
|
||||
<property name="name" value="id"/>
|
||||
<property name="expression" value="payload"/>
|
||||
</bean>
|
||||
</util:list>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="RETRIEVING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="getStudentEndpointWithException"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="getStudentEndpointWithExceptionChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
<property name="jpaQuery" value="from Student s"/>
|
||||
<property name="expectSingleResult" value="true"/>
|
||||
|
||||
<property name="jpaParameters" >
|
||||
<util:list>
|
||||
<bean class="org.springframework.integration.jpa.support.JpaParameter">
|
||||
<property name="name" value="id"/>
|
||||
<property name="expression" value="payload"/>
|
||||
</bean>
|
||||
</util:list>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="RETRIEVING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="getAllStudentsEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="getAllStudentsChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="RETRIEVING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="persitStudentEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="persistStudentChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="UPDATING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="persitStudentUsingMergeEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="persistStudentUsingMergeChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
<property name="persistMode" value="MERGE"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="UPDATING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="getStudentWithParametersEndpoint"
|
||||
class="org.springframework.integration.endpoint.EventDrivenConsumer">
|
||||
<constructor-arg name="inputChannel" ref="getStudentWithParametersChannel"/>
|
||||
<constructor-arg name="handler">
|
||||
<bean class="org.springframework.integration.jpa.outbound.JpaOutboundGateway">
|
||||
<constructor-arg name="jpaExecutor">
|
||||
<bean class="org.springframework.integration.jpa.core.JpaExecutor">
|
||||
<constructor-arg name="entityManager" ref="entityManager"/>
|
||||
<property name="entityClass" value="org.springframework.integration.jpa.test.entity.StudentDomain"/>
|
||||
<property name="jpaQuery" value="from Student s where s.firstName = ? and s.lastName=?"/>
|
||||
<property name="expectSingleResult" value="true"/>
|
||||
<property name="jpaParameters" >
|
||||
<util:list>
|
||||
<bean class="org.springframework.integration.jpa.support.JpaParameter">
|
||||
<property name="expression" value="payload"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.integration.jpa.support.JpaParameter">
|
||||
<property name="value" value="Last Two"/>
|
||||
</bean>
|
||||
</util:list>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="gatewayType" value="RETRIEVING"/>
|
||||
<property name="outputChannel" ref="studentReplyChannel"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.jpa.test.JpaTestUtils;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.TransactionConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
|
||||
public class JpaOutboundGatewayTests {
|
||||
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void getStudent() {
|
||||
final StudentDomain student = studentService.getStudent(1001L);
|
||||
Assert.assertNotNull(student);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Transactional
|
||||
public void deleteNonExistingStudent() {
|
||||
|
||||
StudentDomain student = JpaTestUtils.getTestStudent();
|
||||
student.setRollNumber(3424234234L);
|
||||
|
||||
try {
|
||||
studentService.deleteStudent(student);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting a MessageHandlingException to be thrown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void getStudentWithException() {
|
||||
try {
|
||||
studentService.getStudentWithException(1001L);
|
||||
} catch (MessageHandlingException e) {
|
||||
Assert.assertEquals("The Jpa operation returned more than 1 result object but expectSingleResult was 'true'.",
|
||||
e.getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail("Was expecting a MessageHandlingException to be thrown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void getStudentStudentWithPositionalParameters() {
|
||||
|
||||
StudentDomain student = studentService.getStudentWithParameters("First Two");
|
||||
|
||||
Assert.assertEquals("First Two", student.getFirstName());
|
||||
Assert.assertEquals("Last Two", student.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void getAllStudents() {
|
||||
|
||||
final List<StudentDomain> students = studentService.getAllStudents();
|
||||
Assert.assertNotNull(students);
|
||||
Assert.assertTrue(students.size() == 3);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Transactional
|
||||
public void persistStudent() {
|
||||
|
||||
final StudentDomain studentToPersist = JpaTestUtils.getTestStudent();
|
||||
Assert.assertNull(studentToPersist.getRollNumber());
|
||||
|
||||
final StudentDomain persistedStudent = studentService.persistStudent(studentToPersist);
|
||||
Assert.assertNotNull(persistedStudent);
|
||||
Assert.assertNotNull(persistedStudent.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Transactional
|
||||
public void persistStudentUsingMerge() {
|
||||
|
||||
final StudentDomain studentToPersist = JpaTestUtils.getTestStudent();
|
||||
Assert.assertNull(studentToPersist.getRollNumber());
|
||||
|
||||
final StudentDomain persistedStudent = studentService.persistStudentUsingMerge(studentToPersist);
|
||||
Assert.assertNotNull(persistedStudent);
|
||||
Assert.assertNotNull(persistedStudent.getRollNumber());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.outbound;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.annotation.Payload;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
|
||||
public interface StudentService {
|
||||
|
||||
StudentDomain getStudent(StudentDomain student);
|
||||
|
||||
StudentDomain getStudentWithException(Long id);
|
||||
|
||||
StudentDomain getStudent(Long id);
|
||||
StudentDomain deleteStudent(StudentDomain student);
|
||||
|
||||
@Payload("new java.util.Date()")
|
||||
List<StudentDomain> getAllStudents();
|
||||
|
||||
StudentDomain persistStudent(StudentDomain student);
|
||||
|
||||
StudentDomain persistStudentUsingMerge(StudentDomain studentToPersist);
|
||||
|
||||
StudentDomain getStudentWithParameters(String firstName);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.support.parametersource;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.jpa.support.JpaParameter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingParameterSourceFactoryTests {
|
||||
|
||||
private ExpressionEvaluatingParameterSourceFactory factory = new ExpressionEvaluatingParameterSourceFactory();
|
||||
|
||||
@Test
|
||||
public void testSetStaticParameters() {
|
||||
factory.setParameters(Collections.singletonList(new JpaParameter("foo", "bar", null)));
|
||||
ParameterSource source = factory.createParameterSource(null);
|
||||
assertTrue(source.hasValue("foo"));
|
||||
assertEquals("bar", source.getValue("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapInput() {
|
||||
ParameterSource source = factory.createParameterSource(Collections.singletonMap("foo", "bar"));
|
||||
assertTrue(source.hasValue("foo"));
|
||||
assertEquals("bar", source.getValue("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListOfMapsInput() {
|
||||
@SuppressWarnings("unchecked")
|
||||
ParameterSource source = factory.createParameterSource(Arrays.asList(Collections.singletonMap("foo", "bar"),
|
||||
Collections.singletonMap("foo", "bucket")));
|
||||
String expression = "foo";
|
||||
assertTrue(source.hasValue(expression));
|
||||
assertEquals("[bar, bucket]", source.getValue(expression).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapInputWithExpression() {
|
||||
ParameterSource source = factory.createParameterSource(Collections.singletonMap("foo", "bar"));
|
||||
// This is an illegal parameter name in Spring JDBC so we'd never get this as input
|
||||
assertTrue(source.hasValue("foo.toUpperCase()"));
|
||||
assertEquals("BAR", source.getValue("foo.toUpperCase()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapInputWithMappedExpression() {
|
||||
factory.setParameters(Collections.singletonList(new JpaParameter("spam", null, "foo.toUpperCase()")));
|
||||
ParameterSource source = factory.createParameterSource(Collections.singletonMap("foo", "bar"));
|
||||
assertTrue(source.hasValue("spam"));
|
||||
assertEquals("BAR", source.getValue("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapInputWithMappedExpressionResolveStatic() {
|
||||
|
||||
List<JpaParameter> parameters = new ArrayList<JpaParameter>();
|
||||
parameters.add(new JpaParameter("spam", null, "#staticParameters['foo'].toUpperCase()"));
|
||||
parameters.add(new JpaParameter("foo", "bar", null));
|
||||
factory.setParameters(parameters);
|
||||
|
||||
ParameterSource source = factory.createParameterSource(Collections.singletonMap("crap", "bucket"));
|
||||
assertTrue(source.hasValue("spam"));
|
||||
assertEquals("BAR", source.getValue("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListOfMapsInputWithExpression() {
|
||||
factory.setParameters(Collections.singletonList(new JpaParameter("spam", null, "foo.toUpperCase()")));
|
||||
@SuppressWarnings("unchecked")
|
||||
ParameterSource source = factory.createParameterSource(Arrays.asList(Collections.singletonMap("foo", "bar"),
|
||||
Collections.singletonMap("foo", "bucket")));
|
||||
String expression = "spam";
|
||||
assertTrue(source.hasValue(expression));
|
||||
assertEquals("[BAR, BUCKET]", source.getValue(expression).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPositionalStaticParameters() {
|
||||
List<JpaParameter> parameters = new ArrayList<JpaParameter>();
|
||||
parameters.add(new JpaParameter("foo", null));
|
||||
parameters.add(new JpaParameter("bar", null));
|
||||
factory.setParameters(parameters);
|
||||
|
||||
PositionSupportingParameterSource source = factory.createParameterSource("not important");
|
||||
|
||||
String position0 = (String) source.getValueByPosition(0);
|
||||
String position1 = (String) source.getValueByPosition(1);
|
||||
|
||||
assertEquals("foo", position0);
|
||||
assertEquals("bar", position1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPositionalExpressionParameters() {
|
||||
List<JpaParameter> parameters = new ArrayList<JpaParameter>();
|
||||
parameters.add(new JpaParameter(null, "#root.toUpperCase()"));
|
||||
parameters.add(new JpaParameter("bar", null));
|
||||
factory.setParameters(parameters);
|
||||
|
||||
PositionSupportingParameterSource source = factory.createParameterSource("very important");
|
||||
|
||||
String position0 = (String) source.getValueByPosition(0);
|
||||
String position1 = (String) source.getValueByPosition(1);
|
||||
|
||||
assertEquals("VERY IMPORTANT", position0);
|
||||
assertEquals("bar", position1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPositionalExpressionParameters2() {
|
||||
List<JpaParameter> parameters = new ArrayList<JpaParameter>();
|
||||
|
||||
parameters.add(new JpaParameter("bar", null));
|
||||
parameters.add(new JpaParameter(null, "#root.toUpperCase()"));
|
||||
|
||||
factory.setParameters(parameters);
|
||||
|
||||
PositionSupportingParameterSource source = factory.createParameterSource("very important");
|
||||
|
||||
String position0 = (String) source.getValueByPosition(0);
|
||||
String position1 = (String) source.getValueByPosition(1);
|
||||
|
||||
assertEquals("VERY IMPORTANT", position1);
|
||||
assertEquals("bar", position0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.integration.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public final class Consumer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(Consumer.class);
|
||||
|
||||
private static final BlockingQueue<Message<Collection<?>>> MESSAGES = new LinkedBlockingQueue<Message<Collection<?>>>();
|
||||
|
||||
public void receive(Message<Collection<?>>message) {
|
||||
logger.info("Service Activator received Message: " + message);
|
||||
MESSAGES.add(message);
|
||||
}
|
||||
|
||||
public Message<Collection<?>> poll(long timeoutInMillis) throws InterruptedException {
|
||||
return MESSAGES.poll(timeoutInMillis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.jpa.test.entity.Gender;
|
||||
import org.springframework.integration.jpa.test.entity.StudentDomain;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public final class JpaTestUtils {
|
||||
|
||||
public static StudentDomain getTestStudent() {
|
||||
|
||||
Calendar dateOfBirth = Calendar.getInstance();
|
||||
dateOfBirth.set(1984, 0, 31);
|
||||
|
||||
StudentDomain student = new StudentDomain()
|
||||
.withFirstName("First Executor")
|
||||
.withLastName("Last Executor")
|
||||
.withGender(Gender.MALE)
|
||||
.withDateOfBirth(dateOfBirth.getTime())
|
||||
.withLastUpdated(new Date());
|
||||
|
||||
return student;
|
||||
}
|
||||
|
||||
public static SourcePollingChannelAdapter getSourcePollingChannelAdapter(MessageSource<?> adapter,
|
||||
MessageChannel channel,
|
||||
PollerMetadata poller,
|
||||
GenericApplicationContext context,
|
||||
ClassLoader beanClassLoader) throws Exception {
|
||||
|
||||
SourcePollingChannelAdapterFactoryBean fb = new SourcePollingChannelAdapterFactoryBean();
|
||||
fb.setSource(adapter);
|
||||
fb.setOutputChannel(channel);
|
||||
fb.setPollerMetadata(poller);
|
||||
fb.setBeanClassLoader(beanClassLoader);
|
||||
fb.setAutoStartup(false);
|
||||
fb.setBeanFactory(context.getBeanFactory());
|
||||
fb.afterPropertiesSet();
|
||||
|
||||
return fb.getObject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class TestTrigger implements Trigger {
|
||||
|
||||
private static final AtomicBoolean hasRun = new AtomicBoolean();
|
||||
|
||||
private final Date executionTime;
|
||||
|
||||
private static volatile CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
|
||||
public TestTrigger() {
|
||||
super();
|
||||
executionTime = new Date();
|
||||
}
|
||||
|
||||
public Date nextExecutionTime(TriggerContext triggerContext) {
|
||||
|
||||
if (TestTrigger.hasRun.getAndSet(true)) {
|
||||
TestTrigger.latch.countDown();
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.executionTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((executionTime == null) ? 0 : executionTime.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TestTrigger other = (TestTrigger) obj;
|
||||
if (executionTime == null) {
|
||||
if (other.executionTime != null)
|
||||
return false;
|
||||
} else if (!executionTime.equals(other.executionTime))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
TestTrigger.latch = new CountDownLatch(1);
|
||||
TestTrigger.hasRun.set(false);
|
||||
}
|
||||
|
||||
public void await() {
|
||||
try {
|
||||
TestTrigger.latch.await(5000, TimeUnit.MILLISECONDS);
|
||||
if (latch.getCount() != 0) {
|
||||
throw new RuntimeException("test latch.await() did not count down");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeException("test latch.await() interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test.entity;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the gender of the person
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
*/
|
||||
public enum Gender {
|
||||
|
||||
MALE("M"),FEMALE("F");
|
||||
|
||||
private String identifier;
|
||||
private static Map<String, Gender> identifierMap;
|
||||
|
||||
private Gender(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
static {
|
||||
EnumSet<Gender> all = EnumSet.allOf(Gender.class);
|
||||
identifierMap = new HashMap<String, Gender>();
|
||||
for(Gender gender:all) {
|
||||
identifierMap.put(gender.getIdentifier(), gender);
|
||||
}
|
||||
}
|
||||
|
||||
public static Gender getGenderFromIdentifier(String identifier) {
|
||||
return identifierMap.get(identifier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedNativeQuery;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
|
||||
/**
|
||||
* The JPA Entity for the Student class
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @author Gunnar Hillert
|
||||
*
|
||||
*/
|
||||
@Entity(name="Student")
|
||||
@Table(name="Student")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="selectStudent", query="select s from Student s where s.lastName = 'Last One'"),
|
||||
@NamedQuery(name="updateStudent", query="update Student s set s.lastName = :lastName, s.lastUpdated = :lastUpdated where s.rollNumber in (select max(a.rollNumber) from Student a)")
|
||||
})
|
||||
@NamedNativeQuery(resultClass=StudentDomain.class, name="updateStudentNativeQuery", query="update Student s set s.lastName = :lastName, lastUpdated = :lastUpdated where s.rollNumber in (select max(a.rollNumber) from Student a)")
|
||||
public class StudentDomain {
|
||||
|
||||
@Id
|
||||
@Column(name="rollNumber")
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
private Long rollNumber;
|
||||
|
||||
@Column(name="firstName")
|
||||
private String firstName;
|
||||
|
||||
@Column(name="lastName")
|
||||
private String lastName;
|
||||
|
||||
@Column(name="gender")
|
||||
private String gender;
|
||||
|
||||
@Column(name="dateOfBirth")
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date dateOfBirth;
|
||||
|
||||
@Column(name="lastUpdated")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastUpdated;
|
||||
|
||||
public Long getRollNumber() {
|
||||
return rollNumber;
|
||||
}
|
||||
|
||||
public void setRollNumber(Long rollNumber) {
|
||||
this.rollNumber = rollNumber;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public Gender getGender() {
|
||||
return Gender.getGenderFromIdentifier(gender);
|
||||
}
|
||||
|
||||
public void setGender(Gender gender) {
|
||||
this.gender = gender.getIdentifier();
|
||||
}
|
||||
|
||||
public Date getDateOfBirth() {
|
||||
return dateOfBirth;
|
||||
}
|
||||
|
||||
public void setDateOfBirth(Date dateOfBirth) {
|
||||
this.dateOfBirth = dateOfBirth;
|
||||
}
|
||||
|
||||
|
||||
public Date getLastUpdated() {
|
||||
return lastUpdated;
|
||||
}
|
||||
|
||||
public void setLastUpdated(Date lastUpdated) {
|
||||
this.lastUpdated = lastUpdated;
|
||||
}
|
||||
|
||||
//Convenience methods for chaining method calls
|
||||
|
||||
public StudentDomain withRollNumber(Long rollNumber) {
|
||||
setRollNumber(rollNumber);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StudentDomain withFirstName(String firstName) {
|
||||
setFirstName(firstName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StudentDomain withLastName(String lastName) {
|
||||
setLastName(lastName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StudentDomain withGender(Gender gender) {
|
||||
setGender(gender);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StudentDomain withDateOfBirth(Date dateOfBirth) {
|
||||
setDateOfBirth(dateOfBirth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StudentDomain withLastUpdated(Date lastUpdated) {
|
||||
setLastUpdated(lastUpdated);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.jpa.test.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
* The Entity for Student read status
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="StudentReadStatus")
|
||||
public class StudentReadStatus {
|
||||
|
||||
@Id
|
||||
@Column(name="rollNumber")
|
||||
private int rollNumber;
|
||||
|
||||
@Column(name="readAt")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date readAt;
|
||||
|
||||
public int getRollNumber() {
|
||||
return rollNumber;
|
||||
}
|
||||
|
||||
public void setRollNumber(int rollNumber) {
|
||||
this.rollNumber = rollNumber;
|
||||
}
|
||||
|
||||
public Date getReadAt() {
|
||||
return readAt;
|
||||
}
|
||||
|
||||
public void setReadAt(Date readAt) {
|
||||
this.readAt = readAt;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
drop table StudentReadStatus;
|
||||
drop table Student;
|
||||
DROP TABLE OPENJPA_SEQUENCE_TABLE;
|
||||
|
||||
CREATE TABLE OPENJPA_SEQUENCE_TABLE (ID TINYINT NOT NULL, SEQUENCE_VALUE BIGINT, PRIMARY KEY (ID));
|
||||
CREATE TABLE Student (rollNumber BIGINT generated by default as identity, dateOfBirth DATE, firstName VARCHAR(255), gender VARCHAR(255), lastName VARCHAR(255), lastUpdated TIMESTAMP, PRIMARY KEY (rollNumber));
|
||||
CREATE TABLE StudentReadStatus (rollNumber INTEGER NOT NULL, readAt TIMESTAMP, PRIMARY KEY (rollNumber));
|
||||
@@ -0,0 +1,2 @@
|
||||
drop table StudentReadStatus;
|
||||
drop table Student;
|
||||
@@ -0,0 +1,6 @@
|
||||
insert into Student(rollNumber, firstName,lastName, gender, dateOfBirth,lastUpdated)
|
||||
values ('1001', 'First One','Last One','M','1980-1-1',NOW());
|
||||
insert into Student(rollNumber, firstName,lastName, gender, dateOfBirth,lastUpdated)
|
||||
values ('1002', 'First Two','Last Two','F','1984-1-1',NOW());
|
||||
insert into Student(rollNumber, firstName,lastName, gender, dateOfBirth,lastUpdated)
|
||||
values ('1003', 'First Three','Last Three','F','1984-3-3',NOW());
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
|
||||
<class>org.springframework.integration.jpa.test.entity.StudentDomain</class>
|
||||
<class>org.springframework.integration.jpa.test.entity.StudentReadStatus</class>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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:jpa="http://www.springframework.org/schema/integration/jpa"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/jpa http://www.springframework.org/schema/integration/jpa/spring-integration-jpa-2.1.xsd">
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="H2"/>
|
||||
|
||||
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS" >
|
||||
<jdbc:script location="classpath:H2-DropTables.sql" />
|
||||
<jdbc:script location="classpath:H2-CreateTables.sql" />
|
||||
<jdbc:script location="classpath:H2-PopulateData.sql" />
|
||||
</jdbc:initialize-database>
|
||||
|
||||
<tx:annotation-driven transaction-manager="transactionManager"/>
|
||||
<!-- <context:load-time-weaver />
|
||||
-->
|
||||
<bean id="entityManagerFactory"
|
||||
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="persistenceUnitName" value="persistenceUnit" />
|
||||
<property name="jpaVendorAdapter" ref="vendorAdaptor" />
|
||||
<!-- <property name="jpaProperties" ref="jpaProperties" /> -->
|
||||
</bean>
|
||||
|
||||
<bean id="abstractVendorAdaptor" abstract="true">
|
||||
<property name="generateDdl" value="true" />
|
||||
<property name="database" value="HSQL" />
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
</bean>
|
||||
|
||||
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<import resource="classpath:/commonJpa-context.xml" />
|
||||
|
||||
<bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
|
||||
parent="abstractVendorAdaptor">
|
||||
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect"/>
|
||||
<property name="showSql" value="true"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,8 @@
|
||||
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 %p [%c] - <%m>%n
|
||||
|
||||
log4j.category.org.springframework.integration=WARN
|
||||
log4j.category.org.springframework.integration.jpa=INFO
|
||||
@@ -140,6 +140,7 @@
|
||||
<xi:include href="./http.xml"/>
|
||||
<xi:include href="./ip.xml"/>
|
||||
<xi:include href="./jdbc.xml"/>
|
||||
<xi:include href="./jpa.xml"/>
|
||||
<xi:include href="./jms.xml"/>
|
||||
<xi:include href="./mail.xml"/>
|
||||
<xi:include href="./mongodb.xml"/>
|
||||
|
||||
1074
src/reference/docbook/jpa.xml
Normal file
1074
src/reference/docbook/jpa.xml
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user