package camelinaction; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.sql.DataSource; import org.apache.camel.builder.AdviceWithRouteBuilder; import org.apache.camel.builder.NotifyBuilder; import org.apache.camel.test.spring.CamelSpringTestSupport; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; public class SpringPropagationTest extends CamelSpringTestSupport { private JdbcTemplate jdbc; @Before public void setupDatabase() throws Exception { DataSource ds = context.getRegistry().lookupByNameAndType("myDataSource", DataSource.class); jdbc = new JdbcTemplate(ds); jdbc.execute("create table bookorders " + "( order_id varchar(10), order_book varchar(50) )"); jdbc.execute("create table bookaudit " + "( order_id varchar(10), order_book varchar(50), order_redelivery varchar(5) )"); } @After public void dropDatabase() throws Exception { jdbc.execute("drop table bookorders"); jdbc.execute("drop table bookaudit"); } @Override protected AbstractApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("SpringPropagationTest.xml"); } @Override public boolean isUseAdviceWith() { return true; } @Test public void testWithCamel() throws Exception { // we should have 1 original message NotifyBuilder notify = new NotifyBuilder(context).whenDone(1).create(); context.start(); // there should be 0 row in the database when we start assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookorders", Long.class)); assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookaudit", Long.class)); template.sendBody("activemq:queue:inbox", "Camel in Action"); String reply = consumer.receiveBody("activemq:queue:order", 10000, String.class); assertEquals("Camel in Action", reply); // wait for the route to complete assertTrue(notify.matches(10, TimeUnit.SECONDS)); // the database need a little sleep time before commits are visible Thread.sleep(1000); // there should be 1 row in the database with the order assertEquals(Long.valueOf(1), jdbc.queryForObject("select count(*) from bookorders", Long.class)); assertEquals(Long.valueOf(1), jdbc.queryForObject("select count(*) from bookaudit", Long.class)); // print the SQL log.info("The following orders was recorded in the orders ..."); List<Map<String, Object>> rows = jdbc.queryForList("select * from bookorders"); for (Map<String, Object> row : rows) { log.info("Book order[id={}, book={}]", row.get("order_id"), row.get("order_book")); } log.info("The following orders was recorded in the audit-log ..."); rows = jdbc.queryForList("select * from bookaudit"); for (Map<String, Object> row : rows) { log.info("Book audit-log[id={}, book={}, redelivery={}]", row.get("order_id"), row.get("order_book"), row.get("order_redelivery")); } } @Test public void testWithDonkey() throws Exception { // we should have 1 original message + 6 redelivery attempts NotifyBuilder notify = new NotifyBuilder(context).whenDone(1).create(); context.start(); // there should be 0 row in the database when we start assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookorders", Long.class)); template.sendBody("activemq:queue:inbox", "Donkey in Action"); String reply = consumer.receiveBody("activemq:queue:order", 10000, String.class); assertNull("There should be no reply", reply); reply = consumer.receiveBody("activemq:queue:ActiveMQ.DLQ", 10000, String.class); assertNotNull("It should have been moved to DLQ", reply); // wait for the route to complete assertTrue(notify.matches(10, TimeUnit.SECONDS)); // the database need a little sleep time before commits are visible Thread.sleep(1000); // there should be 0 row in the database with the order assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookorders", Long.class)); // there should be 1 + 6 redelivery attempt row in the database with the audit-log assertEquals(Long.valueOf(1), jdbc.queryForObject("select count(*) from bookaudit where order_redelivery = 'false'", Long.class)); assertEquals(Long.valueOf(6), jdbc.queryForObject("select count(*) from bookaudit where order_redelivery = 'true'", Long.class)); // print the SQL log.info("The following orders was recorded in the orders ..."); List<Map<String, Object>> rows = jdbc.queryForList("select * from bookorders"); for (Map<String, Object> row : rows) { log.info("Book order[id={}, book={}]", row.get("order_id"), row.get("order_book")); } log.info("The following orders was recorded in the audit-log ..."); rows = jdbc.queryForList("select * from bookaudit"); for (Map<String, Object> row : rows) { log.info("Book audit-log[id={}, book={}, redelivery={}]", row.get("order_id"), row.get("order_book"), row.get("order_redelivery")); } } @Test public void testAuditLogFail() throws Exception { // we should have 1 original message + 6 redelivery attempts NotifyBuilder notify = new NotifyBuilder(context).whenDone(1 + 6).create(); // simulate the audit-log will fail context.getRouteDefinition("audit").adviceWith(context, new AdviceWithRouteBuilder() { @Override public void configure() throws Exception { // simulate error connecting to database interceptSendToEndpoint("bean:auditLogService").skipSendToOriginalEndpoint() .throwException(new IOException("Cannot connect to database")); } }); context.start(); // there should be 0 row in the database when we start assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookorders", Long.class)); assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookaudit", Long.class)); template.sendBody("activemq:queue:inbox", "Camel in Action"); // wait for the route to complete assertTrue(notify.matches(10, TimeUnit.SECONDS)); // there should be 0 row in the database with the order assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookorders", Long.class)); assertEquals(Long.valueOf(0), jdbc.queryForObject("select count(*) from bookaudit", Long.class)); // and the message is in the DLQ String reply = consumer.receiveBody("activemq:queue:ActiveMQ.DLQ", 10000, String.class); assertNotNull("It should have been moved to DLQ", reply); // print the SQL log.info("The following orders was recorded in the orders ..."); List<Map<String, Object>> rows = jdbc.queryForList("select * from bookorders"); for (Map<String, Object> row : rows) { log.info("Book order[id={}, book={}]", row.get("order_id"), row.get("order_book")); } log.info("The following orders was recorded in the audit-log ..."); rows = jdbc.queryForList("select * from bookaudit"); for (Map<String, Object> row : rows) { log.info("Book audit-log[id={}, book={}, redelivery={}]", row.get("order_id"), row.get("order_book"), row.get("order_redelivery")); } } }