org.apache.batchee.container.impl.controller.ExecutionTransitioner Maven / Gradle / Ivy
/*
* Copyright 2012 International Business Machines Corp.
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.batchee.container.impl.controller;
import org.apache.batchee.container.Controller;
import org.apache.batchee.container.ExecutionElementController;
import org.apache.batchee.container.exception.BatchContainerRuntimeException;
import org.apache.batchee.container.impl.JobContextImpl;
import org.apache.batchee.container.impl.StepContextImpl;
import org.apache.batchee.container.impl.jobinstance.RuntimeJobExecution;
import org.apache.batchee.container.jsl.ExecutionElement;
import org.apache.batchee.container.jsl.IllegalTransitionException;
import org.apache.batchee.container.jsl.Transition;
import org.apache.batchee.container.jsl.TransitionElement;
import org.apache.batchee.container.navigator.ModelNavigator;
import org.apache.batchee.container.services.BatchKernelService;
import org.apache.batchee.container.services.ServicesManager;
import org.apache.batchee.container.status.ExecutionStatus;
import org.apache.batchee.container.status.ExtendedBatchStatus;
import org.apache.batchee.container.util.PartitionDataWrapper;
import org.apache.batchee.jaxb.Decision;
import org.apache.batchee.jaxb.End;
import org.apache.batchee.jaxb.Fail;
import org.apache.batchee.jaxb.Flow;
import org.apache.batchee.jaxb.JSLJob;
import org.apache.batchee.jaxb.Split;
import org.apache.batchee.jaxb.Step;
import org.apache.batchee.jaxb.Stop;
import javax.batch.runtime.BatchStatus;
import java.util.List;
import java.util.concurrent.BlockingQueue;
public class ExecutionTransitioner {
private final ServicesManager manager;
private RuntimeJobExecution jobExecution;
private long rootJobExecutionId;
private ModelNavigator> modelNavigator;
// 'volatile' since it receives stop on separate thread.
private volatile ExecutionElementController currentStoppableElementController;
private ExecutionElementController previousElementController;
private ExecutionElement currentExecutionElement = null;
private ExecutionElement previousExecutionElement = null;
private JobContextImpl jobContext;
private BlockingQueue analyzerQueue = null;
private List stepExecIds;
private StepContextImpl parentStepContext;
public ExecutionTransitioner(final RuntimeJobExecution jobExecution, final long rootJobExecutionId, final ModelNavigator> modelNavigator,
final ServicesManager servicesManager) {
this.jobExecution = jobExecution;
this.rootJobExecutionId = rootJobExecutionId;
this.modelNavigator = modelNavigator;
this.jobContext = jobExecution.getJobContext();
this.manager = servicesManager;
}
public ExecutionTransitioner(final RuntimeJobExecution jobExecution, final long rootJobExecutionId,
final ModelNavigator jobNavigator, final BlockingQueue analyzerQueue,
final ServicesManager manager) {
this.jobExecution = jobExecution;
this.rootJobExecutionId = rootJobExecutionId;
this.modelNavigator = jobNavigator;
this.jobContext = jobExecution.getJobContext();
this.analyzerQueue = analyzerQueue;
this.manager = manager;
}
public ExecutionStatus doExecutionLoop() {
try {
currentExecutionElement = modelNavigator.getFirstExecutionElement(jobExecution.getRestartOn());
} catch (final IllegalTransitionException e) {
throw new IllegalArgumentException("Could not transition to first execution element within job.", e);
}
while (true) {
if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
}
final ExecutionElementController currentElementController = getNextElementController();
currentStoppableElementController = currentElementController;
if (BaseStepController.class.isInstance(currentElementController)) {
BaseStepController.class.cast(currentElementController).setParentStepContext(parentStepContext);
}
final ExecutionStatus status = currentElementController.execute();
// Nothing special for decision or step except to get exit status. For flow and split we want to bubble up though.
if ((currentExecutionElement instanceof Split) || (currentExecutionElement instanceof Flow)) {
// Exit status and restartOn should both be in the job context.
if (!status.getExtendedBatchStatus().equals(ExtendedBatchStatus.NORMAL_COMPLETION)) {
return status;
}
}
// Seems like this should only happen if an Error is thrown at the step level, since normally a step-level
// exception is caught and the fact that it was thrown capture in the ExecutionStatus
if (jobContext.getBatchStatus().equals(BatchStatus.FAILED)) {
throw new BatchContainerRuntimeException("Sub-execution returned its own BatchStatus of FAILED. Deal with this by throwing exception to the next layer.");
}
// set the execution element controller to null so we don't try to call stop on it after the element has finished executing
currentStoppableElementController = null;
if (jobContext.getBatchStatus().equals(BatchStatus.STOPPING)) {
return new ExecutionStatus(ExtendedBatchStatus.JOB_OPERATOR_STOPPING);
}
Transition nextTransition;
try {
nextTransition = modelNavigator.getNextTransition(currentExecutionElement, status);
} catch (final IllegalTransitionException e) {
throw new BatchContainerRuntimeException("Problem transitioning to next execution element.", e);
}
//
// We will find ourselves in one of four states now.
//
// 1. Finished transitioning after a normal execution, but nothing to do 'next'.
// 2. We just executed a step which through an exception, but didn't match a transition element.
// 3. We are going to 'next' to another execution element (and jump back to the top of this '
// 'while'-loop.
// 4. We matched a terminating transition element (, or getStepExecIds() {
return stepExecIds;
}
public void setParentStepContext(final StepContextImpl parentStepContext) {
this.parentStepContext = parentStepContext;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy