如何确定JAXB已完成编组到文件

时间:2017-11-24 10:19:07

标签: java xml jaxb marshalling

在服务器上有一个进程,每隔一个特定的时间间隔(例如5分钟)从特定目录中获取文件。 正在拾取的文件是由Web服务生成的。 JAXB编组将文件从对象转换为xml文件。 问题是文件在完成之前被频繁拾取。 解决方案是将文件放在临时目录中,或者为它们提供临时的特定扩展,让轮询过程知道跳过这些。 之后,可以将文件移动到处理目录,也可以更改扩展名,以便轮询过程可以将其取出。

该方法如下所示;

    private void writeToFile(Object obj, String outputFileName) {
    LOG.debug("Executing operation writeToFile using filename '{}' and object of type '{}'.", outputFileName, obj.getClass());

    try {
        Marshaller jaxbMarshaller = JAXB_CONTEXT.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        jaxbMarshaller.marshal(obj, new File(outputFileName));
        LOG.debug("Wrote request to file '{}'.", outputFileName);
    } catch (JAXBException e) {
        LOG.error("Exception occurred while writing request to file:", e);
    }
    LOG.debug("Done executing operation writeToFile.");
}

我的问题很热,要确定编组过程已完成,以便文件可以发布以便进一步处理?

2 个答案:

答案 0 :(得分:1)

请从此链接下载代码[https://turreta.com/2017/03/07/jaxb-perform-pre-and-post-processing-with-unmarshaller-listener/]将以下Person Marshall Listener代码添加到源代码,因为这将调用每个节点已检查Person内部的根节点实例(这需要修改作为基本节点)在Marshall方法之前和之后,也使用了2的计数,因为每次开始和结束节点都会调用它,因为这应该仅在结束节点上调用,如果count == 2

package com.turreta.jaxb.unmarshaller.listener;

    public class PersonMarshallListener extends javax.xml.bind.Marshaller.Listener {

            int beforeCount = 1;
            int afterCount = 1;

          @Override
           public void beforeMarshal(Object source) {
              super.beforeMarshal(source);
              if (source instanceof Person) {

                  if (beforeCount == 2) {
                      beforeCount = 1;
                      System.out.println("BEFORE MARSHAL");
                  } else {
                      beforeCount++;
                  }
              }

           }

           @Override
           public void afterMarshal(Object source) {
               super.afterMarshal(source);

               if (source instanceof Person) {

                   if (afterCount == 2) {

                       afterCount = 1;
                       System.out.println("AFTER MARSHAL");
    //                 System.out.println("This will be called once the marshall has been completed");
                   } else {
                       afterCount++;
                   }
               }


           }

    }

用以下代码替换DemoApp

package com.turreta.jaxb.unmarshaller.listener;

import java.io.FileInputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

public class DemoApp {
    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Person.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        FileInputStream xml = new FileInputStream("src/main/resources/person.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        PersonUnmarshallListener pul = new PersonUnmarshallListener();
        unmarshaller.setListener(pul);

        Person person = (Person) unmarshaller.unmarshal(xsr);
        System.out.println(person);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setListener(new PersonMarshallListener());
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(person, System.out);


    }
}

答案 1 :(得分:0)

以下是一些代码,我是如何解决它的(Spring Integration)

您创建一个缓冲区来存储不够大的文件,并在以后处理它们。

我知道这不是完美的(有了睡眠),但它有效。更好的解决方案不是使用文件交换,而是使用REST-api传输数据。

import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.integration.core.MessageSource;
import org.springframework.messaging.Message;

import java.io.File;
import java.util.List;

public class LastModifiedFileReadingMessageSource implements MessageSource<File> {

    private final Logger log = LoggerFactory.getLogger(LastModifiedFileReadingMessageSource.class);
    private final MessageSource fileReadingMessageSource;
    private final List<Message<File>> buffer = Lists.newArrayList();
    private final long age = 60;

    public LastModifiedFileReadingMessageSource(MessageSource fileReadingMessageSource) {
        this.fileReadingMessageSource = fileReadingMessageSource;
    }

    public Message<File> receive() {
        Message<File> message = fileReadingMessageSource.receive();
        while (message != null) {
            if (isOldEnough(message)) {
                return message;
            } else {
                buffer.add(message);
                log.info("Buffering file which is not old enough: {}; Buffer size: ", message, buffer.size());
            }
            message = fileReadingMessageSource.receive();
        }
        while (!buffer.isEmpty()) {
            message = buffer.stream().filter(this::isOldEnough).findFirst().orElse(null);
            if (message != null) {
                buffer.remove(message);
                log.info("Use file from buffer: {}; Buffer size: ", message, buffer.size());
                return message;
            }
            sleep();
        }
        return message;
    }

    private void sleep() {
        try {
            log.info("Go to sleep for a while... ({} seconds)", age);
            Thread.sleep(this.age * 1000);
        } catch (InterruptedException e) {
            log.error("Thread.sleep was never a good idea ;(", e);
        }
    }

    private boolean isOldEnough(Message<File> message) {
        long now = System.currentTimeMillis() / 1000;
        return (message.getPayload().lastModified() / 1000 + this.age <= now);
    }
}