/*
* 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.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jdbc.JdbcOutboundGateway;
import org.springframework.integration.jdbc.MessagePreparedStatementSetter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
/**
* @author Dave Syer
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
* @author Gunnar Hillert
* @since 2.0
*
*/
public class JdbcOutboundGatewayParserTests {
private JdbcTemplate jdbcTemplate;
private MessageChannel channel;
private ConfigurableApplicationContext context;
private MessagingTemplate messagingTemplate;
private static volatile int adviceCalled;
@Test
public void testMapPayloadMapReply() {
setUp("handlingMapPayloadJdbcOutboundGatewayTest.xml", getClass());
assertTrue(this.context.containsBean("jdbcGateway"));
Message<?> message = MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build();
this.channel.send(message);
Message<?> reply = this.messagingTemplate.receive();
assertNotNull(reply);
@SuppressWarnings("unchecked")
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
assertEquals("bar", payload.get("name"));
Map<String, Object> map = this.jdbcTemplate.queryForMap("SELECT * from FOOS");
assertEquals("Wrong id", message.getHeaders().getId().toString(), map.get("ID"));
assertEquals("Wrong name", "bar", map.get("name"));
JdbcOutboundGateway gateway = context.getBean("jdbcGateway.handler", JdbcOutboundGateway.class);
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
Assert.assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertEquals(1, adviceCalled);
}
@Test
@SuppressWarnings("unchecked")
public void testKeyGeneration() {
setUp("handlingKeyGenerationJdbcOutboundGatewayTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build();
this.channel.send(message);
Message<?> reply = this.messagingTemplate.receive();
assertNotNull(reply);
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
Object id = payload.get("SCOPE_IDENTITY()");
assertNotNull(id);
Map<String, Object> map = this.jdbcTemplate.queryForMap("SELECT * from BARS");
assertEquals("Wrong id", id, map.get("ID"));
assertEquals("Wrong name", "bar", map.get("name"));
this.jdbcTemplate.execute("DELETE FROM BARS");
MessageChannel setterRequest = this.context.getBean("setterRequest", MessageChannel.class);
setterRequest.send(new GenericMessage<String>("bar2"));
reply = this.messagingTemplate.receive();
assertNotNull(reply);
payload = (Map<String, ?>) reply.getPayload();
id = payload.get("SCOPE_IDENTITY()");
assertNotNull(id);
map = this.jdbcTemplate.queryForMap("SELECT * from BARS");
assertEquals("Wrong id", id, map.get("ID"));
assertEquals("Wrong name", "bar2", map.get("name"));
}
@Test
public void testCountUpdates() {
setUp("handlingCountUpdatesJdbcOutboundGatewayTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build();
this.channel.send(message);
Message<?> reply = this.messagingTemplate.receive();
assertNotNull(reply);
@SuppressWarnings("unchecked")
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
assertEquals(1, payload.get("updated"));
}
@Test
public void testWithPoller() throws Exception {
setUp("JdbcOutboundGatewayWithPollerTest-context.xml", this.getClass());
Message<?> message = MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build();
this.channel.send(message);
Message<?> reply = this.messagingTemplate.receive();
assertNotNull(reply);
@SuppressWarnings("unchecked")
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
assertEquals("bar", payload.get("name"));
Map<String, Object> map = this.jdbcTemplate.queryForMap("SELECT * from BAZZ");
assertEquals("Wrong id", message.getHeaders().getId().toString(), map.get("ID"));
assertEquals("Wrong name", "bar", map.get("name"));
}
@Test
public void testWithSelectQueryOnly() throws Exception {
setUp("JdbcOutboundGatewayWithSelectTest-context.xml", getClass());
Message<?> message = MessageBuilder.withPayload(100).build();
this.channel.send(message);
@SuppressWarnings("unchecked")
Message<Map<String, Object>> reply = (Message<Map<String, Object>>) this.messagingTemplate.receive();
String id = (String) reply.getPayload().get("id");
Integer status = (Integer) reply.getPayload().get("status");
String name = (String) reply.getPayload().get("name");
assertEquals("100", id);
assertEquals(Integer.valueOf(3), status);
assertEquals("Cartman", name);
}
@Test
public void testReplyTimeoutIsSet() {
setUp("JdbcOutboundGatewayWithPollerTest-context.xml", getClass());
PollingConsumer outboundGateway = this.context.getBean("jdbcOutboundGateway", PollingConsumer.class);
DirectFieldAccessor accessor = new DirectFieldAccessor(outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("messagingTemplate");
MessagingTemplate messagingTemplate = (MessagingTemplate) source;
accessor = new DirectFieldAccessor(messagingTemplate);
Long sendTimeout = (Long) accessor.getPropertyValue("sendTimeout");
assertEquals("Wrong sendTimeout", Long.valueOf(444L), sendTimeout);
}
@Test
public void testDefaultMaxMessagesPerPollIsSet() {
setUp("JdbcOutboundGatewayWithPollerTest-context.xml", this.getClass());
PollingConsumer pollingConsumer = this.context.getBean(PollingConsumer.class);
DirectFieldAccessor accessor = new DirectFieldAccessor(pollingConsumer);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("poller"); //JdbcPollingChannelAdapter
accessor = new DirectFieldAccessor(source);
Integer maxRowsPerPoll = (Integer) accessor.getPropertyValue("maxRowsPerPoll");
assertEquals("maxRowsPerPoll should default to 1", Integer.valueOf(1), maxRowsPerPoll);
}
@Test
public void testMaxMessagesPerPollIsSet() {
setUp("JdbcOutboundGatewayWithPoller2Test-context.xml", this.getClass());
PollingConsumer pollingConsumer = this.context.getBean(PollingConsumer.class);
DirectFieldAccessor accessor = new DirectFieldAccessor(pollingConsumer);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
source = accessor.getPropertyValue("poller"); //JdbcPollingChannelAdapter
accessor = new DirectFieldAccessor(source);
Integer maxRowsPerPoll = (Integer) accessor.getPropertyValue("maxRowsPerPoll");
assertEquals("maxRowsPerPoll should default to 10", Integer.valueOf(10), maxRowsPerPoll);
}
@Test //INT-1029
public void testOutboundGatewayInsideChain() {
setUp("handlingMapPayloadJdbcOutboundGatewayTest.xml", getClass());
String beanName = "org.springframework.integration.handler.MessageHandlerChain#" +
"0$child.jdbc-outbound-gateway-within-chain.handler";
JdbcOutboundGateway jdbcMessageHandler = this.context.getBean(beanName, JdbcOutboundGateway.class);
MessageChannel channel = this.context.getBean("jdbcOutboundGatewayInsideChain", MessageChannel.class);
assertFalse(TestUtils.getPropertyValue(jdbcMessageHandler, "requiresReply", Boolean.class));
channel.send(MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build());
PollableChannel outbound = this.context.getBean("replyChannel", PollableChannel.class);
Message<?> reply = outbound.receive(10000);
assertNotNull(reply);
@SuppressWarnings("unchecked")
Map<String, ?> payload = (Map<String, ?>) reply.getPayload();
assertEquals("bar", payload.get("name"));
}
@After
public void tearDown() {
if (this.context != null) {
this.context.close();
}
}
protected void setupMessagingTemplate() {
PollableChannel pollableChannel = this.context.getBean("output", PollableChannel.class);
this.messagingTemplate = new MessagingTemplate();
this.messagingTemplate.setDefaultDestination(pollableChannel);
this.messagingTemplate.setReceiveTimeout(10000);
}
public void setUp(String name, Class<?> cls) {
this.context = new ClassPathXmlApplicationContext(name, cls);
this.jdbcTemplate = new JdbcTemplate(this.context.getBean("dataSource", DataSource.class));
this.channel = this.context.getBean("target", MessageChannel.class);
setupMessagingTemplate();
}
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
adviceCalled++;
return callback.execute();
}
}
public static class TestMessagePreparedStatementSetter implements MessagePreparedStatementSetter {
@Override
public void setValues(PreparedStatement ps, Message<?> requestMessage) throws SQLException {
ps.setObject(1, requestMessage.getPayload());
}
}
}