/*
* Copyright 2002-2016 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 java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.jpa.support.JpaParameter;
import org.springframework.integration.jpa.support.parametersource.ExpressionEvaluatingParameterSourceFactory;
import org.springframework.integration.jpa.test.entity.StudentDomain;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* @author Gunnar Hillert
* @author Amol Nayak
* @author Gary Russell
* @author Artem Bilan
* @since 2.2
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class JpaExecutorTests {
@Autowired
protected EntityManager entityManager;
@Autowired
private BeanFactory beanFactory;
/**
* 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));
jpaExecutor.afterPropertiesSet();
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 testInstantiateJpaExecutorWithNullJpaOperations() {
JpaOperations jpaOperations = null;
try {
new JpaExecutor(jpaOperations);
}
catch (IllegalArgumentException e) {
Assert.assertEquals("jpaOperations must not be null.", e.getMessage());
}
}
@Test
public void testSetMultipleQueryTypes() {
JpaExecutor executor = new JpaExecutor(mock(EntityManager.class));
executor.setJpaQuery("select s from Student s");
Assert.assertNotNull(TestUtils.getPropertyValue(executor, "jpaQuery", String.class));
try {
executor.setNamedQuery("NamedQuery");
}
catch (IllegalArgumentException e) {
Assert.assertEquals("You can define only one of the "
+ "properties 'jpaQuery', 'nativeQuery', 'namedQuery'", e.getMessage());
}
Assert.assertNull(TestUtils.getPropertyValue(executor, "namedQuery"));
try {
executor.setNativeQuery("select * from Student");
}
catch (IllegalArgumentException e) {
Assert.assertEquals("You can define only one of the "
+ "properties 'jpaQuery', 'nativeQuery', 'namedQuery'", e.getMessage());
}
Assert.assertNull(TestUtils.getPropertyValue(executor, "nativeQuery"));
executor = new JpaExecutor(mock(EntityManager.class));
executor.setNamedQuery("NamedQuery");
Assert.assertNotNull(TestUtils.getPropertyValue(executor, "namedQuery", String.class));
try {
executor.setJpaQuery("select s from Student s");
}
catch (IllegalArgumentException e) {
Assert.assertEquals("You can define only one of the "
+ "properties 'jpaQuery', 'nativeQuery', 'namedQuery'", e.getMessage());
}
Assert.assertNull(TestUtils.getPropertyValue(executor, "jpaQuery"));
}
@Test
@Transactional
public void selectWithMessageAsParameterSource() {
String query = "select s from Student s where s.firstName = :firstName";
Message<Map<String, String>> message =
MessageBuilder.withPayload(Collections.singletonMap("firstName", "First One")).build();
JpaExecutor executor = getJpaExecutorForMessageAsParamSource(query);
StudentDomain student = (StudentDomain) executor.poll(message);
Assert.assertNotNull(student);
}
@Test
@Transactional
public void selectWithPayloadAsParameterSource() {
String query = "select s from Student s where s.firstName = :firstName";
Message<String> message =
MessageBuilder.withPayload("First One").build();
JpaExecutor executor = getJpaExecutorForPayloadAsParamSource(query);
StudentDomain student = (StudentDomain) executor.poll(message);
Assert.assertNotNull(student);
}
@Test
@Transactional
public void updateWithMessageAsParameterSource() {
String query = "update Student s set s.firstName = :firstName where s.lastName = 'Last One'";
Message<Map<String, String>> message =
MessageBuilder.withPayload(Collections.singletonMap("firstName", "First One")).build();
JpaExecutor executor = getJpaExecutorForMessageAsParamSource(query);
Integer rowsAffected = (Integer) executor.executeOutboundJpaOperation(message);
Assert.assertTrue(1 == rowsAffected);
}
@Test
@Transactional
public void updateWithPayloadAsParameterSource() {
String query = "update Student s set s.firstName = :firstName where s.lastName = 'Last One'";
Message<String> message =
MessageBuilder.withPayload("First One").build();
JpaExecutor executor = getJpaExecutorForPayloadAsParamSource(query);
Integer rowsAffected = (Integer) executor.executeOutboundJpaOperation(message);
Assert.assertTrue(1 == rowsAffected);
}
private JpaExecutor getJpaExecutorForMessageAsParamSource(String query) {
JpaExecutor executor = new JpaExecutor(entityManager);
ExpressionEvaluatingParameterSourceFactory factory =
new ExpressionEvaluatingParameterSourceFactory(mock(BeanFactory.class));
factory.setParameters(
Collections.singletonList(new JpaParameter("firstName", null, "payload['firstName']")));
executor.setParameterSourceFactory(factory);
executor.setJpaQuery(query);
executor.setExpectSingleResult(true);
executor.setUsePayloadAsParameterSource(false);
executor.afterPropertiesSet();
return executor;
}
private JpaExecutor getJpaExecutorForPayloadAsParamSource(String query) {
JpaExecutor executor = new JpaExecutor(entityManager);
ExpressionEvaluatingParameterSourceFactory factory =
new ExpressionEvaluatingParameterSourceFactory(mock(BeanFactory.class));
factory.setParameters(
Collections.singletonList(new JpaParameter("firstName", null, "#this")));
executor.setParameterSourceFactory(factory);
executor.setJpaQuery(query);
executor.setExpectSingleResult(true);
executor.setUsePayloadAsParameterSource(true);
executor.afterPropertiesSet();
return executor;
}
@Test
public void testResultStartingFromThirdRecordForJPAQuery() throws Exception {
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
jpaExecutor.setJpaQuery("select s from Student s");
jpaExecutor.setFirstResultExpression(new LiteralExpression("2"));
jpaExecutor.setBeanFactory(this.beanFactory);
jpaExecutor.afterPropertiesSet();
List<?> results = (List<?>) jpaExecutor.poll(MessageBuilder.withPayload("").build());
Assert.assertNotNull(results);
Assert.assertEquals(1, results.size());
}
@Test
public void testResultStartingFromThirdRecordForNativeQuery() throws Exception {
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
jpaExecutor.setNativeQuery("select * from Student s");
jpaExecutor.setFirstResultExpression(new LiteralExpression("2"));
jpaExecutor.setBeanFactory(this.beanFactory);
jpaExecutor.afterPropertiesSet();
List<?> results = (List<?>) jpaExecutor.poll(MessageBuilder.withPayload("").build());
Assert.assertNotNull(results);
Assert.assertEquals(1, results.size());
}
@Test
public void testResultStartingFromThirdRecordForNamedQuery() throws Exception {
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
jpaExecutor.setNamedQuery("selectAllStudents");
jpaExecutor.setFirstResultExpression(new LiteralExpression("2"));
jpaExecutor.setBeanFactory(this.beanFactory);
jpaExecutor.afterPropertiesSet();
List<?> results = (List<?>) jpaExecutor.poll(MessageBuilder.withPayload("").build());
Assert.assertNotNull(results);
Assert.assertEquals(1, results.size());
}
@Test
public void testResultStartingFromThirdRecordUsingEntity() throws Exception {
final JpaExecutor jpaExecutor = new JpaExecutor(entityManager);
jpaExecutor.setEntityClass(StudentDomain.class);
jpaExecutor.setFirstResultExpression(new LiteralExpression("2"));
jpaExecutor.setBeanFactory(this.beanFactory);
jpaExecutor.afterPropertiesSet();
List<?> results = (List<?>) jpaExecutor.poll(MessageBuilder.withPayload("").build());
Assert.assertNotNull(results);
Assert.assertEquals(1, results.size());
}
@Test
public void withNullMaxResultsExpression() {
final JpaExecutor jpaExecutor = new JpaExecutor(mock(EntityManager.class));
try {
jpaExecutor.setMaxResultsExpression(null);
}
catch (Exception e) {
Assert.assertEquals("maxResultsExpression cannot be null", e.getMessage());
return;
}
Assert.fail("Expected the test case to throw an exception");
}
}