How to configure a Spring batch job with single reader and calling multiple writers depending on object returned

核能气质少年 提交于 2019-12-07 17:01:14

问题


Below is the job file currently i'm using.

<batch:job id="job1">
    <batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="reader" processor="processor" writer="ItemWriter" commit-interval="3">
            </batch:chunk>
        </batch:tasklet>
    </batch:step>
</batch:job>

回答1:


As was said in the Luca's comment, you can use a ClassifierCompositeItemWriter which needs a org.springframework.classify.Classifier.

One of the few implementations of the latter is org.springframework.classify.BackToBackPatternClassifier which takes in turn a routerDelegate and a matcherMap.

The routerDelegate is a bean which will have a method annotated with @Classifier. This method will take an Object and return a String. This string will then be matched against the values you declare in your module-context, and call an ItemWriter accordingly.

Here's an example :

<bean class="org.springframework.batch.item.support.ClassifierCompositeItemWriter">
    <property name="classifier">
        <bean class="org.springframework.classify.BackToBackPatternClassifier">
            <property name="routerDelegate">
                <bean class="xx.xx.xx.YourClassifier"></bean>
            </property>
            <property name="matcherMap">
                <map>
                    <entry key="value1">
                        <bean class="xx.xx.xx.YourItemWriter1></bean>
                    </entry>
                    <entry key="value2">
                        <bean class="xx.xx.xx.YourItemWriter2></bean>
                    </entry>
                </map>
            </property>
        </bean>
    </property>
</bean>

And here's what a Classifier looks like (this one is a Generic classifier using Reflect API to call a method passed as an argument on an object) :

public class GenericClassifier<T> {

    private String methodName;

    @Classifier
    public String classify(T classifiable) {

        Method method;
        String value = "";

        try {
            // Get the method with Reflect
            method = classifiable.getClass().getMethod(methodName);

            // Call the method with Reflect
            value= (String) method.invoke(classifiable);
        } catch (Exception e) {
            // Error management
        }

        return value;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
}

This classifier is used this way, where YourMethod is a public method of the class of the Object to be classified (without the parenthesis) :

<bean class="xx.xx.xx.GenericClassifier">
    <property name="methodName" value="YourMethod"></property>
</bean>

The value String returned by the Classifier is then matched with the key of the according entry of the matcherMap.




回答2:


Forgot to add solution that I found. Below solution worked for me. Compiled the Code and it's working fine.

First, you will need a Classifier. Either implement the Classifier interface or annotate classify() method with @Classifier.

Here I have used annotation.

public class MyClassifier 
{ 
  @Classifier public String classify(Policy pol)
  { 
    return pol.getPolCode;// returns "01", "02" 
  } 
}

Add a Classifier bean

<bean id="myClassifier" class="org.springframework.batch.classify.BackToBackPatternClassifier">
   <property name="routerDelegate"> 
     <bean class="MyClassifier" /> 
   </property> 
   <property name="matcherMap"> 
     <map> 
       <entry key="01" value-ref="pol01ItemWriter" /> 
       <entry key="02" value-ref="pol02ItemWriter" />
     </map>
   </property>
</bean>

Add your writer bean as like below

<bean id="ItemWriter" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter">
   <property name="myClassifier" ref="myClassifier" /> 
</bean>

The Above Code may throw WriterNotOpenException. For this you need to add batch:stream to the step.

<batch:step id="step1">
  <batch:tasklet> 
    <batch:chunk reader="reader" processor="processor" writer="ItemWriter" commit-interval="3">
      <batch:streams> 
        <batch:stream ref="pol01ItemWriter"/>
        <batch:stream ref="pol02ItemWriter"/>
      </batch:streams>
    </batch:chunk>
  </batch:tasklet>
</batch:step>


来源:https://stackoverflow.com/questions/33330171/how-to-configure-a-spring-batch-job-with-single-reader-and-calling-multiple-writ

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!