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:
Amol Nayak
2012-02-16 22:27:00 +05:30
committed by Oleg Zhurakousky
parent 6c2f3d8dd0
commit 16f48a12e6
82 changed files with 7762 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int="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>

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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());
}
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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());
}
}

View File

@@ -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>

View File

@@ -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());
}
}

View File

@@ -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>

View File

@@ -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());
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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");
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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));

View File

@@ -0,0 +1,2 @@
drop table StudentReadStatus;
drop table Student;

View File

@@ -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());

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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