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 org.junit.Test;
19 import org.kuali.rice.kew.api.KewApiServiceLocator;
20 import org.kuali.rice.kew.api.WorkflowDocument;
21 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
22 import org.kuali.rice.kew.api.action.ActionRequest;
23 import org.kuali.rice.kew.api.action.InvalidActionTakenException;
24 import org.kuali.rice.kew.api.document.DocumentProcessingQueue;
25 import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
26 import org.kuali.rice.kew.messaging.MessageServiceNames;
27 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
28 import org.kuali.rice.kew.service.KEWServiceLocator;
29 import org.kuali.rice.kew.test.KEWTestCase;
30 import org.kuali.rice.kew.test.TestUtilities;
31 import org.kuali.rice.kim.api.group.Group;
32 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
33 import org.kuali.rice.ksb.messaging.service.KSBXMLService;
34 import org.kuali.rice.test.BaselineTestCase;
35
36 import javax.xml.namespace.QName;
37 import java.util.Collection;
38 import java.util.List;
39
40 import static org.junit.Assert.*;
41
42 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.CLEAR_DB)
43 public class ExceptionRoutingTest extends KEWTestCase {
44
45 protected void loadTestData() throws Exception {
46 loadXmlFile("RouteManagerConfig.xml");
47 }
48
49 protected void setUpAfterDataLoad() throws Exception {
50 super.setUpAfterDataLoad();
51
52 ExceptionRoutingTestPostProcessor.THROW_DO_ACTION_TAKEN_EXCEPTION = false;
53 ExceptionRoutingTestPostProcessor.THROW_ROUTE_DELETE_ROUTE_HEADER_EXCEPTION = false;
54 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
55 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = false;
56 ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING = false;
57 ExceptionRoutingTestPostProcessor.BLOW_UP_ON_TRANSITION_INTO_EXCEPTION = false;
58 }
59
60 @Test public void testSequentialExceptionRouting() throws Exception {
61 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "ExceptionRoutingSequentialDoc");
62 try {
63 doc.route("");
64 fail("should have thrown routing exception");
65 } catch (Exception e) {
66 }
67
68 TestUtilities.getExceptionThreader().join();
69
70 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
71 assertTrue("Document should be in exception status", doc.isException());
72
73 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(doc.getDocumentId());
74
75 assertEquals("Should be a single exception request", 1, actionRequests.size());
76 for (ActionRequest actionRequest : actionRequests) {
77 Group group = KimApiServiceLocator.getGroupService().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.getName());
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 = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "ExceptionRoutingSequentialDoc");
115 try {
116 doc.route("");
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 = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
125 assertTrue("Document should be in exception status", doc.isException());
126
127 try {
128 doc.route("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 }
133 }
134
135 @Test public void testParallelExceptionRouting() throws Exception {
136 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "ExceptionRoutingParallelDoc");
137 doc.route("");
138 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), doc.getDocumentId());
139 assertTrue("User should have an approve request", doc.isApprovalRequested());
140 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), doc.getDocumentId());
141 assertTrue("User should have an approve request", doc.isApprovalRequested());
142 List<RouteNodeInstance> nodes = KewApiServiceLocator.getWorkflowDocumentService().getActiveRouteNodeInstances(
143 doc.getDocumentId());
144
145
146 assertEquals("There should be two active nodes", 2, nodes.size());
147 TestUtilities.assertAtNode(doc, "RouteNode1");
148 TestUtilities.assertAtNode(doc, "RouteNode3");
149
150 try {
151 doc.approve("");
152 fail("should have generated routing exception");
153 } catch (Exception e) {
154 }
155
156 TestUtilities.getExceptionThreader().join();
157 List<ActionRequest> actionRequests = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(doc.getDocumentId());
158 RouteNodeInstance routeNode1 = null;
159 for (RouteNodeInstance nodeInstanceVO : nodes) {
160 if (nodeInstanceVO.getName().equals("RouteNode1")) {
161 routeNode1 = nodeInstanceVO;
162 }
163 }
164 assertNotNull("Could not locate the routeNode1 node instance.", routeNode1);
165
166 boolean hasCompleteRequest = false;
167 for (ActionRequest actionRequest : actionRequests) {
168 if (actionRequest.isCompleteRequest()) {
169 Group group = KimApiServiceLocator.getGroupService().getGroup(actionRequest.getGroupId());
170 assertTrue("Complete should be requested", actionRequest.isCompleteRequest());
171 assertTrue("Request should be a workgroup request", actionRequest.isGroupRequest());
172 assertNull("For exception routing, node instance should have a null id.", actionRequest.getRouteNodeInstanceId());
173
174 assertEquals("Request should be to 'ExceptionRoutingGroup'", "ExceptionRoutingGroup", group.getName());
175 hasCompleteRequest = true;
176 }
177 }
178 assertTrue("Document should have had a complete request", hasCompleteRequest);
179 ExplodingRuleAttribute.dontExplode=true;
180
181
182 Collection actionItems = KEWServiceLocator.getActionListService().findByDocumentId(doc.getDocumentId());
183 assertEquals("There should only be action items for the member of our exception workgroup", 1, actionItems.size());
184
185 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
186 assertTrue("Document should be routing for completion to member of exception workgroup", doc.isCompletionRequested());
187 assertTrue("Document should be in exception status", doc.isException());
188 doc.complete("");
189
190 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), doc.getDocumentId());
191 doc.approve("");
192
193 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), doc.getDocumentId());
194 doc.approve("");
195
196 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
197 doc.approve("");
198
199 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
200 doc.approve("");
201
202 assertTrue("Document should be final", doc.isFinal());
203 }
204
205
206
207
208
209
210
211 @Test public void testExceptionInTransitionFromStart() throws Exception {
212
213 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "AdhocTransitionTestDocument");
214
215 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_LEVEL_EXCEPTION = true;
216
217 try {
218 doc.route("");
219 fail("We should be in exception routing");
220 } catch (Exception e) {
221 }
222
223 TestUtilities.getExceptionThreader().join();
224 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), doc.getDocumentId());
225 assertTrue("document should be in exception routing", doc.isException());
226 }
227
228
229
230
231
232
233
234 @Test public void testRequeueOfExceptionDocument() throws Exception {
235 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "AdhocTransitionTestDocument");
236 document.route("");
237 assertFalse("Document should not be in exception routing.", document.isException());
238
239
240 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
241 assertTrue("Jhopf should have an approve.", document.isApprovalRequested());
242
243
244 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = true;
245 try {
246 document.approve("");
247 fail("We should be in exception routing");
248 } catch (Exception e) {
249 }
250
251 TestUtilities.waitForExceptionRouting();
252 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
253 assertTrue("document should be in exception routing", document.isException());
254
255
256
257
258 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
259 assertFalse("Should not have transitioned out of exception routing yet.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
260
261 DocumentRouteHeaderValue routeHeaderValue = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId());
262 DocumentProcessingQueue documentProcessingQueue = MessageServiceNames.getDocumentProcessingQueue(routeHeaderValue);
263 documentProcessingQueue.process(String.valueOf(document.getDocumentId()));
264
265
266 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
267 assertTrue("document should be in exception routing", document.isException());
268 assertFalse("document shouldn't have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
269
270
271 ExceptionRoutingTestPostProcessor.THROW_ROUTE_STATUS_CHANGE_EXCEPTION = false;
272 assertTrue("rkirkend should be in the exception workgroup.", document.isCompletionRequested());
273 document.complete("Completing out of exception routing.");
274
275
276
277
278 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
279 assertTrue(document.isApprovalRequested());
280 document.approve("");
281
282
283 assertTrue("Document should be FINAL.", document.isFinal());
284
285
286 assertTrue("Document should have transitioned out of exception routing.", ExceptionRoutingTestPostProcessor.TRANSITIONED_OUT_OF_EXCEPTION_ROUTING);
287 }
288
289 }