package org.javaee7.jms.batch; import org.javaee7.util.BatchTestHelper; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.InSequence; import org.jboss.shrinkwrap.api.ArchivePaths; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; import javax.annotation.Resource; import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.JobExecution; import javax.ejb.EJB; import javax.jms.*; import java.util.Properties; import java.util.Random; import static org.junit.Assert.*; /** * This test demonstrates programmatical creation of durable consumer, and reading * its subscribed messages in a batch job in form of an +ItemReader+. * * include::JmsItemReader[] * * The items are then fed into the writer, that performs the aggregation and stores * the result into a +@Singleton+ EJB. * * include::SummingItemWriter[] * * @author Patrik Dudits */ @RunWith(Arquillian.class) public class JmsItemReaderTest { /** * Upon deployment a topic and connection factory for durable subscription are created: * * include::Resources[] * * Then the subscription itself is created by means of +@Singleton+ +@Startup+ EJB * +SubscriptionCreator+. * * include::SubscriptionCreator#createSubscription[] * * The job itself computes sum and count of random numbers that are send on the topic. * Note that at time of sending there is no active consumer listening on the topic. */ @Deployment public static WebArchive deployment() { return ShrinkWrap.create(WebArchive.class) .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")) .addClass(BatchTestHelper.class) .addPackage(JmsItemReader.class.getPackage()) .addAsResource("META-INF/batch-jobs/jms-job.xml"); } @Resource(lookup = "java:comp/DefaultJMSConnectionFactory") ConnectionFactory factory; @Resource(lookup = Resources.TOPIC) Topic topic; @EJB ResultCollector collector; /** * In this test case we verify that the subscription is really created upon deployment * and thus messages are waiting for the job even before the first run of it. * * The subscription is not deleted even after the application is undeployed, because * the physical topic and its subscription in the message broker still exist, * even after the application scoped managed objects are deleted. * * Following method is used to generate the payload: * * include::JmsItemReaderTest#sendMessages[] * * So we send 10 random numbers, and verify that summing integers works exactly the * same way on both ends. Or that the job really picked up all the numbers submitted * for the computation. */ @InSequence(1) @Test public void worksAfterDeployment() throws InterruptedException { int sum = sendMessages(10); runJob(); assertEquals(10, collector.getLastItemCount()); assertEquals(sum, collector.getLastSum()); assertEquals(1, collector.getNumberOfJobs()); } /** * To verify that the durable subscription really collects messages we do few * more runs. */ @InSequence(2) @Test public void worksInMultipleRuns() throws InterruptedException { int sum = sendMessages(14); runJob(); assertEquals(14, collector.getLastItemCount()); assertEquals(sum, collector.getLastSum()); assertEquals(2, collector.getNumberOfJobs()); sum = sendMessages(8); // <1> Sending messages from separate connections makes no difference sum += sendMessages(4); runJob(); assertEquals(12, collector.getLastItemCount()); assertEquals(sum, collector.getLastSum()); assertEquals(3, collector.getNumberOfJobs()); } private void runJob() throws InterruptedException { JobOperator jobOperator = BatchRuntime.getJobOperator(); Long executionId = jobOperator.start("jms-job", new Properties()); JobExecution jobExecution = jobOperator.getJobExecution(executionId); BatchTestHelper.keepTestAlive(jobExecution); } private int sendMessages(int count) { int sum = 0; Random r = new Random(); try (JMSContext jms = factory.createContext(Session.AUTO_ACKNOWLEDGE)) { JMSProducer producer = jms.createProducer(); for (int i=0; i< count; i++) { int payload = r.nextInt(); producer.send(topic, payload); sum += payload; } } return sum; } }