2

所以我正在创建我的第一个 Spring 批处理作业。我正在尝试读取 xml,操作一些值并将其写出来。如果我不实现 org.springframework.batch.item.ItemProcessor 接口,我的工作似乎可以解组我的 XML 文档并将其写出来。一旦我实现了为了操作值而需要执行的接口,我会收到以下错误。当我检查输出文件时,它输出 xml 标记、起始根元素标记,仅此而已。如果我在工作的第 1 步中注释掉对处理器的调用,则该文件将写入我的文件目录。任何帮助将不胜感激,我一直在寻找解决方法,但没有任何运气。我的消息针对多个大型 xsd 进行验证,因此我将它们排除在代码之外。

2018-05-21 15:58:57.690 错误 6684 --- [main] osbatch.core.step.AbstractStep:在作业 importUserJob java.lang.ClassCastException 中执行步骤 1 时遇到错误:javax.xml.bind.JAXBElement 不能转换为 [mySchema] BatchProcessor.process(BatchProcessor.java:1) ~[classes/:na]

public class BatchProcessor implements ItemProcessor<ProdRequest, ProdRequest>{

@Override
public ProdRequest process(ProdRequest arg0) throws Exception {
    //Error still thrown even when I comment out all of the code. Break points in this methoda re never reached.
    return arg0;
}

}

-

@Configuration
@EnableBatchProcessing
public class XMLReaderConfiguration {

@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;





@Bean
public BatchProcessor processor() {
    return new BatchProcessor();
}

@Bean(destroyMethod="")
public StaxEventItemReader<ProdRequest> reader(){
    StaxEventItemReader<ProdRequest> reader = new StaxEventItemReader<>();
    reader.setResource(new ClassPathResource("policy.xml"));
    reader.setFragmentRootElementName("ProdRequest");

    Jaxb2Marshaller xmlMarshaller = new Jaxb2Marshaller();

    ObjectFactory objectFactory = new ObjectFactory();


    xmlMarshaller.setClassesToBeBound(new Class[] { 
            //all of my object classes (all generated by JAXB) I have added the xmlRootElement attribute to my top level class only.
           });

    xmlMarshaller.setSupportJaxbElementClass(true);



    reader.setUnmarshaller(xmlMarshaller);



    return reader;
}

@Bean(destroyMethod="")
public StaxEventItemWriter<ProdRequest> writer(){
    StaxEventItemWriter<ProdRequest> writer = new StaxEventItemWriter<ProdRequest>();
    String exportFilePath = "C:/Test/springBatchTest.xml";
    writer.setResource(new FileSystemResource(exportFilePath));
    writer.setRootTagName("ProdRequest");

    Jaxb2Marshaller xmlMarshaller = new Jaxb2Marshaller();

    xmlMarshaller.setClassesToBeBound(new Class[] { 
            //all of my object classes (all generated by JAXB) I have added the xmlRootElement attribute to my top level class only.
           });

    xmlMarshaller.setSupportJaxbElementClass(true); 
    writer.setMarshaller(xmlMarshaller);
    return writer;
}

@Bean
public Step step1(){
    return stepBuilderFactory.get("step1")
            .<ProdRequest, ProdRequest> chunk(10)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
}


@Bean
public Job importUserJob(){
    return jobBuilderFactory.get("importUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();               
}
}
4

1 回答 1

1

所以最终我在 spring 框架中设置了一个断点,发现在我的文档被解组后,它实际上返回了一个包含我期望的文档的通用 JAXBElement。当该 JAXBElement 被传递给实现 Spring ItemProcessor 的 BatchProcessor 类时,由于我的类不希望文档位于 JAXBElement 内,因此引发了错误。所以为了解决这个问题,我必须将 BatchProcessor 的参数更改为 JAXBElement。我的修复如下。我删除了一些公司特定名称和我的 JAXBClasses 列表。希望这对未来的人有所帮助。谢谢!

public class BatchProcessor implements ItemProcessor<JAXBElement<ProdRequest> , ProdRequest>{

@Override
public ProdRequest process(JAXBElement<ProdRequest>  jaxbElement) throws Exception {
    ObjectFactory objectFactory = new ObjectFactory();
    JAXBElement<String> code = objectFactory.createProdRequestCode("test");
    CWDocProdRequest doc = jaxbElement.getValue();
    doc.setCode(code);

    return doc;
}

}

    @Configuration
    @EnableBatchProcessing
    public class XMLReaderConfiguration {

@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;


@Bean
public BatchCWAutoProcessor processor() {
    return new BatchCWAutoProcessor();
}

@Bean(destroyMethod="")
public StaxEventItemReader <JAXBElement<ProdRequest>> reader(){
    StaxEventItemReader<JAXBElement<ProdRequest>> reader = new StaxEventItemReader<JAXBElement<ProdRequest>>();
    reader.setResource(new ClassPathResource("policy.xml"));
    reader.setFragmentRootElementName("ProdRequest");




    Jaxb2Marshaller xmlMarshaller = new Jaxb2Marshaller();

    ObjectFactory objectFactory = new ObjectFactory();

    xmlMarshaller.setClassesToBeBound(new Class[] { 
                    //auto generated JAXB classes
           });

    xmlMarshaller.setSupportJaxbElementClass(true);


    reader.setUnmarshaller(xmlMarshaller);



    return reader;
}

@Bean(destroyMethod="")
public StaxEventItemWriter<ProdRequest> writer(){
    StaxEventItemWriter<ProdRequest> writer = new StaxEventItemWriter<ProdRequest>();
    String exportFilePath = "C:/springBatchTest.xml";
    writer.setResource(new FileSystemResource(exportFilePath));
    writer.setRootTagName("ProdRequest");


    Jaxb2Marshaller xmlMarshaller = new Jaxb2Marshaller();

    xmlMarshaller.setClassesToBeBound(new Class[] {
                //list auto generated JAXB classes here
           });

    xmlMarshaller.setSupportJaxbElementClass(true);

    writer.setMarshaller(xmlMarshaller);
    return writer;
}

@Bean
public Step step1(){
    return stepBuilderFactory.get("step1")
            //.<ProdRequest, ProdRequest> chunk(10)//changed this to the line below
            .<JAXBElement<ProdRequest>, ProdRequest> chunk(10)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
}


@Bean
public Job importUserJob(){
    return jobBuilderFactory.get("importUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();               
}
    }
于 2018-05-24T14:19:02.390 回答