Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring批处理JSR-352重新启动错误的分区_Java_Spring_Spring Batch_Jsr - Fatal编程技术网

Java Spring批处理JSR-352重新启动错误的分区

Java Spring批处理JSR-352重新启动错误的分区,java,spring,spring-batch,jsr,Java,Spring,Spring Batch,Jsr,我使用SpringBatch JSR-352实现创建了一个简单的批处理。批处理使用PartitionMapper为每个区块注入单独的属性。 根据JSR-352规范(当partitionsOverride=False时),当一个分区块失败并且批重新启动时,只有失败的分区块应该重新启动 例如,如果我们有3个分区:分区0、分区1和分区2。 如果partition1和partition2失败,批处理只应使用其自己的批处理属性重新启动partition1和partition2 但是,我注意到,当使用Spr

我使用SpringBatch JSR-352实现创建了一个简单的批处理。批处理使用PartitionMapper为每个区块注入单独的属性。 根据JSR-352规范(当partitionsOverride=False时),当一个分区块失败并且批重新启动时,只有失败的分区块应该重新启动

例如,如果我们有3个分区:分区0、分区1和分区2。 如果partition1和partition2失败,批处理只应使用其自己的批处理属性重新启动partition1和partition2

但是,我注意到,当使用Spring批处理JSR-352实现(最新版本3.0.3.Release)时,重新启动批处理将重新启动partition0和partition1,而不是partition1和partition2。因此,它正确地检测到两个分区出现故障,但错误地重新启动了前(两)个分区,而不是应该重新启动的故障分区

这是Spring批处理实现中的错误还是我遗漏了什么

见JSR-352文件第10.8.5节:

以下是我使用的代码:

/META-INF/batch jobs/sampleBatch.xml

<?xml version="1.0" encoding="UTF-8"?>
<job id="sampleBatch" version="1.0" 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">

<step id="sampleStep">
    <chunk item-count="100">
        <reader ref="com.springapp.batch.SampleReader">
            <properties>
                <property name="sample" value="#{partitionPlan['sample']}"/>
            </properties>
        </reader>
        <writer ref="com.springapp.batch.SampleWriter">
            <properties>
                <property name="sample" value="#{partitionPlan['sample']}"/>
            </properties>
        </writer>
    </chunk>
    <partition>
        <mapper ref="com.springapp.batch.SamplePartitionMapper"/>
    </partition>
</step>
</job>

com.springapp.batch.SamplePartitionMapper:

package com.springapp.batch;

import java.util.Properties;
import javax.batch.api.partition.PartitionMapper;
import javax.batch.api.partition.PartitionPlan;
import javax.batch.api.partition.PartitionPlanImpl;

public class SamplePartitionMapper implements PartitionMapper {

@Override
public PartitionPlan mapPartitions() throws Exception {
    final PartitionPlan partitionPlan = new PartitionPlanImpl();

    int size = 3;
    Properties[] partitionProps = new Properties[size];

    for (int i=0; i<size; i++) {
        final Properties properties = new Properties();
        properties.put("sample", ""+i);
        partitionProps[i] = properties;
        System.out.println("mapPartitions: " + i);
    }

    partitionPlan.setThreads(1);
    partitionPlan.setPartitions(partitionProps.length);
    partitionPlan.setPartitionProperties(partitionProps);

    return partitionPlan;
}
}
package com.springapp.batch;
导入java.util.Properties;
导入javax.batch.api.partition.PartitionMapper;
导入javax.batch.api.partition.PartitionPlan;
导入javax.batch.api.partition.PartitionPlanImpl;
公共类SamplePartitionMapper实现PartitionMapper{
@凌驾
public PartitionPlan mapPartitions()引发异常{
final PartitionPlan PartitionPlan=新的PartitionPlanImpl();
int size=3;
Properties[]partitionProps=新属性[大小];

对于(inti=0;i来看,它看起来像一个bug。我已经记录了Jira问题来跟踪它

public class SampleReader extends AbstractItemReader {

@Inject
@BatchProperty
private String sample;

Iterator<Integer> iter;

@Override
public void open(Serializable checkpoint) throws Exception {
    System.out.println("open for reading sample: " + sample);
    ArrayList list = new ArrayList<Integer>();
    for(int i=0; i<Integer.parseInt(sample); i++) {
        list.add(new Integer(i));
    }
    iter = list.iterator();
}

@Override
public Integer readItem() throws Exception {
    if(iter.hasNext())
        return iter.next();
    else
        return null;
}
}
public class SampleWriter extends AbstractItemWriter {

@Inject
@BatchProperty
private String sample;

@Override
public void writeItems(List<Object> items) throws Exception {
    System.out.println("writeItems sample: " + sample);

    if(sample.equals("1")) {
        throw new Exception("FAIL PARTITION 1");
    }
    if(sample.equals("2")) {
        throw new Exception("FAIL PARTITION 2");
    }

    for (Object itemObj : items) {
        Integer item = (Integer) itemObj;
        System.out.println(item);
    }
}
}
package com.springapp.batch;

import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.batch.operations.JobOperator;
import javax.batch.runtime.BatchRuntime;
import javax.batch.runtime.JobExecution;
import javax.inject.Inject;

import junit.framework.Assert;
import org.junit.Test;

//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:spring-config.xml")
public class AppTests {

@Test
public void testJob() throws Exception {
    JobOperator jobOperator = BatchRuntime.getJobOperator();
    long jobExecution = jobOperator.start("sampleBatch", new Properties());

    int attempt = 0;
    while (true) {
        JobExecution execution = jobOperator.getJobExecution(jobExecution);
        if (execution.getEndTime() != null) {
            //check status
            if( "FAILED".equals(execution.getExitStatus()) && attempt < 3 ) {
                attempt++;
                System.out.println("Batch failed, trying to restart (attempt " + attempt + ")..");
                jobExecution = jobOperator.restart(jobExecution,  new Properties());
                continue;
            }
            System.out.println("Batch ended with status: " + execution.getExitStatus());
            break;
        }
    }
    Assert.assertEquals("COMPLETED", jobOperator.getJobExecution(jobExecution).getExitStatus());
}
}