Announcement Announcement Module
Collapse
No announcement yet.
Step Scope Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Step Scope

    The following is a job where a job parameters map is passed to a bean that is then passed to a tasklet. Both are in "step" scope. However, when running concurrent jobs, all tasklets are being set with the same bean.

    For example, in the tasklet, the job parameters derived from "execute(.. ChunkContext chunkContext)" fail to match the job parameters acquired through the property setter "setParametersBean".

    So, if Job Thread 1 has the job property "name"="valueForJob1", and Job Thread 2 has the property "name"="valueForJob2", both tasklets within each respective job are being passed a "ParameterBean" with the property "name"="valueForJob1". However, chunkContext.getStepContext().getJobParameters() resolves the correct value "valueForJob1" for the first thread and "valueForJob2" for the second thread.

    Code:
      <bean id="fooTasklet"
            class="FooTasklet scope="step">
        <property name="parametersBean" ref="parametersBean" />
      </bean>
      <bean id="parametersBean" scope="step">
        <constructor-arg value="#{jobParameters}" />
      </bean>
      <job id="job">
        <b:step id="step">
          <b:tasklet ref="fooTasklet" />
        </b:step>
      </job>
    Last edited by flipflop; Apr 23rd, 2010, 01:45 AM. Reason: Added another paragraph detailing the issue.

  • #2
    You need to put the scope step on your step.

    Comment


    • #3
      That makes sense but the schema doesn't seem to support it:

      org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'scope' is not allowed to appear in element 'b:step'

      Comment


      • #4
        forget it. Next time I'll grab a coffee first

        That being said, that does not solve your issue

        Comment


        • #5
          Sorry, I failed to mention a _really_ important detail, the step in question is a child of a partitioner.

          There appear to be two step contexts. One parent step context (the step controlling the partitioner) and a second step context, which is a child thread started/tasked by the partitioner. The child steps are launched individually and in parallel by the partitioner. When applying job parameters declaratively using the expression "#{jobParameters}", the map that's passed to each tasklet (again partitioned and in parallel) is the map initialized with the properties of the first partitioned tasklet. So, it seems the "step" scoped bean is stored in the parent step context but initialized with the properties of the first child step. I would have expected a bean solely in the parent step context without the granularity of the child step context--or, a bean initialized with the child step properties but not an incorrect combination of both.

          So, I assume there's no way to inject a child step with properties that are scoped for the respective partitioned step? In other words, where each partitioned step is supplied declaratively with a bean associated with its partition.

          Code:
            <b:job id="job">
              <b:step id="step" parent="abstractStep">
                <b:partition step="stepDelegate"
                    partitioner="partitioner">
                  <b:handler grid-size="10" task-executor="taskExecutor" />
                </b:partition>
              </b:step>
            </b:job>
          
            <bean id="partitioner" class="Partitioner" scope="step">
              <property name="jobParametersMap" value="#{jobParameters}" />
            </bean>
          
            <b:step id="stepDelegate">
              <b:tasklet ref="tasklet" />
            </b:step>
          
            <bean id="tasklet" class="Tasklet" scope="step">
              <property name="parametersBean" ref="parametersBean" />
            </bean>
          
            <bean id="parametersBean" class="ParametersBean" scope="step">
              <constructor-arg value="#{jobParameters}" />
            </bean>

          Comment


          • #6
            Given the way the step scope is implemented I don't see why it wouldn't work. Dave might give more input here.

            Comment


            • #7
              If the partitioner forks two partitions with "valueForJob1" in one parameter map and "valueForJob2" in the second parameter map, the job parameters passed through the setter of both tasklets (that's a member of stepDelegate) is definitely "valueForJob1."

              Again, as a workaround I'm programmatically extracting the job parameters from the ChunkContext object provided through the execute method to correctly derive valueForJob1 and valueForJob2 since I can't seem to get the property injection to work...

              Any help is appreciated.

              Comment


              • #8
                I think you are confusing JobParameters (which apply to the whole job execution, so it is unsurprising if all steps have the same value) and step execution context (which is provided by the partitioner). You probably meant to use #{stepExecutionContext} not #{jobParameters}

                Comment

                Working...
                X