2

SpringBatchジョブのステップ間でデータを渡す方法に精通しています。しかし、あなたの仕事が多くの小さな仕事で構成されている場合はどうなりますか?以下の例では、最初のジョブsiNotificationJobの最後にあるJobExecutionContextにいくつかのデータを設定したいと思います。次に、そのデータは、次のジョブciNotificationJobのStepExecutionContextのJobExecutionContextから読み取ることができます。このデータを何らかの方法で宣伝する必要がありますか?ジョブパラメータの設定に使用するステップ「ciNotificationJob」で定義されたジョブパラメータエクストラクタに結果が表示されないようです。

考え?

アンドリュー

    <job id="notificationJob" xmlns="http://www.springframework.org/schema/batch">

    <batch:step id="pn_step_0" next="pn-step-1">
        <batch:job ref="siNotificationJob" job-launcher="jobLauncher" 
            job-parameters-extractor="jobParamsExtractor"/>
    </batch:step>       
    <batch:step id="pn-step-1" next="pn-step-2">
        <batch:job ref="ciNotificationJob" job-launcher="jobLauncher" 
            job-parameters-extractor="jobParamsExtractor"/>
    </batch:step>           
</job>
4

2 に答える 2

2

私はこれを解決することができました。私がどのようにそれを解決したかを例を通してお見せします。複雑でしたが、結果はかなりわかりやすいと思います。

「notificationJob」という全体的なジョブが1つあります。3つの異なるジョブ(ステップではない)を呼び出す3つのステップがあります。これらの各ジョブは、独立して実行することも、トップレベルの「notificationJob」内から呼び出すこともできます。また、各サブジョブには多くのステップがあります。ここではこれらすべてのステップを示すつもりはありませんが、これらはより多くのステップを備えた完全なジョブそのものであることを強調したいと思います。

    <job id="notificationJob" xmlns="http://www.springframework.org/schema/batch">
    <batch:listeners>
        <batch:listener ref="pn_job-parent-listener" />
    </batch:listeners>
    <batch:step id="pn_step-0" next="pn-step-1">
        <batch:job ref="siNotificationJob" job-launcher="jobLauncher" 
            job-parameters-extractor="futureSiParamsExtractor"/>
    </batch:step>
    <batch:step id="pn-step-1" next="pn-step-2">
        <batch:job ref="ciNotificationJob" job-launcher="jobLauncher" 
            job-parameters-extractor="futureCiParamsExtractor"/>
    </batch:step>
    <batch:step id="pn-step-2">
        <batch:job ref="combineResultsJob" job-launcher="jobLauncher" 
            job-parameters-extractor="jobParamsExtractor"/>
    </batch:step>           
</job>

重要なのは、あるジョブから結果を抽出し、次のジョブでそれらを読み取ることができることです。今、あなたはこれを複数の方法で行うことができます。1つの方法は、あるジョブの結果をDBまたはテキストファイルに出力してから、次のジョブをそのファイル/テーブルから読み取ることです。それほど多くのデータを扱っていなかったので、メモリ内で情報を渡しました。したがって、job-parameter-extractorsに気付くでしょう。パラメータエクストラクタの組み込み実装に依存することも、独自の実装を実装することもできます。私は実際に両方を使用しています。StepExecutionから値を抽出するだけで、次のサブジョブに昇格/移動する必要があります。

    <bean id="jobParamsExtractor" class="org.springframework.batch.core.step.job.DefaultJobParametersExtractor">
    <property name="keys">
        <list>
            <value>OUTPUT</value>
        </list>
    </property>
</bean>

<bean id="futureSiParamsExtractor" class="jobs.SlideDatesParamExtractor">
    <property name="mode" value="FORWARD" />
    <property name="addedParams">
        <map><entry>
                <key><value>outputName</value></key>
                <value>FUTURE_SI_JOB_RESULTS</value>
            </entry></map>
    </property>
</bean> 

<bean id="futureCiParamsExtractor" class="jobs.SlideDatesParamExtractor">
    <property name="mode" value="FORWARD" />
    <property name="addedParams">
        <map><entry>
                <key><value>outputName</value></key>
                <value>FUTURE_CI_JOB_RESULTS</value>
            </entry></map>
    </property>
</bean>

最後に、親ジョブリスナーがあることに気付くでしょう。これは、あるジョブから状態を転送し、次のジョブで使用できるようにする魔法です。これがそれを行うクラスの私の実装です。

    <bean id="pn_job-state-listener" class="jobs.JobStateListener">
    <property name="parentJobListener" ref="pn_job-parent-listener" />
</bean> 

<bean id="pn_job-parent-listener" class="cjobs.ParentJobListener">
</bean>

package jobs.permnotification;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

public class ParentJobListener implements JobExecutionListener
{

    private JobExecution parentExecution;

    @Override
    public void beforeJob(JobExecution jobExecution)
    {
        this.parentExecution = jobExecution;
    }

    @Override
    public void afterJob(JobExecution jobExecution)
    {
        // TODO Auto-generated method stub

    }

    public void setParentExecution(JobExecution parentExecution)
    {
        this.parentExecution = parentExecution;
    }

    public JobExecution getParentExecution()
    {
    return parentExecution;
    }

}


package jobs.permnotification;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

public class JobStateListener implements JobExecutionListener
{
    private ParentJobListener parentJobListener;


    @Override
    public void beforeJob(JobExecution jobExecution)
    {
        if(parentJobListener == null || parentJobListener.getParentExecution() == null) return;
        passStateFromParentToJob(StepKey.FUTURE_SI_JOB_RESULTS.toString(), jobExecution);
        passStateFromParentToJob(StepKey.FUTURE_CI_JOB_RESULTS.toString(), jobExecution);
        passStateFromParentToJob(StepKey.OUTPUT.toString(), jobExecution);
    }

    @Override
    public void afterJob(JobExecution jobExecution)
    {
        if(parentJobListener == null || parentJobListener.getParentExecution() == null) return;
        //take state from child step and move it into the parent execution context
        passStateFromJobToParent(StepKey.FUTURE_SI_JOB_RESULTS.toString(), jobExecution);
        passStateFromJobToParent(StepKey.FUTURE_CI_JOB_RESULTS.toString(), jobExecution);
        passStateFromJobToParent(StepKey.OUTPUT.toString(), jobExecution);
    }

    private void passStateFromJobToParent(String key, JobExecution jobExecution)
    {
        Object obj = jobExecution.getExecutionContext().get(key);
        if(obj != null)
            parentJobListener.getParentExecution().getExecutionContext().put(key, obj);
    }

    private void passStateFromParentToJob(String key, JobExecution jobExecution)
    {
        Object obj = parentJobListener.getParentExecution().getExecutionContext().get(key);
        if(obj != null)
            jobExecution.getExecutionContext().put(key, obj);
    }

    public void setParentJobListener(ParentJobListener parentJobListener)
    {
        this.parentJobListener = parentJobListener;
    }

    public ParentJobListener getParentJobListener()
    {
        return parentJobListener;
    }

}
于 2014-05-09T19:00:25.390 に答える
0

これは一種のハックです....代わりにスプリング統合を使用することをお勧めします..しかし、これがあなたの状況に当てはまるかどうかを確認してください。

Spring Batchメタデータテーブルを設定している場合、テーブルに最新のジョブ実行をクエリすると、各ジョブ内で生成されたデータを取得できる可能性があります。ジョブ実行コンテキスト内のすべてのデータが保存され、クエリを実行できます。

SpringBatchメタテーブル

于 2012-10-15T19:53:48.283 に答える