001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.engine;
018:
019: import java.io.Serializable;
020:
021: import javax.xml.namespace.QName;
022:
023: import org.junit.Test;
024: import org.kuali.bus.services.KSBServiceLocator;
025: import org.kuali.workflow.test.WorkflowTestCase;
026:
027: import edu.iu.uis.eden.DocumentRouteStatusChange;
028: import edu.iu.uis.eden.EdenConstants;
029: import edu.iu.uis.eden.KEWServiceLocator;
030: import edu.iu.uis.eden.clientapp.WorkflowDocument;
031: import edu.iu.uis.eden.clientapp.vo.NetworkIdVO;
032: import edu.iu.uis.eden.engine.node.BranchState;
033: import edu.iu.uis.eden.engine.node.RouteNodeInstance;
034: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
035: import edu.iu.uis.eden.messaging.JavaServiceDefinition;
036: import edu.iu.uis.eden.messaging.KEWJavaService;
037: import edu.iu.uis.eden.messaging.MessageServiceNames;
038: import edu.iu.uis.eden.messaging.exceptionhandling.DocumentMessageExceptionHandler;
039: import edu.iu.uis.eden.postprocessor.DefaultPostProcessor;
040: import edu.iu.uis.eden.postprocessor.ProcessDocReport;
041: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
042: import edu.iu.uis.eden.test.TestUtilities;
043:
044: public class StandardWorkflowEngineTest extends WorkflowTestCase {
045:
046: protected void loadTestData() throws Exception {
047: loadXmlFile("EngineConfig.xml");
048: }
049:
050: /**
051: * Tests that the proper state is set up on the root branch in the document
052: * to indicate that both PROCESSED and FINAL callbacks have been made into
053: * the post processor.
054: */
055: @Test
056: public void testSystemBranchState() throws Exception {
057: // route the document to final
058: WorkflowDocument document = new WorkflowDocument(
059: new NetworkIdVO("ewestfal"), "SimpleDocType");
060: document.routeDocument("");
061: assertTrue("Document should be final.", document.stateIsFinal());
062:
063: // now look at the branch state
064: DocumentRouteHeaderValue routeHeader = KEWServiceLocator
065: .getRouteHeaderService().getRouteHeader(
066: document.getRouteHeaderId());
067: RouteNodeInstance nodeInstance = (RouteNodeInstance) routeHeader
068: .getInitialRouteNodeInstance(0);
069: BranchState processedBranchState = nodeInstance.getBranch()
070: .getBranchState(
071: EdenConstants.POST_PROCESSOR_PROCESSED_KEY);
072: BranchState finalBranchState = nodeInstance.getBranch()
073: .getBranchState(EdenConstants.POST_PROCESSOR_FINAL_KEY);
074: assertNotNull(processedBranchState);
075: assertNotNull(finalBranchState);
076: assertEquals("true", processedBranchState.getValue());
077: assertEquals("true", finalBranchState.getValue());
078: assertEquals(1, TestPostProcessor.processedCount);
079: assertEquals(1, TestPostProcessor.finalCount);
080: }
081:
082: /**
083: * Tests that a FINAL document can go into exception routing and recover
084: * properly while only calling the PROCESSED and FINAL callbacks once.
085: */
086: @Test
087: public void testFinalDocumentExceptionRoutingRecovery()
088: throws Exception {
089:
090: // route the document to final
091: WorkflowDocument document = new WorkflowDocument(
092: new NetworkIdVO("ewestfal"), "SimpleDocType");
093: document.routeDocument("");
094: assertTrue("Document should be final.", document.stateIsFinal());
095: assertEquals(1, TestPostProcessor.processedCount);
096: assertEquals(1, TestPostProcessor.finalCount);
097:
098: // now queue up an exploder which should push the document into
099: // exception routing
100: JavaServiceDefinition serviceDef = new JavaServiceDefinition();
101: serviceDef.setPriority(new Integer(1));
102: serviceDef.setQueue(true);
103: serviceDef.setRetryAttempts(0);
104: serviceDef.setServiceInterface(KEWJavaService.class.getName());
105: serviceDef.setServiceName(new QName("KEW", "exploader"));
106: serviceDef.setService(new ImTheExploderProcessor());
107:
108: serviceDef
109: .setMessageExceptionHandler(DocumentMessageExceptionHandler.class
110: .getName());
111: serviceDef.validate();
112: KSBServiceLocator.getServiceDeployer().registerService(
113: serviceDef, true);
114:
115: KEWJavaService exploderAsService = (KEWJavaService) MessageServiceNames
116: .getServiceAsynchronously(
117: new QName("KEW", "exploader"),
118: KEWServiceLocator.getRouteHeaderService()
119: .getRouteHeader(
120: document.getRouteHeaderId()));
121: exploderAsService.invoke("");
122: // we need to make the exploder a service to get this going again...
123: // SpringServiceLocator.getRouteQueueService().requeueDocument(document.getRouteHeaderId(),
124: // ImTheExploderProcessor.class.getName());
125: // fail("Should have exploded!!!");
126: TestUtilities.waitForExceptionRouting();
127:
128: // the document should be in exception routing now
129: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
130: document.getRouteHeaderId());
131: assertTrue("Document should be in exception routing.", document
132: .stateIsException());
133: assertEquals(1, TestPostProcessor.processedCount);
134: assertEquals(1, TestPostProcessor.finalCount);
135:
136: assertTrue("ewestfal should have a complete request.", document
137: .isCompletionRequested());
138: document.complete("");
139:
140: // the document should be final once again
141: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
142: document.getRouteHeaderId());
143: assertTrue("Document should be final.", document.stateIsFinal());
144: assertEquals(1, TestPostProcessor.processedCount);
145: assertEquals(1, TestPostProcessor.finalCount);
146: }
147:
148: public void tearDown() throws Exception {
149: TestPostProcessor.resetProcessedCount();
150: TestPostProcessor.resetFinalCount();
151: super .tearDown();
152: }
153:
154: public static class TestPostProcessor extends DefaultPostProcessor {
155:
156: public static int finalCount = 0;
157:
158: public static int processedCount = 0;
159:
160: public ProcessDocReport doRouteStatusChange(
161: DocumentRouteStatusChange statusChangeEvent)
162: throws Exception {
163: if (EdenConstants.ROUTE_HEADER_PROCESSED_CD
164: .equals(statusChangeEvent.getNewRouteStatus())) {
165: processedCount++;
166: } else if (EdenConstants.ROUTE_HEADER_FINAL_CD
167: .equals(statusChangeEvent.getNewRouteStatus())) {
168: finalCount++;
169: }
170: return new ProcessDocReport(true);
171: }
172:
173: public static void resetProcessedCount() {
174: processedCount = 0;
175: }
176:
177: public static void resetFinalCount() {
178: finalCount = 0;
179: }
180: }
181:
182: public static class ImTheExploderProcessor implements
183: KEWJavaService {
184:
185: public void invoke(Serializable payLoad) {
186: throw new WorkflowRuntimeException("I'm the Exploder!!!");
187: }
188:
189: }
190:
191: }
|