Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accesing JobContext from a partitioned step in JSR 352

I'm trying to pass an object between batchlets, but I've encountered a problem when trying to access the jobContext from a partitioned step (batchlet).

According to the JSR 352 Specification

9.4.1.1 Batch Context Lifecycle and Scope: A batch context has thread affinity and is visible only to the batch artifacts executing on that particular thread. A batch context injected field may be null when out of scope. Each context type has a distinct scope and lifecycle as follows: 1. JobContext There is one JobContext per job execution. It exists for the life of a job. There is a distinct JobContext for each sub-thread of a parallel execution (e.g. partitioned step). 2. StepContext There is one StepContext per step execution. It exists for the life of the step. For a partitioned step, there is one StepContext for the parent step/thread; there is a distinct StepContext for each sub-thread.

My (failed) solution was to use the JobContext.setTransientUserData, but because the partitioned step uses a distinct JobContext I can't get the TransientUserData.

Is there an alternative to what I'm trying to do? Using PartitionMapper properties it's not possible because I need to pass an object, not a string to every partition.

To be clear, I need to do this:

  1. NormalBatchlet -> Save an object to be used in the next step.
  2. PartitionedBatchlet -> Obtain the saved object in previous step. This object isn't a simple String so using PartitionMapper properties is not a solution.

UPDATE

I'm now using a simple Singleton EJB with a HashMap to store objects between steps and when the job is finished I clear this map to avoid resources leak.

This is a workaround because I really want to use only the javax.batch package and not depend on EJB's, so I'm not putting it as an answer.

like image 662
Pablo Andrés Martínez Vargas Avatar asked Mar 10 '14 16:03

Pablo Andrés Martínez Vargas


2 Answers

You could try something like this which should conform with the current spec programming model.

Store the object from your first step using the persistent step data in your NormalBatchlet:

stepCtx.setPersistentUserData(mySerializableData);

Retrieve the data from the first step in your partitions, by looking up the previous step:

Long execId = jobCtx.getExecutionId();

List<StepExecution> stepExecs = jobOperator.getStepExecutions(execID);

MyPersistentUserData myData;

for (StepExecution step : stepExecs) {
    if (step.getStepName().equals("somePreviousStepX") {
        myData = (MyPersistentUserData)step.getPersistentUserData();
    }
}

//use myData
like image 157
Kaushik Mukherjee Avatar answered Oct 13 '22 17:10

Kaushik Mukherjee


There is not a spec-defined way to share the transient user data between the JobContext of the main thread and the partition-level JobContext(s). This is an understandable point of confusion, but this is indeed the intended design.

like image 30
Scott Kurz Avatar answered Oct 13 '22 18:10

Scott Kurz