【问题标题】:StaxEventItemWriter ignores Jax2bMarshaller propertiesStaxEventItemWriter 忽略 Jax2bMarshaller 属性
【发布时间】:2021-10-26 10:57:47
【问题描述】:

我有一个简单的项目编写器,如下所示:

    return new StaxEventItemWriterBuilder<AddSubscriptionXml>()
            .version("1.0")
            .rootTagName("BePostSubscriptionDistribution")
            .name("optInSumoItemWriter")
            .rootElementAttributes(rootAttrs)
            .resource(new FileSystemResource(sumoSavePath + "/opt_ins_add.xml"))
            .marshaller(jaxb2Marshaller)
            .build();

我的编组器具有以下属性:

@Bean
@Scope(SCOPE_PROTOTYPE)
public Jaxb2Marshaller jaxb2Marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setMarshallerProperties(getMarshallerProps());
    marshaller.setClassesToBeBound(AddSubscriptionXml.class, ModSubscriptionXml.class, DelSubscriptionXml.class);
    return marshaller;
}

private Map<String, String> getMarshallerProps() {
    return new HashMap<>(){{
        put(Marshaller.JAXB_ENCODING, UTF_8.toString());
        put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        put("com.sun.xml.bind.xmlHeaders", "<!DOCTYPE BePostSubscriptionDistribution SYSTEM \"..\\BePostSubscriptionDistribution.dtd\">");
    }};
}

奇怪的是,StaxEventItemWriter 完全忽略了编组器属性。

首先,输出看起来像废话,没有缩进。 但更重要的是,我缺少 DocType 行:

结果(自己格式化):

<?xml version="1.0" encoding="UTF-8"?>
<BePostSubscriptionDistribution TimeDateStamp="2021-08-26 13:03:44.761" identification="addSubscription">
    <AddMagazineSubscription>
        <SubscriptionNumber EditionCode="EDITION_CODE_1">id__19860702 064M81</SubscriptionNumber>
... 

期望:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE BePostSubscriptionDistribution SYSTEM "..\BePostSubscriptionDistribution.dtd">
... 

知道如何解决这个问题吗?大量时间浪费在本应微不足道的事情上。

注意:在调试模式中,我看到当传递给 ItemWriter 时,marshaller 属性已正确设置。

注意:我在这里打开了一个 Github 问题: https://github.com/spring-projects/spring-batch/issues/3982

【问题讨论】:

    标签: java spring-batch stax


    【解决方案1】:

    在浏览了源代码之后,我认为没有直接的解决方案。 marshaller 乍一看并不是用来写 xml 文件头的,而只是用来写根目录下的 xml 项。
    我会尝试与交易对手核实,看看他们是否可以接受省略 doctype。

    如果没有其他选择,我将下载 StaxEventItemWriter 来分析输出流的编写方式并添加所需的功能。虽然从未来升级(imo)的角度来看,提供后门备份 api 会更好。

    对于缩进,我使用了这里提到的补丁,效果很好:The XML output from the Spring Batch Jaxb2Marshaller - Marshaller.JAXB_FORMATTED_OUTPUT is not working, why?

    虽然我不清楚为什么不立即将缩进/漂亮打印作为选项添加到 spring batch StaxEventItemWriter 而不是使用外部库。缩进似乎是任何使用 XML 并在 2021 年发送未格式化的 xml 的人的基本要求,这有点奇怪。管理员有条件立即查看文件(可能通过终端),以防万一事情没有按预期进行。

    根据@Mahmoud Ben Hassine 的评论:

    我可以通过提供自定义实现覆盖方法 startDocumentendDocument 来解决 docType 问题。
    这也会破坏当前关于 rootElement 的 api,但没有什么是无法从子类中修复的。

    【讨论】:

    • it's not clear to me why indentation / pretty print is not added to spring batch StaxEventItemWriter immediately:这是因为 StaxEventItemWriter 将编组过程委托给 Spring OXM 的 Marshaller 接口。就 Spring Batch 而言,Marshaller 返回的 String 是不透明的。 Spring Batch 仅将该字符串按原样写入输出编写器。
    • 看起来漂亮的打印输出与 StaxEventItemWriter 使用的 Stax(参见 github.com/spring-projects/spring-batch/issues/…stackoverflow.com/a/19320949/5019386)不兼容。您在 Github 上创建的问题与 github.com/spring-projects/spring-batch/issues/1754 重复。也就是说,我同意你的观点,缩进输出不应该那么难。
    • @MahmoudBenHassine 目前缩进对我来说不是阻塞问题,补丁有效。感谢您的意见。
    • 不客气。在这种情况下,您能否通过引用您在其他问题中使用的补丁来对您创建的问题添加评论?对于您要添加的文档类型行,是否已尝试覆盖 StaxEventItemWriter#startDocument?
    • The code behind the headerCallback isn't all that clear to me on first sigh:标题回调允许您在根元素名称和子元素之间添加内容(因此这不是您要查找的内容)。 I need the doctype line to be in between the xml declaration and the root element。你可以通过 orverridding startDocument/endDocument 来做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 2023-03-19
    • 2011-04-13
    • 2011-07-19
    相关资源
    最近更新 更多