All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.jbatch.container.impl.PartitionedStepBuilder Maven / Gradle / Ivy

The newest version!
/*
 * 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 com.ibm.jbatch.container.impl;

import jakarta.batch.runtime.context.JobContext;

import com.ibm.jbatch.container.context.impl.JobContextImpl;
import com.ibm.jbatch.container.context.impl.StepContextImpl;
import com.ibm.jbatch.container.jsl.CloneUtility;
import com.ibm.jbatch.jsl.model.Flow;
import com.ibm.jbatch.jsl.model.JSLJob;
import com.ibm.jbatch.jsl.model.JSLProperties;
import com.ibm.jbatch.jsl.model.ObjectFactory;
import com.ibm.jbatch.jsl.model.Partition;
import com.ibm.jbatch.jsl.model.PartitionPlan;
import com.ibm.jbatch.jsl.model.Property;
import com.ibm.jbatch.jsl.model.Split;
import com.ibm.jbatch.jsl.model.Step;

public class PartitionedStepBuilder {

	public static final String JOB_ID_SEPARATOR = ":";  // Use something permissible in NCName to allow us to key off of.
    /*
     * Build a generated job with only one flow in it to submit to the
     * BatchKernel. This is used to build subjobs from splits.
     * 
     */
    public static JSLJob buildFlowInSplitSubJob(JobContextImpl jobContext, Split split, Flow flow) {

        ObjectFactory jslFactory = new ObjectFactory();
        JSLJob subJob = jslFactory.createJSLJob();

        // Uses the true top-level job instance id, not an internal "subjob" id.
        String subJobId = generateSubJobId(jobContext.getInstanceId(), split.getId(), flow.getId());
        subJob.setId(subJobId);
        
        
        //Copy all properties from parent JobContext to flow threads
        subJob.setProperties(CloneUtility.javaPropsTojslProperties(jobContext.getProperties()));

        //We don't need to do a deep copy here since each flow is already independent of all others, unlike in a partition
        //where one step instance can be executed with different properties on multiple threads.

        subJob.getExecutionElements().add(flow);
        
        jobContext.addTopLevelContextProperties(subJob.getProperties());

        return subJob;
    }
	


    /*
     * Build a generated job with only one step in it to submit to the
     * BatchKernel. This is used for partitioned steps.
     * 
     */
    public static JSLJob buildPartitionSubJob(JobContextImpl jobContext, StepContextImpl stepCtx, Step step, int partitionInstance) {

        ObjectFactory jslFactory = new ObjectFactory();
        JSLJob subJob = jslFactory.createJSLJob();
        

        // Set the generated subjob id
        // Uses the true top-level job instance id, not an internal "subjob" id.
        String subJobId = generateSubJobId(jobContext.getInstanceId(), step.getId(), partitionInstance);
        subJob.setId(subJobId);
        
        
        //Copy all properties from parent JobContext to partitioned step threads
        subJob.setProperties(CloneUtility.javaPropsTojslProperties(jobContext.getProperties()));

        // Add one step to job
        Step newStep = jslFactory.createStep();
        
        //set id
        newStep.setId(step.getId());

        
        /***
         * deep copy all fields in a step
         */
        newStep.setAllowStartIfComplete(step.getAllowStartIfComplete());
        
        if (step.getBatchlet() != null){
        	newStep.setBatchlet(CloneUtility.cloneBatchlet(step.getBatchlet()));
        }
        
        if (step.getChunk() != null) {
        	newStep.setChunk(CloneUtility.cloneChunk(step.getChunk()));
        }
        
        // Do not copy next attribute and control elements.  Transitioning should ONLY
        // take place on the main thread.
        
        //Do not add step listeners, only call them on parent thread.

        //Add partition artifacts and set instances to 1 as the base case 
        Partition partition = step.getPartition();
        if (partition != null) {
        	if (partition.getCollector() != null) {
        		
        		Partition basePartition = jslFactory.createPartition();
        		
        		PartitionPlan partitionPlan = jslFactory.createPartitionPlan();
        		partitionPlan.setPartitions(null);
        		basePartition.setPlan(partitionPlan);
        		
        		basePartition.setCollector(partition.getCollector());
        		newStep.setPartition(basePartition);
                	
        	}
        }
        
        newStep.setStartLimit(step.getStartLimit());
        JSLProperties newProperties = CloneUtility.cloneJSLProperties(step.getProperties());

        // 
        // Propagate StepContext info.  Note that unlike the JobContext info, this is
        // propagated for partitions, but NOT split-flows, since only for a partition
        // is a step split up across threads.
        // 
        if (newProperties == null) {
        	newProperties = jslFactory.createJSLProperties();
        }

		Property jobName = jslFactory.createProperty();
		jobName.setName(StepContextImpl.TOP_LEVEL_STEP_EXECUTION_ID_PROP);
		// No such thing as a partition of a partition so internal and "external" execution IDs are identical here.
		jobName.setValue(String.valueOf(stepCtx.getInternalStepExecutionId()));  
		newProperties.getPropertyList().add(jobName);
		
		// Link back to Step object
        newStep.setProperties(newProperties);
        
        // Don't try to only clone based on type (e.g. ChunkListener vs. StepListener).
        // We don't know the type at the model level, and a given artifact could implement more
        // than one listener interface (e.g. ChunkListener AND StepListener).
        newStep.setListeners(CloneUtility.cloneListeners(step.getListeners()));       
        
        //Add Step properties, need to be careful here to remember the right precedence
        
        subJob.getExecutionElements().add(newStep);

        // Propagate JobContext info
        jobContext.addTopLevelContextProperties(subJob.getProperties());
        
        return subJob;
    }

    /**
     * @param parentJobInstanceId
     *            the execution id of the parent job
     * @param splitId this is the split id where the flows are nested    
     * @param flowId
     *            this is the id of the partitioned control element, it can be a
     *            step id or flow id
     * @param partitionInstance
     *            the instance number of the partitioned element
     * @return a String of the form
     *         :::
     */
    private static String generateSubJobId(Long parentJobInstanceId, String splitId, String flowId) {

        StringBuilder strBuilder = new StringBuilder(JOB_ID_SEPARATOR);
        strBuilder.append(parentJobInstanceId.toString());
        strBuilder.append(JOB_ID_SEPARATOR);
        strBuilder.append(splitId);
        strBuilder.append(JOB_ID_SEPARATOR);
        strBuilder.append(flowId);

        return strBuilder.toString();
    }
    
    /**
     * @param parentJobInstanceId
     *            the execution id of the parent job
     * @param stepId
     *            this is the id of the partitioned control element, it can be a
     *            step id or flow id
     * @param partitionInstance
     *            the instance number of the partitioned element
     * @return a String of the form
     *         ::
     */
    private static String generateSubJobId(Long parentJobInstanceId, String stepId, int partitionInstance) {

        StringBuilder strBuilder = new StringBuilder(JOB_ID_SEPARATOR);
        strBuilder.append(parentJobInstanceId.toString());
        strBuilder.append(JOB_ID_SEPARATOR);
        strBuilder.append(stepId);
        strBuilder.append(JOB_ID_SEPARATOR);
        strBuilder.append(partitionInstance);

        return strBuilder.toString();
    }
    
    

    
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy