1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.rice.kew.routemanager;
18
19 import java.util.Collection;
20
21 import javax.xml.namespace.QName;
22
23 import org.junit.Test;
24 import org.kuali.rice.kew.dto.ActionRequestDTO;
25 import org.kuali.rice.kew.dto.NetworkIdDTO;
26 import org.kuali.rice.kew.dto.RouteNodeInstanceDTO;
27 import org.kuali.rice.kew.exception.InvalidActionTakenException;
28 import org.kuali.rice.kew.exception.WorkflowException;
29 import org.kuali.rice.kew.messaging.MessageServiceNames;
30 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
31 import org.kuali.rice.kew.service.KEWServiceLocator;
32 import org.kuali.rice.kew.service.WorkflowDocument;
33 import org.kuali.rice.kew.service.WorkflowInfo;
34 import org.kuali.rice.kew.test.KEWTestCase;
35 import org.kuali.rice.kew.test.TestUtilities;
36 import org.kuali.rice.kim.bo.Group;
37 import org.kuali.rice.kim.service.KIMServiceLocator;
38 import org.kuali.rice.ksb.messaging.service.KSBXMLService;
39
40
41 public class ExceptionRoutingTest extends KEWTestCase {
42
43 protected void loadTestData() throws Exception {
44 loadXmlFile("RouteManagerConfig.xml");
45 }
46
47 protected void setUpAfterDataLoad() throws Exception {
48 super.setUpAfterDataLoad();
49
50 ExceptionRoutingTestPostProcessor.THROW_DO_ACTION_TAKEN_EXCEPTION = false;
51 ExceptionRoutingTestPostProcessor.THROW_ROUTE_DELETE_ROUTE_HEADER_EXCEPTION = false;
52 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
53 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = false;
54 ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING = false;
55 ExceptionRoutingTestPostProcessor.BLOW_UP_ON_TRANSITION_INTO_EXCEPTION = false;
56 }
57
58 @Test public void testSequentialExceptionRouting() throws Exception {
59 WorkflowDocument doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), "ExceptionRoutingSequentialDoc");
60 try {
61 doc.routeDocument("");
62 fail("should have thrown routing exception");
63 } catch (Exception e) {
64 }
65
66 TestUtilities.getExceptionThreader().join();
67
68 doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), doc.getRouteHeaderId());
69 assertTrue("Document should be in exception status", doc.stateIsException());
70
71 WorkflowInfo info = new WorkflowInfo();
72 ActionRequestDTO[] actionRequests = info.getActionRequests(doc.getRouteHeaderId());
73
74 assertEquals("Should be a single exception request", 1, actionRequests.length);
75 for (int i = 0; i < actionRequests.length; i++) {
76 ActionRequestDTO actionRequest = actionRequests[i];
77 Group group = KIMServiceLocator.getIdentityManagementService().getGroup(actionRequest.getGroupId());
78 assertTrue("Request should be an exception request.", actionRequest.isExceptionRequest());
79 assertTrue("Complete should be requested", actionRequest.isCompleteRequest());
80 assertTrue("Request should be a workgroup request", actionRequest.isGroupRequest());
81 assertEquals("Request should be to 'ExceptionRoutingGroup'", "ExceptionRoutingGroup", group.getGroupName());
82 assertNotNull("annotation cannot be null", actionRequest.getAnnotation());
83 assertFalse("annotation cannot be empty", "".equals(actionRequest.getAnnotation()));
84 }
85
86 }
87
88
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 @Test public void testInvalidActionsInExceptionRouting() throws Exception {
114 WorkflowDocument doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), "ExceptionRoutingSequentialDoc");
115 try {
116 doc.routeDocument("");
117 fail("should have thrown routing exception");
118 } catch (Exception e) {
119 log.info("Expected exception occurred: " + e);
120 }
121
122 TestUtilities.getExceptionThreader().join();
123
124 doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), doc.getRouteHeaderId());
125 assertTrue("Document should be in exception status", doc.stateIsException());
126
127 try {
128 doc.routeDocument("routing a document that is in exception routing");
129 fail("Succeeded in routing document that is in exception routing");
130 } catch (InvalidActionTakenException iate) {
131 log.info("Expected exception occurred: " + iate);
132 } catch (WorkflowException we) {
133 fail("Attempt at routing document in exception routing succeeded, when it should have been an InvalidActionTakenException");
134 }
135 }
136
137 @Test public void testParallelExceptionRouting() throws Exception {
138 WorkflowDocument doc = new WorkflowDocument(new NetworkIdDTO("user1"), "ExceptionRoutingParallelDoc");
139 doc.routeDocument("");
140 doc = new WorkflowDocument(new NetworkIdDTO("ewestfal"), doc.getRouteHeaderId());
141 assertTrue("User should have an approve request", doc.isApprovalRequested());
142 doc = new WorkflowDocument(new NetworkIdDTO("bmcgough"), doc.getRouteHeaderId());
143 assertTrue("User should have an approve request", doc.isApprovalRequested());
144 RouteNodeInstanceDTO[] nodes = new WorkflowInfo().getActiveNodeInstances(doc.getRouteHeaderId());
145
146
147 assertEquals("There should be two active nodes", 2, nodes.length);
148 TestUtilities.assertAtNode(doc, "RouteNode1");
149 TestUtilities.assertAtNode(doc, "RouteNode3");
150
151 try {
152 doc.approve("");
153 fail("should have generated routing exception");
154 } catch (Exception e) {
155 }
156
157 TestUtilities.getExceptionThreader().join();
158 WorkflowInfo info = new WorkflowInfo();
159 ActionRequestDTO[] actionRequests = info.getActionRequests(doc.getRouteHeaderId());
160 RouteNodeInstanceDTO routeNode1 = null;
161 for (RouteNodeInstanceDTO nodeInstanceVO : nodes) {
162 if (nodeInstanceVO.getName().equals("RouteNode1")) {
163 routeNode1 = nodeInstanceVO;
164 }
165 }
166 assertNotNull("Could not locate the routeNode1 node instance.", routeNode1);
167
168 boolean hasCompleteRequest = false;
169 for (int i = 0; i < actionRequests.length; i++) {
170 ActionRequestDTO actionRequest = actionRequests[i];
171 if (actionRequest.isCompleteRequest()) {
172 Group group = KIMServiceLocator.getIdentityManagementService().getGroup(actionRequest.getGroupId());
173 assertTrue("Complete should be requested", actionRequest.isCompleteRequest());
174 assertTrue("Request should be a workgroup request", actionRequest.isGroupRequest());
175 assertNull("For exception routing, node instance should have a null id.", actionRequest.getNodeInstanceId());
176
177
178 assertNull("Exception request routeMethodName wrong", actionRequest.getRouteMethodName());
179 assertEquals("Request should be to 'ExceptionRoutingGroup'", "ExceptionRoutingGroup", group.getGroupName());
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().findByRouteHeaderId(doc.getRouteHeaderId());
188 assertEquals("There should only be action items for the member of our exception workgroup", 1, actionItems.size());
189
190 doc = new WorkflowDocument(new NetworkIdDTO("user3"), doc.getRouteHeaderId());
191 assertTrue("Document should be routing for completion to member of exception workgroup", doc.isCompletionRequested());
192 assertTrue("Document should be in exception status", doc.stateIsException());
193 doc.complete("");
194
195 doc = new WorkflowDocument(new NetworkIdDTO("bmcgough"), doc.getRouteHeaderId());
196 doc.approve("");
197
198 doc = new WorkflowDocument(new NetworkIdDTO("ewestfal"), doc.getRouteHeaderId());
199 doc.approve("");
200
201 doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), doc.getRouteHeaderId());
202 doc.approve("");
203
204 doc = new WorkflowDocument(new NetworkIdDTO("jhopf"), doc.getRouteHeaderId());
205 doc.approve("");
206
207 assertTrue("Document should be final", doc.stateIsFinal());
208 }
209
210
211
212
213
214
215
216 @Test public void testExceptionInTransitionFromStart() throws Exception {
217
218 WorkflowDocument doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), "AdhocTransitionTestDocument");
219
220 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = true;
221
222 try {
223 doc.routeDocument("");
224 fail("We should be in exception routing");
225 } catch (Exception e) {
226 }
227
228 TestUtilities.getExceptionThreader().join();
229 doc = new WorkflowDocument(new NetworkIdDTO("rkirkend"), doc.getRouteHeaderId());
230 assertTrue("document should be in exception routing", doc.stateIsException());
231 }
232
233
234
235
236
237
238
239 @Test public void testRequeueOfExceptionDocument() throws Exception {
240 WorkflowDocument document = new WorkflowDocument(new NetworkIdDTO("rkirkend"), "AdhocTransitionTestDocument");
241 document.routeDocument("");
242 assertFalse("Document should not be in exception routing.", document.stateIsException());
243
244
245 document = new WorkflowDocument(new NetworkIdDTO("jhopf"), document.getRouteHeaderId());
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 = new WorkflowDocument(new NetworkIdDTO("rkirkend"), document.getRouteHeaderId());
258 assertTrue("document should be in exception routing", document.stateIsException());
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.getRouteHeaderId());
267 QName documentServiceName = new QName(routeHeaderValue.getDocumentType().getServiceNamespace(), MessageServiceNames.DOCUMENT_ROUTING_SERVICE);
268 KSBXMLService routeDocumentMessageService = (KSBXMLService)MessageServiceNames.getServiceAsynchronously(documentServiceName, routeHeaderValue);
269 routeDocumentMessageService.invoke(String.valueOf(document.getRouteHeaderId()));
270
271
272
273
274 document = new WorkflowDocument(new NetworkIdDTO("rkirkend"), document.getRouteHeaderId());
275 assertTrue("document should be in exception routing", document.stateIsException());
276 assertFalse("document shouldn't have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
277
278
279 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
280 assertTrue("rkirkend should be in the exception workgroup.", document.isCompletionRequested());
281 document.complete("Completing out of exception routing.");
282
283
284
285
286 document = new WorkflowDocument(new NetworkIdDTO("jhopf"), document.getRouteHeaderId());
287 assertTrue(document.isApprovalRequested());
288 document.approve("");
289
290
291 assertTrue("Document should be FINAL.", document.stateIsFinal());
292
293
294 assertTrue("Document should have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
295 }
296
297 }