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

edolor 发布于 2019-11-08 java 最后更新 2019-11-08 22:59 16 浏览

在服务器上有一个过程,每隔特定时间间隔(例如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.");
}
我的问题很火,以确定编组过程已完成,以便文件可以发布进一步处理?
已邀请:

eet

赞同来自:

这是一些代码,我是如何解决它的(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);
    }
}

uid

赞同来自:

请从此链接下载代码[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);
}
}