/* * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * 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; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.messaging.Message; /** * @author Jonas Partner * @author Gary Russell */ public class JdbcPollingChannelAdapterIntegrationTests { private static Log logger = LogFactory.getLog(JdbcPollingChannelAdapterIntegrationTests.class); private EmbeddedDatabase embeddedDatabase; private JdbcTemplate jdbcTemplate; @Before public void setUp() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); builder .setType(EmbeddedDatabaseType.DERBY) .addScript( "classpath:org/springframework/integration/jdbc/pollingChannelAdapterIntegrationTest.sql"); this.embeddedDatabase = builder.build(); this.jdbcTemplate = new JdbcTemplate(this.embeddedDatabase); } @After public void tearDown() { this.embeddedDatabase.shutdown(); } @Test public void testSimplePollForListOfMapsNoUpdate() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item"); this.jdbcTemplate.update("insert into item values(1,2)"); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); assertTrue("Wrong payload type", payload instanceof List<?>); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 1, rows.size()); assertTrue("Returned row not a map", rows.get(0) instanceof Map<?, ?>); Map<?, ?> row = (Map<?, ?>) rows.get(0); assertEquals("Wrong id", 1, row.get("id")); assertEquals("Wrong status", 2, row.get("status")); } @Test public void testParameterizedPollForListOfMapsNoUpdate() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item where status=:status"); adapter.setSelectSqlParameterSource(new SqlParameterSource() { @Override public boolean hasValue(String name) { return "status".equals(name); } @Override public Object getValue(String name) throws IllegalArgumentException { return 2; } @Override public String getTypeName(String name) { return null; } @Override public int getSqlType(String name) { return Types.INTEGER; } }); this.jdbcTemplate.update("insert into item values(1,2)"); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); assertTrue("Wrong payload type", payload instanceof List<?>); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 1, rows.size()); assertTrue("Returned row not a map", rows.get(0) instanceof Map<?, ?>); Map<?, ?> row = (Map<?, ?>) rows.get(0); assertEquals("Wrong id", 1, row.get("id")); assertEquals("Wrong status", 2, row.get("status")); } @Test public void testSimplePollForListWithRowMapperNoUpdate() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item"); adapter.setRowMapper(new ItemRowMapper()); this.jdbcTemplate.update("insert into item values(1,2)"); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 1, rows.size()); assertTrue("Wrong payload type", rows.get(0) instanceof Item); Item item = (Item) rows.get(0); assertEquals("Wrong id", 1, item.getId()); assertEquals("Wrong status", 2, item.getStatus()); } @Test public void testSimplePollForListWithRowMapperAndOneUpdate() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item where status=2"); adapter .setUpdateSql("update item set status = 10 where id in (:id)"); adapter.setRowMapper(new ItemRowMapper()); adapter.setBeanFactory(mock(BeanFactory.class)); adapter.afterPropertiesSet(); this.jdbcTemplate.update("insert into item values(1,2)"); this.jdbcTemplate.update("insert into item values(2,2)"); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 2, rows.size()); assertTrue("Wrong payload type", rows.get(0) instanceof Item); Item item = (Item) rows.get(0); assertEquals("Wrong id", 1, item.getId()); assertEquals("Wrong status", 2, item.getStatus()); int countOfStatusTwo = this.jdbcTemplate .queryForObject("select count(*) from item where status = 2", Integer.class); assertEquals( "Status not updated incorect number of rows with status 2", 0, countOfStatusTwo); int countOfStatusTen = this.jdbcTemplate .queryForObject("select count(*) from item where status = 10", Integer.class); assertEquals( "Status not updated incorect number of rows with status 10", 2, countOfStatusTen); } @Test public void testSimplePollForListWithRowMapperAndUpdatePerRow() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item where status=2"); adapter.setUpdateSql("update item set status = 10 where id = :id"); adapter.setUpdatePerRow(true); adapter.setRowMapper(new ItemRowMapper()); adapter.setBeanFactory(mock(BeanFactory.class)); adapter.afterPropertiesSet(); this.jdbcTemplate.update("insert into item values(1,2)"); this.jdbcTemplate.update("insert into item values(2,2)"); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 2, rows.size()); assertTrue("Wrong payload type", rows.get(0) instanceof Item); Item item = (Item) rows.get(0); assertEquals("Wrong id", 1, item.getId()); assertEquals("Wrong status", 2, item.getStatus()); int countOfStatusTwo = this.jdbcTemplate .queryForObject("select count(*) from item where status = 2", Integer.class); assertEquals( "Status not updated incorect number of rows with status 2", 0, countOfStatusTwo); int countOfStatusTen = this.jdbcTemplate .queryForObject("select count(*) from item where status = 10", Integer.class); assertEquals( "Status not updated incorect number of rows with status 10", 2, countOfStatusTen); } @Test public void testSimplePollForListWithRowMapperAndInsertPerRowAndMaxRows() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item where id not in (select id from copy)"); adapter.setUpdateSql("insert into copy values(:id,10)"); adapter.setUpdatePerRow(true); adapter.setMaxRowsPerPoll(1); adapter.setRowMapper(new ItemRowMapper()); adapter.setBeanFactory(mock(BeanFactory.class)); adapter.afterPropertiesSet(); this.jdbcTemplate.update("insert into item values(1,2)"); this.jdbcTemplate.update("insert into item values(2,2)"); logger.debug(adapter.receive()); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 1, rows.size()); assertTrue("Wrong payload type", rows.get(0) instanceof Item); Item item = (Item) rows.get(0); logger.debug(item); assertEquals("Wrong id", 2, item.getId()); assertEquals("Wrong status", 2, item.getStatus()); int countOfStatusTwo = this.jdbcTemplate .queryForObject("select count(*) from item where status = 2", Integer.class); assertEquals( "Status not updated incorect number of rows with status 2", 2, countOfStatusTwo); int countOfStatusTen = this.jdbcTemplate .queryForObject("select count(*) from copy where status = 10", Integer.class); assertEquals( "Status not updated incorect number of rows with status 10", 2, countOfStatusTen); } @Test public void testSimplePollForListWithRowMapperAndUpdatePerRowWithMaxRows() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item where status=2"); adapter.setUpdateSql("update item set status = 10 where id = :id"); adapter.setUpdatePerRow(true); adapter.setMaxRowsPerPoll(1); adapter.setRowMapper(new ItemRowMapper()); adapter.setBeanFactory(mock(BeanFactory.class)); adapter.afterPropertiesSet(); this.jdbcTemplate.update("insert into item values(1,2)"); this.jdbcTemplate.update("insert into item values(2,2)"); adapter.receive(); Message<Object> message = adapter.receive(); Object payload = message.getPayload(); List<?> rows = (List<?>) payload; assertEquals("Wrong number of elements", 1, rows.size()); assertTrue("Wrong payload type", rows.get(0) instanceof Item); Item item = (Item) rows.get(0); assertEquals("Wrong id", 2, item.getId()); assertEquals("Wrong status", 2, item.getStatus()); int countOfStatusTwo = this.jdbcTemplate .queryForObject("select count(*) from item where status = 2", Integer.class); assertEquals( "Status not updated incorect number of rows with status 2", 0, countOfStatusTwo); int countOfStatusTen = this.jdbcTemplate .queryForObject("select count(*) from item where status = 10", Integer.class); assertEquals( "Status not updated incorect number of rows with status 10", 2, countOfStatusTen); } @Test public void testEmptyPoll() { JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter( this.embeddedDatabase, "select * from item"); Message<Object> message = adapter.receive(); assertNull("Message received when no rows in table", message); } private static class Item { private int id; private int status; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } @Override public String toString() { return "Item [id=" + id + ", status=" + status + "]"; } } private static class ItemRowMapper implements RowMapper<Item> { @Override public Item mapRow(ResultSet rs, int rowNum) throws SQLException { Item item = new Item(); item.setId(rs.getInt(1)); item.setStatus(rs.getInt(2)); return item; } } }