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.messaging.exceptionhandling;
018:
019: import java.lang.reflect.InvocationTargetException;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.apache.log4j.MDC;
024: import org.kuali.bus.services.KSBServiceLocator;
025: import org.kuali.rice.util.ExceptionUtils;
026:
027: import edu.iu.uis.eden.EdenConstants;
028: import edu.iu.uis.eden.KEWServiceLocator;
029: import edu.iu.uis.eden.actionitem.ActionItem;
030: import edu.iu.uis.eden.actionrequests.ActionRequestFactory;
031: import edu.iu.uis.eden.actionrequests.ActionRequestValue;
032: import edu.iu.uis.eden.engine.node.RouteNodeInstance;
033: import edu.iu.uis.eden.exception.RouteManagerException;
034: import edu.iu.uis.eden.exception.WorkflowDocumentExceptionRoutingService;
035: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
036: import edu.iu.uis.eden.messaging.PersistedMessage;
037: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
038: import edu.iu.uis.eden.util.PerformanceLogger;
039:
040: public class ExceptionRoutingServiceImpl implements
041: WorkflowDocumentExceptionRoutingService {
042:
043: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
044: .getLogger(ExceptionRoutingServiceImpl.class);
045:
046: public void placeInExceptionRouting(Throwable throwable,
047: PersistedMessage persistedMessage, Long routeHeaderId) {
048: RouteNodeInstance nodeInstance = null;
049: KEWServiceLocator.getRouteHeaderService().lockRouteHeader(
050: routeHeaderId, true);
051: DocumentRouteHeaderValue document = KEWServiceLocator
052: .getRouteHeaderService().getRouteHeader(routeHeaderId);
053: throwable = unwrapRouteManagerExceptionIfPossible(throwable);
054: if (throwable instanceof RouteManagerException) {
055: RouteManagerException rmException = (RouteManagerException) throwable;
056: nodeInstance = rmException.getRouteContext()
057: .getNodeInstance();
058: } else {
059: List activeNodeInstances = KEWServiceLocator
060: .getRouteNodeService().getActiveNodeInstances(
061: routeHeaderId);
062: if (activeNodeInstances.isEmpty()) {
063: // get the initial node instance
064: nodeInstance = (RouteNodeInstance) document
065: .getInitialRouteNodeInstances().get(0);
066: } else {
067: // take the first active nodeInstance found.
068: nodeInstance = (RouteNodeInstance) activeNodeInstances
069: .get(0);
070: }
071: }
072:
073: MDC.put("docID", routeHeaderId);
074: PerformanceLogger performanceLogger = new PerformanceLogger(
075: routeHeaderId);
076: try {
077:
078: // mark all active requests to initialized and delete the action items
079: List actionRequests = KEWServiceLocator
080: .getActionRequestService().findPendingByDoc(
081: routeHeaderId);
082: for (Iterator iter = actionRequests.iterator(); iter
083: .hasNext();) {
084: ActionRequestValue actionRequest = (ActionRequestValue) iter
085: .next();
086: if (actionRequest.isActive()) {
087: actionRequest
088: .setStatus(EdenConstants.ACTION_REQUEST_INITIALIZED);
089: for (Iterator iterator = actionRequest
090: .getActionItems().iterator(); iterator
091: .hasNext();) {
092: KEWServiceLocator.getActionListService()
093: .deleteActionItem(
094: (ActionItem) iterator.next());
095: }
096: KEWServiceLocator.getActionRequestService()
097: .saveActionRequest(actionRequest);
098: }
099: }
100:
101: LOG.debug("Generating exception request for doc : "
102: + routeHeaderId);
103: Throwable cause = determineActualCause(throwable, 0);
104:
105: String message = (cause != null && cause.getMessage() != null) ? cause
106: .getMessage()
107: : "";
108: if (message.length() > EdenConstants.MAX_ANNOTATION_LENGTH) {
109: message = message.substring(0,
110: EdenConstants.MAX_ANNOTATION_LENGTH);
111: }
112: ActionRequestFactory arFactory = new ActionRequestFactory(
113: document, nodeInstance);
114: ActionRequestValue exceptionRequest = arFactory
115: .createActionRequest(
116: EdenConstants.ACTION_REQUEST_COMPLETE_REQ,
117: new Integer(0),
118: nodeInstance.getRouteNode()
119: .getExceptionWorkgroup(),
120: "Exception Workgroup for route node "
121: + nodeInstance.getName(),
122: EdenConstants.EXCEPTION_REQUEST_RESPONSIBILITY_ID,
123: Boolean.TRUE, message);
124: DocumentRouteHeaderValue rh = KEWServiceLocator
125: .getRouteHeaderService().getRouteHeader(
126: routeHeaderId);
127: rh
128: .setDocRouteStatus(EdenConstants.ROUTE_HEADER_EXCEPTION_CD);
129: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
130: rh);
131: KEWServiceLocator.getActionRequestService()
132: .activateRequest(exceptionRequest);
133: KSBServiceLocator.getRouteQueueService().delete(
134: persistedMessage);
135: } catch (Exception e) {
136: throw new WorkflowRuntimeException(
137: "Caught exception generating exception request", e);
138: } finally {
139: performanceLogger
140: .log("Time to generate exception request.");
141: MDC.remove("docID");
142: }
143: }
144:
145: private Throwable unwrapRouteManagerExceptionIfPossible(
146: Throwable throwable) {
147: throwable = ExceptionUtils.unwrapActualCause(throwable);
148: if (throwable != null
149: && (!(throwable instanceof RouteManagerException))
150: && throwable.getCause() instanceof RouteManagerException) {
151: throwable = throwable.getCause();
152: }
153: return throwable;
154: }
155:
156: protected Throwable determineActualCause(Throwable throwable,
157: int depth) {
158: if (depth >= 10) {
159: return throwable;
160: }
161: if ((throwable instanceof InvocationTargetException)
162: || (throwable instanceof RouteManagerException)) {
163: if (throwable.getCause() != null) {
164: return determineActualCause(throwable.getCause(),
165: ++depth);
166: }
167: }
168: return throwable;
169: }
170: }
|