2017-11-24 1 views
0

サーバー上に特定のディレクトリ(特定のディレクトリ)(たとえば5分)ごとにファイルを取得するプロセスがあります。 ピックアップされているファイルは、Webサービスによって生成されます。 JAXBマーシャリングはファイルをオブジェクトからxmlファイルに変換します。 問題は、ファイルが完了する前にピックアップされることが頻繁に発生することです。 解決方法は、一時ディレクトリにファイルを配置するか、一時的な特定の拡張子を付けて、ポーリングプロセスにこれらをスキップするよう通知させることです。 その後、ファイルを処理ディレクトリに移動することができます。または、拡張機能を変更して、ポーリングプロセスがそれらを取得できるようにすることができます。JAXBがファイルにマーシャリングされたことを確認する方法

この方法は次のようになります。

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."); 
} 

私の質問は、ファイルがさらなる処理のためにリリースすることができるようにマーシャリングプロセスへが行われていることdtermineする暑いですか?ここで

+0

jaxbMarshaller.marshalの後に.xmlpartialという別の拡張子を付けてoutputFileNameを試してみると、ファイル名を.xml拡張子に戻す行を追加すると、完了したらウォッチャーがxmlファイルをピックアップするようにすることができます – Saran

+0

これは問題ありませんが、マーシャリングが完了したときはどうすればわかりますか?それは私が悩んでいる本質的な問題です。 PS:私は 'lck'のような拡張機能についてもっと考えていましたが、すべてが本当にうまいです。 – Frazz

+0

[link](https://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#marshalEventCallback)afterMarshal – Saran

答えて

0

人の内のルートノードのインスタンスをチェックして、これは、各ノードに対して呼び出されますようhttps://turreta.com/2017/03/07/jaxb-perform-pre-and-post-processing-with-unmarshaller-listener/]は、ソースに人マーシャルリスナーのコードの下に加える[このリンクからコードをダウンロードしてください(これを変更する必要がありますあなたのベースノードとして)は、始まりと終わりのノードがこれを毎回呼び出すので、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); 


    } 
} 
+0

ありがとう、私はコードのあなたの適応を使用して、ありがとう、それは動作します。今私がこれを理解していることを確認する。PersonMarshallListenerのafterMarshalメソッドは、ソースオブジェクトがPersonのインスタンスであるかどうかをチェックし、そうであればノードを数えてルートノード内にあるかどうかを判定します。人のXMLは1つのXML要素しか知っていないので、次はルートノードでなければなりません。私は正しいですか?私がいれば、ルートノードに到達する前に私が持っている多くのノードを知らなければどうでしょうか?おかげさまで、あなたは大きな助けになりました! – Frazz

+0

_Am私は正しいですか?_いいえ。xmlには任意の数のノードを含めることができますが、心配する必要はありません。ダウンロードしたソースからのxmlでは、Personがルート要素であり、count 2は()であり、人のインスタンスでチェックされたときにtrueになります。完了の詳細だけが必要なので、エンドノードのみを使用するように制限しています。そこでif(afterCount == 2){'をチェックします。 – Saran

+0

あなたはそれを明確にしました。あなたの時間と努力をありがとう、非常に感謝します!答えとして受け入れます。 – Frazz

0

は、私はそれを解決する方法いくつかのコード、(春インテグレーション)

は、あなたが十分な年齢ではないし、後でそれらを処理ファイルを格納するためのバッファを作成することです。

私はそれが完璧ではない(睡眠あり)と知っていますが、それは機能します。より良い解決策は、ファイル交換ではなく、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); 
    } 
} 
+0

コード例でこれを実装する方法がわかりません。私はwebservicesとjaxbの新機能です。 – Frazz

関連する問題