1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.routemanager;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24
25 import java.util.Collection;
26 import java.util.List;
27
28 import org.junit.Test;
29 import org.kuali.rice.kew.api.KewApiServiceLocator;
30 import org.kuali.rice.kew.api.WorkflowDocument;
31 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
32 import org.kuali.rice.kew.api.action.ActionRequest;
33 import org.kuali.rice.kew.api.action.ActionRequestType;
34 import org.kuali.rice.kew.api.action.InvalidActionTakenException;
35 import org.kuali.rice.kew.api.action.RecipientType;
36 import org.kuali.rice.kew.api.document.DocumentProcessingQueue;
37 import org.kuali.rice.kew.api.document.DocumentStatus;
38 import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
39 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
40 import org.kuali.rice.kew.service.KEWServiceLocator;
41 import org.kuali.rice.kew.test.KEWTestCase;
42 import org.kuali.rice.kew.test.TestUtilities;
43 import org.kuali.rice.kim.api.group.Group;
44 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
45 import org.kuali.rice.test.BaselineTestCase;
46
47 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.CLEAR_DB)
48 public class ExceptionRoutingTest extends KEWTestCase {
49
50 protected void loadTestData() throws Exception {
51 loadXmlFile("RouteManagerConfig.xml");
52 }
53
54 protected void setUpAfterDataLoad() throws Exception {
55 super.setUpAfterDataLoad();
56
57 ExceptionRoutingTestPostProcessor.THROW_DO_ACTION_TAKEN_EXCEPTION = false;
58 ExceptionRoutingTestPostProcessor.THROW_ROUTE_DELETE_ROUTE_HEADER_EXCEPTION = false;
59 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
60 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = false;
61 ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING = false;
62 ExceptionRoutingTestPostProcessor.BLOW_UP_ON_TRANSITION_INTO_EXCEPTION = false;
63 }
64
65 @Test public void testSequentialExceptionRouting() throws Exception {
66 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "ExceptionRoutingSequentialDoc");
67 try {
68 doc.route("");
69 fail("should have thrown routing exception");
70 } catch (Exception e) {
71 }
72
73 TestUtilities.getExceptionThreader().join();
74
75 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
76 assertEquals("Document status incorrect", DocumentStatus.EXCEPTION, doc.getStatus());
77
78 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(doc.getDocumentId());
79
80 assertEquals("Should be a single exception request", 1, actionRequests.size());
81 for (ActionRequest actionRequest : actionRequests) {
82 Group group = KimApiServiceLocator.getGroupService().getGroup(actionRequest.getGroupId());
83 assertTrue("Request should be an exception request." + actionRequest, actionRequest.isExceptionRequest());
84 assertEquals("Complete should be requested", ActionRequestType.COMPLETE, actionRequest.getActionRequested());
85 assertEquals("Request should be a workgroup request", RecipientType.GROUP, actionRequest.getRecipientType());
86 assertEquals("Request should be to 'ExceptionRoutingGroup'", "ExceptionRoutingGroup", group.getName());
87 assertNotNull("annotation cannot be null", actionRequest.getAnnotation());
88 assertFalse("annotation cannot be empty", "".equals(actionRequest.getAnnotation()));
89 }
90
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 @Test public void testInvalidActionsInExceptionRouting() throws Exception {
119 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "ExceptionRoutingSequentialDoc");
120 try {
121 doc.route("");
122 fail("should have thrown routing exception");
123 } catch (Exception e) {
124 log.info("Expected exception occurred: " + e);
125 }
126
127 TestUtilities.getExceptionThreader().join();
128
129 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
130 assertTrue("Document should be in exception status", doc.isException());
131
132 try {
133 doc.route("routing a document that is in exception routing");
134 fail("Succeeded in routing document that is in exception routing");
135 } catch (InvalidActionTakenException iate) {
136 log.info("Expected exception occurred: " + iate);
137 }
138 }
139
140 @Test public void testParallelExceptionRouting() throws Exception {
141 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "ExceptionRoutingParallelDoc");
142 doc.route("");
143 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), doc.getDocumentId());
144 assertTrue("User should have an approve request", doc.isApprovalRequested());
145 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), doc.getDocumentId());
146 assertTrue("User should have an approve request", doc.isApprovalRequested());
147 List<RouteNodeInstance> nodes = KewApiServiceLocator.getWorkflowDocumentService().getActiveRouteNodeInstances(
148 doc.getDocumentId());
149
150
151 assertEquals("There should be two active nodes", 2, nodes.size());
152 TestUtilities.assertAtNode(doc, "RouteNode1");
153 TestUtilities.assertAtNode(doc, "RouteNode3");
154
155 try {
156 doc.approve("");
157 fail("should have generated routing exception");
158 } catch (Exception e) {
159 }
160
161 TestUtilities.getExceptionThreader().join();
162 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(doc.getDocumentId());
163 RouteNodeInstance routeNode1 = null;
164 for (RouteNodeInstance nodeInstanceVO : nodes) {
165 if (nodeInstanceVO.getName().equals("RouteNode1")) {
166 routeNode1 = nodeInstanceVO;
167 }
168 }
169 assertNotNull("Could not locate the routeNode1 node instance.", routeNode1);
170
171 boolean hasCompleteRequest = false;
172 for (ActionRequest actionRequest : actionRequests) {
173 if (actionRequest.isCompleteRequest()) {
174 Group group = KimApiServiceLocator.getGroupService().getGroup(actionRequest.getGroupId());
175 assertTrue("Complete should be requested", actionRequest.isCompleteRequest());
176 assertTrue("Request should be a workgroup request", actionRequest.isGroupRequest());
177 assertNull("For exception routing, node instance should have a null id.", actionRequest.getRouteNodeInstanceId());
178
179 assertEquals("Request should be to 'ExceptionRoutingGroup'", "ExceptionRoutingGroup", group.getName());
180 hasCompleteRequest = true;
181 }
182 }
183 assertTrue("Document should have had a complete request", hasCompleteRequest);
184 ExplodingRuleAttribute.dontExplode=true;
185
186
187 Collection actionItems = KEWServiceLocator.getActionListService().findByDocumentId(doc.getDocumentId());
188 assertEquals("There should only be action items for the member of our exception workgroup", 1, actionItems.size());
189
190 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
191 assertTrue("Document should be routing for completion to member of exception workgroup", doc.isCompletionRequested());
192 assertTrue("Document should be in exception status", doc.isException());
193 doc.complete("");
194
195 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), doc.getDocumentId());
196 doc.approve("");
197
198 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), doc.getDocumentId());
199 doc.approve("");
200
201 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
202 doc.approve("");
203
204 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
205 doc.approve("");
206
207 assertTrue("Document should be final", doc.isFinal());
208 }
209
210
211
212
213
214
215
216 @Test public void testExceptionInTransitionFromStart() throws Exception {
217
218 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "AdhocTransitionTestDocument");
219
220 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = true;
221
222 try {
223 doc.route("");
224 fail("We should be in exception routing");
225 } catch (Exception e) {
226 }
227
228 TestUtilities.getExceptionThreader().join();
229 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
230 assertEquals("document should be in exception routing", DocumentStatus.EXCEPTION, doc.getStatus());
231 }
232
233
234
235
236
237
238
239 @Test public void testRequeueOfExceptionDocument() throws Exception {
240 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "AdhocTransitionTestDocument");
241 document.route("");
242 assertFalse("Document should not be in exception routing.", document.isException());
243
244
245 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
246 assertTrue("Jhopf should have an approve.", document.isApprovalRequested());
247
248
249 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = true;
250 try {
251 document.approve("");
252 fail("We should be in exception routing");
253 } catch (Exception e) {
254 }
255
256 TestUtilities.waitForExceptionRouting();
257 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
258 assertEquals("document should be in exception routing", DocumentStatus.EXCEPTION, document.getStatus());
259
260
261
262
263 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
264 assertFalse("Should not have transitioned out of exception routing yet.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
265
266 DocumentRouteHeaderValue routeHeaderValue = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId());
267 String applicationId = routeHeaderValue.getDocumentType().getApplicationId();
268 DocumentProcessingQueue documentProcessingQueue = KewApiServiceLocator.getDocumentProcessingQueue(document.getDocumentId(), applicationId);
269 documentProcessingQueue.process(String.valueOf(document.getDocumentId()));
270
271
272 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
273 assertEquals("document should be in exception routing", DocumentStatus.EXCEPTION, document.getStatus());
274 assertFalse("document shouldn't have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
275
276
277 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
278 assertTrue("rkirkend should be in the exception workgroup.", document.isCompletionRequested());
279 document.complete("Completing out of exception routing.");
280
281
282
283
284 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
285 assertTrue(document.isApprovalRequested());
286 document.approve("");
287
288
289 assertTrue("Document should be FINAL.", document.isFinal());
290
291
292 assertTrue("Document should have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
293 }
294
295 }