/** * Execute a workflow item, returns true if the item succeeds. This method will throw an exception * if the workflow item fails and the Workflow is has keepgoing==false. * * @param failedMap List to add any messages if the item fails * @param c index of the WF item * @param cmd WF item descriptor * @return true if the execution succeeds, false otherwise */ protected StepExecutionResult executeWFItem( final StepExecutionContext executionContext, final Map<Integer, StepExecutionResult> failedMap, final int c, final StepExecutionItem cmd) { if (null != executionContext.getExecutionListener()) { executionContext .getExecutionListener() .log(Constants.DEBUG_LEVEL, c + ": Workflow step executing: " + cmd); } StepExecutionResult result; try { result = framework .getExecutionService() .executeStep( ExecutionContextImpl.builder(executionContext).stepNumber(c).build(), cmd); if (!result.isSuccess()) { failedMap.put(c, result); } } catch (StepException e) { result = StepExecutionResultImpl.wrapStepException(e); failedMap.put(c, result); } if (null != executionContext.getExecutionListener()) { executionContext .getExecutionListener() .log(Constants.DEBUG_LEVEL, c + ": Workflow step finished, result: " + result); } return result; }
private StepExecutionContext replaceFailedNodesListenerInContext( StepExecutionContext executionContext, FailedNodesListener captureFailedNodesListener) { ExecutionListenerOverride listen = null; if (null != executionContext.getExecutionListener()) { listen = executionContext.getExecutionListener().createOverride(); } if (null != listen) { listen.setFailedNodesListener(captureFailedNodesListener); } return new ExecutionContextImpl.Builder(executionContext).executionListener(listen).build(); }
/** * Execute the sequence of ExecutionItems within the context, and with the given keepgoing value, * return true if successful */ protected boolean executeWorkflowItemsForNodeSet( final StepExecutionContext executionContext, final Map<Integer, StepExecutionResult> failedMap, final List<StepExecutionResult> resultList, final List<StepExecutionItem> iWorkflowCmdItems, final boolean keepgoing) { return executeWorkflowItemsForNodeSet( executionContext, failedMap, resultList, iWorkflowCmdItems, keepgoing, executionContext.getStepNumber()); }
/** * Execute the sequence of ExecutionItems within the context, and with the given keepgoing value, * return true if successful */ protected boolean executeWorkflowItemsForNodeSet( final StepExecutionContext executionContext, final Map<Integer, StepExecutionResult> failedMap, final List<StepExecutionResult> resultList, final List<StepExecutionItem> iWorkflowCmdItems, final boolean keepgoing, final int beginStepIndex) { boolean workflowsuccess = true; final WorkflowExecutionListener wlistener = getWorkflowListener(executionContext); int c = beginStepIndex; for (final StepExecutionItem cmd : iWorkflowCmdItems) { boolean stepSuccess = false; if (null != wlistener) { wlistener.beginWorkflowItem(c, cmd); } // wrap node failed listener (if any) and capture status results NodeRecorder stepCaptureFailedNodesListener = new NodeRecorder(); StepExecutionContext stepContext = replaceFailedNodesListenerInContext(executionContext, stepCaptureFailedNodesListener); Map<String, NodeStepResult> nodeFailures; // execute the step item, and store the results StepExecutionResult stepResult = null; Map<Integer, StepExecutionResult> stepFailedMap = new HashMap<Integer, StepExecutionResult>(); stepResult = executeWFItem(stepContext, stepFailedMap, c, cmd); stepSuccess = stepResult.isSuccess(); nodeFailures = stepCaptureFailedNodesListener.getFailedNodes(); if (null != executionContext.getExecutionListener() && null != executionContext.getExecutionListener().getFailedNodesListener()) { executionContext .getExecutionListener() .getFailedNodesListener() .matchedNodes(stepCaptureFailedNodesListener.getMatchedNodes()); } try { if (!stepSuccess && cmd instanceof HasFailureHandler) { final HasFailureHandler handles = (HasFailureHandler) cmd; final StepExecutionItem handler = handles.getFailureHandler(); if (null != handler) { // if there is a failure, and a failureHandler item, execute the failure handler // set keepgoing=false, and store the results // will throw an exception on failure because keepgoing=false NodeRecorder handlerCaptureFailedNodesListener = new NodeRecorder(); StepExecutionContext handlerExecContext = replaceFailedNodesListenerInContext( executionContext, handlerCaptureFailedNodesListener); // if multi-node, determine set of nodes to run handler on: (failed node list only) if (stepCaptureFailedNodesListener.getMatchedNodes().size() > 1) { HashSet<String> failedNodeList = new HashSet<String>(stepCaptureFailedNodesListener.getFailedNodes().keySet()); handlerExecContext = new ExecutionContextImpl.Builder(handlerExecContext) .nodeSelector(SelectorUtils.nodeList(failedNodeList)) .build(); } if (null != stepResult) { // add step failure data to data context handlerExecContext = addStepFailureContextData(stepResult, handlerExecContext); // extract node-specific failure and set as node-context data handlerExecContext = addNodeStepFailureContextData(stepResult, handlerExecContext); } Map<Integer, StepExecutionResult> handlerFailedMap = new HashMap<Integer, StepExecutionResult>(); StepExecutionResult handlerResult = executeWFItem(handlerExecContext, handlerFailedMap, c, handler); boolean handlerSuccess = handlerResult.isSuccess(); // handle success conditions: // 1. if keepgoing=true, then status from handler overrides original step // 2. keepgoing=false, then status is the same as the original step, unless // the keepgoingOnSuccess is set to true and the handler succeeded boolean useHandlerResults = keepgoing; if (!keepgoing && handlerSuccess && handler instanceof HandlerExecutionItem) { useHandlerResults = ((HandlerExecutionItem) handler).isKeepgoingOnSuccess(); } if (useHandlerResults) { stepSuccess = handlerSuccess; stepResult = handlerResult; stepFailedMap = handlerFailedMap; nodeFailures = handlerCaptureFailedNodesListener.getFailedNodes(); } } } } finally { if (null != wlistener) { wlistener.finishWorkflowItem(c, cmd); } } resultList.add(stepResult); failedMap.putAll(stepFailedMap); if (!stepSuccess) { workflowsuccess = false; } // report node failures based on results of step and handler run. if (null != executionContext.getExecutionListener() && null != executionContext.getExecutionListener().getFailedNodesListener()) { if (nodeFailures.size() > 0) { executionContext .getExecutionListener() .getFailedNodesListener() .nodesFailed(nodeFailures); } else if (workflowsuccess) { executionContext.getExecutionListener().getFailedNodesListener().nodesSucceeded(); } } if (!stepSuccess && !keepgoing) { break; } c++; } return workflowsuccess; }