001 /**
002 * Copyright 2005-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kcb.service.impl;
017
018 import org.apache.commons.lang.RandomStringUtils;
019 import org.junit.Assert;
020 import org.junit.Test;
021 import org.kuali.rice.kcb.bo.MessageDelivery;
022 import org.kuali.rice.kcb.bo.MessageDeliveryStatus;
023 import org.kuali.rice.kcb.api.message.MessageDTO;
024 import org.kuali.rice.kcb.quartz.MessageProcessingJob;
025 import org.kuali.rice.kcb.test.KCBTestCase;
026 import org.kuali.rice.ksb.service.KSBServiceLocator;
027 import org.kuali.rice.test.BaselineTestCase.BaselineMode;
028 import org.kuali.rice.test.BaselineTestCase.Mode;
029 import org.quartz.JobExecutionContext;
030 import org.quartz.JobExecutionException;
031 import org.quartz.SchedulerException;
032 import org.quartz.listeners.JobListenerSupport;
033 import org.springframework.transaction.support.TransactionSynchronizationManager;
034
035 import java.util.Collection;
036 import java.util.concurrent.CountDownLatch;
037 import java.util.concurrent.TimeUnit;
038
039 import static org.junit.Assert.*;
040
041 /**
042 * Tests MessagingService
043 *
044 * @author Kuali Rice Team (rice.collab@kuali.org)
045 */
046 /*
047 @PerTestUnitTestData({
048 @UnitTestData(filename = "file:ken/src/main/config/sql/KENBootstrap.sql", delimiter = "/"),
049 @UnitTestData(filename = "classpath:org/kuali/rice/kcb/test/KENTestData.sql")
050 }
051 )*/
052 @BaselineMode(Mode.CLEAR_DB)
053 public class MessagingServiceTest extends KCBTestCase {
054 private CountDownLatch signal = new CountDownLatch(1);
055
056 @Override
057 public void setUp() throws Exception {
058 super.setUp();
059
060 services.getRecipientPreferenceService().saveRecipientDelivererConfig("testuser5", "mock", new String[] { "Test Channel #1" });
061 services.getRecipientPreferenceService().saveRecipientDelivererConfig("testuser5", "sms", new String[] { "Test Channel #1" });
062 services.getRecipientPreferenceService().saveRecipientDelivererConfig("testuser5", "broken", new String[] { "Test Channel #1" }); // this one throws exceptions
063 services.getRecipientPreferenceService().saveRecipientDelivererConfig("testuser5", "bogus", new String[] { "Test Channel #1" }); // this one doesn't exist
064
065 assertEquals(4, services.getRecipientPreferenceService().getDeliverersForRecipientAndChannel("testuser5", "Test Channel #1").size());
066 }
067
068 protected long deliver() throws Exception {
069 MessageDTO message = new MessageDTO();
070 message.setContent("test content 1");
071 message.setChannel("Test Channel #1");
072 message.setContentType("test content type 1");
073 message.setDeliveryType("test delivery type 1");
074 message.setRecipient("testuser5");
075 message.setTitle("test title 1");
076 message.setOriginId("origin id");
077
078 registerJobListener();
079
080 long id = services.getMessagingService().deliver(message);
081
082 waitForNextJobCompletion();
083
084 Collection<MessageDelivery> deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
085 assertNotNull(deliveries);
086 int delivCount = services.getRecipientPreferenceService().getDeliverersForRecipientAndChannel("testuser5", "Test Channel #1").size();
087 assertEquals(delivCount, deliveries.size());
088 assertTrue(deliveries.size() > 0);
089 int failed = 0;
090 for (MessageDelivery delivery: deliveries) {
091 if ("broken".equals(delivery.getDelivererTypeName()) || "bogus".equals(delivery.getDelivererTypeName())) {
092 assertEquals(MessageDeliveryStatus.UNDELIVERED.name(), delivery.getDeliveryStatus());
093 assertEquals(1, delivery.getProcessCount().intValue());
094 failed++;
095 } else {
096 assertEquals(MessageDeliveryStatus.DELIVERED.name(), delivery.getDeliveryStatus());
097 }
098 }
099
100 assertEquals(2, failed);
101
102 // try up till max attempts, which for now is 3
103
104 waitForNextJobCompletion();
105
106 failed = 0;
107 deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
108 for (MessageDelivery delivery: deliveries) {
109 if ("broken".equals(delivery.getDelivererTypeName()) || "bogus".equals(delivery.getDelivererTypeName())) {
110 assertEquals(MessageDeliveryStatus.UNDELIVERED.name(), delivery.getDeliveryStatus());
111 assertEquals(2, delivery.getProcessCount().intValue());
112 failed++;
113 } else {
114 assertEquals(MessageDeliveryStatus.DELIVERED.name(), delivery.getDeliveryStatus());
115 }
116 }
117
118 assertEquals(2, failed);
119
120 waitForNextJobCompletion();
121
122 failed = 0;
123 deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
124 for (MessageDelivery delivery: deliveries) {
125 if ("broken".equals(delivery.getDelivererTypeName()) || "bogus".equals(delivery.getDelivererTypeName())) {
126 assertEquals(MessageDeliveryStatus.UNDELIVERED.name(), delivery.getDeliveryStatus());
127 assertEquals(3, delivery.getProcessCount().intValue());
128 failed++;
129 } else {
130 assertEquals(MessageDeliveryStatus.DELIVERED.name(), delivery.getDeliveryStatus());
131 }
132 }
133
134 assertEquals(2, failed);
135
136 // finally the last attempt, nothing should have changed
137
138 waitForNextJobCompletion();
139
140 failed = 0;
141 deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
142 for (MessageDelivery delivery: deliveries) {
143 if ("broken".equals(delivery.getDelivererTypeName()) || "bogus".equals(delivery.getDelivererTypeName())) {
144 assertEquals(MessageDeliveryStatus.UNDELIVERED.name(), delivery.getDeliveryStatus());
145 assertEquals(3, delivery.getProcessCount().intValue());
146 failed++;
147 } else {
148 assertEquals(MessageDeliveryStatus.DELIVERED.name(), delivery.getDeliveryStatus());
149 }
150 }
151
152 assertEquals(2, failed);
153
154 return id;
155 }
156
157 @Test
158 public void testDeliver() throws Exception {
159 Assert.assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
160
161 deliver();
162 }
163
164 @Test
165 public void testDismiss() throws Exception {
166 Assert.assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
167
168 long id = deliver();
169
170 registerJobListener();
171
172 services.getMessagingService().remove(id, "a user", "a cause");
173
174 waitForNextJobCompletion();
175
176 Collection<MessageDelivery> deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
177 assertNotNull(deliveries);
178 // should be all gone except for the 2 bad deliveries
179 assertEquals(2, deliveries.size());
180 for (MessageDelivery d: deliveries) {
181 assertTrue("broken".equals(d.getDelivererTypeName()) || "bogus".equals(d.getDelivererTypeName()));
182 }
183 }
184
185 @Test
186 public void testDismissByOriginId() throws Exception {
187 Assert.assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
188
189 long id = deliver();
190
191 registerJobListener();
192
193 services.getMessagingService().removeByOriginId("origin id", "a user", "a cause");
194
195 waitForNextJobCompletion();
196
197 Collection<MessageDelivery> deliveries = services.getMessageDeliveryService().getAllMessageDeliveries();
198 assertNotNull(deliveries);
199 // should be all gone except for the 2 bad deliveries
200 assertEquals(2, deliveries.size());
201
202 // should be all gone except for the 2 bad deliveries
203 assertEquals(2, deliveries.size());
204 for (MessageDelivery d: deliveries) {
205 assertTrue("broken".equals(d.getDelivererTypeName()) || "bogus".equals(d.getDelivererTypeName()));
206 }
207 }
208
209 protected void registerJobListener() throws SchedulerException {
210 KSBServiceLocator.getScheduler().addGlobalJobListener(new JobListenerSupport() {
211 @Override
212 public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
213 log.info("Job was executed: " + context);
214 if (MessageProcessingJob.NAME.equals(context.getJobDetail().getName())) {
215 signal.countDown();
216 }
217 }
218 public String getName() {
219 return System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(10);
220 }
221 });
222 }
223
224 protected void waitForNextJobCompletion() throws InterruptedException {
225 log.info("Waiting for job to complete...");
226 signal.await(100, TimeUnit.SECONDS); // time limit so as not to hang tests if something goes wrong
227 signal = new CountDownLatch(1);
228 log.info("Job completed...");
229 }
230 }