1

JSR 352 Batch API で次のロジックを実現する方法はありますか? ジョブの開始時にわかっているさまざまな条件に基づいて、それぞれを実行する必要がある一連のステップがあります。ConditionsEntity は、外部システムによって提供されます。

public List<Steps> createStepSequence(ConditionsEntity conditions) {
  if (conditions.isStep1Enabled()) {
    steps.add(step1)
  }
  if (conditions.isStep2Enabled()) {
    steps.add(step2)
  }
  if (conditions.isStep3Enabled()) {
    steps.add(step3)
  }
  //many more ifs

return steps;
}

com.ibm.jbatch.container.exception.BatchContainerRuntimeException: 決定は別の決定より前に行うことはできません。ここにFAILINGコードを追加しています

<?xml version="1.0" encoding="UTF-8"?>
<job id="myJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd" version="1.0">
    <properties>
        <property name="isExecuteStep2" value="false"/>
        <property name="isExecuteStep3" value="false"/>
    </properties>
    <step id="step1" next="decider1">
        <batchlet ref="myBatchlet1"/>
    </step>
    <decision id="decider1" ref="SkipNextStepDecider">
        <properties>
            <property name="isExecuteNextStep" value="#{jobProperties['isExecuteStep2']}"/>
        </properties>
        <next on="EXECUTE" to="step2"/>
        <next on="SKIP" to="decider2"/>
    </decision>
    <step id="step2">
        <batchlet ref="myBatchlet2"/>
    </step>
    <decision id="decider2" ref="SkipNextStepDecider">
        <properties>
            <property name="isExecuteNextStep" value="#{jobProperties['isExecuteStep3']}"/>
        </properties>
        <next on="EXECUTE" to="step3"/>
        <end on="SKIP"/>
    </decision>
    <step id="step3">
        <batchlet ref="myBatchlet3"/>
    </step>
</job>


@Named
public class SkipNextStepDecider implements Decider {

    @Inject
    @BatchProperty
    private String isExecuteNextStep;

    @Override
    public String decide(StepExecution[] ses) throws Exception {
        if (isExecuteNextStep.equalsIgnoreCase("true")) {
            return "EXECUTE";
        } else {
            return "SKIP";
        }
    }
}

更新 passThroughStep を使用して、次の提案されたソリューションを実装しました。正しく動作していますが、このコードの重複をすべて回避できるようにしたいと思っています。

<?xml version="1.0" encoding="UTF-8"?>
<job id="decisionpoc" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <step id="dummy0" next="decider1">
        <batchlet ref="dummyBatchlet"/>
    </step>
    <decision id="decider1" ref="skipNextStepDecider">
        <properties>
            <property name="condition" value="isExecuteStep1"/>
        </properties>
        <next on="EXECUTE" to="step1"/>
        <next on="SKIP" to="dummy1"/>
    </decision>
    <step id="step1" next="decider2">
        <batchlet ref="myBatchlet1"/>
    </step>
    <step id="dummy1" next="decider2">
        <batchlet ref="dummyBatchlet"/>
    </step>
    <decision id="decider2" ref="skipNextStepDecider">
        <properties>
            <property name="condition" value="isExecuteStep2"/>
        </properties>
        <next on="EXECUTE" to="step2"/>
        <next on="SKIP" to="dummy2"/>
    </decision>
    <step id="step2">
        <batchlet ref="myBatchlet2"/>
    </step>
    <step id="dummy2" next="decider3">
        <batchlet ref="dummyBatchlet"/>
    </step>
    <decision id="decider3" ref="skipNextStepDecider">
        <properties>
            <property name="condition" value="isExecuteStep3"/>
        </properties>
        <next on="EXECUTE" to="step3"/>
        <end on="SKIP"/>
    </decision>
    <step id="step3">
        <batchlet ref="myBatchlet3"/>
    </step>
</job>

決定者

@Named
public class SkipNextStepDecider implements Decider {

    @Inject
    @BatchProperty
    private String condition;

    @Inject
    private JobContext jobContext;

    @Override
    public String decide(StepExecution[] ses) throws Exception {
        Properties parameters = getParameters();
        String isExecuteNextStep = parameters.getProperty(condition);
        if (isExecuteNextStep.equalsIgnoreCase("true")) {
            return "EXECUTE";
        } else {
            return "SKIP";
        }
    }

    private Properties getParameters() {
        JobOperator operator = getJobOperator();
        return operator.getParameters(jobContext.getExecutionId());

    }
}

私のテスト

public class DecisionPOCTest extends AbstractBatchLOT {

    @Test
    public void testProcess() throws Exception {
        JobOperator jobOperator = getJobOperator();
        Properties properties = new Properties();
        properties.setProperty("isExecuteStep1", "true");
        properties.setProperty("isExecuteStep2", "false");
        properties.setProperty("isExecuteStep3", "true");
        Long executionId = jobOperator.start("poc/decisionPOC", properties);
        JobExecution jobExecution = jobOperator.getJobExecution(executionId);

        jobExecution = BatchTestHelper.keepTestAlive(jobExecution);


        List<StepExecution> stepExecutions = jobOperator.getStepExecutions(executionId);
        List<String> executedSteps = new ArrayList<>();
        for (StepExecution stepExecution : stepExecutions) {
            executedSteps.add(stepExecution.getStepName());
        }

        assertEquals(COMPLETED, jobExecution.getBatchStatus());
        assertEquals(4, stepExecutions.size());
        assertArrayEquals(new String[]{"dummy0", "step1", "dummy2", "step3"}, executedSteps.toArray());
        assertFalse(executedSteps.contains("step2"));
    }
}
4

4 に答える 4

1

@chengには、あなたがしていることからの非常に小さな変更である良い答えがあります(基本的には、決定者をバッチレットに変更するだけです)。

少なくとも私にとっては、仕様がここで提供する他のオプションを検討することは興味深い質問です。もう 1 つの方法は、すべての "isExecuteStepNN" props が注入された Decider を使用して単一の決定を行うことで、各ステップの後に呼び出すことができます。その Decider には StepExecution が渡されるため、前のステップが何であるかがわかります。それを「isExecute...」小道具と組み合わせて、Decider が次に実行するステップの ID を返すようにすることができます。

それは賢いかもしれませんが、チェンの答えはより簡単な回避策だと思います。また、仕様はこれを許可することを検討する必要があると思います。おそらく、これをサポートしない理由は、「どの StepExecution を決定メソッドに渡す必要があるか?」という質問への回答を避けるためです。これは解決可能と思われます。

于 2019-12-04T14:13:54.180 に答える