0

サービスバスからメッセージを引き出したい。メッセージは XML に他なりません。PEEK_LOCK目的を達成するためにオプションを使用したい。

今のところ、キューにメッセージはありません。私のコードは、30 秒ごとにスケジュールを実行します。キューにメッセージがある場合はメッセージをプルし、それ以外の場合はNo more message を出力します

ReceiveMessageOptions opts = ReceiveMessageOptions.DEFAULT;
opts.setReceiveMode(ReceiveMode.PEEK_LOCK);
service.getQueue(queueName).getValue().setMaxSizeInMegabytes((long) 1);
BrokeredMessage message;
message = service.receiveQueueMessage(queueName).getValue();
StreamSource source = null;
ResponseEntity<String> response = null;
LOG.debug("Message: " + message);
// LOG.debug("message.getMessageId(): " + message.getMessageId());
// try {
if (message != null) {
    source = new StreamSource(message.getBody());
    StringWriter outWriter = new StringWriter();
    StreamResult result = new StreamResult(outWriter);
    TransformerFactory tFactory = TransformerFactory.newInstance();
    Transformer transformer = tFactory.newTransformer();
    transformer.transform(source, result);
    StringBuffer sb = outWriter.getBuffer();
    String finalstring = sb.toString();
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    InputSource src = new InputSource();
    src.setCharacterStream(new StringReader(finalstring));

    Document doc = builder.parse(src);
    String ecnNo = doc.getElementsByTagName(xmlECNNoTag).item(0).getTextContent();

    LOG.info(ecnNo + " Is pulled from queue "); 
    if (LOG.isDebugEnabled()) {
        LOG.info("XML Content: " + finalstring);
    }
}
service.deleteMessage(message);

コードを削除すると、peek_lockコードは正常に機能します。を使用すると、次のpeek_lockエラーが発生します。

javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; 行番号: 1; 列番号: 50; publicId と systemId の間に空白が必要です。com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:749) で ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc で。 trax.TransformerImpl.transform(TransformerImpl.java:351) ~[na:1.8.0_66] com.jci.subscriber.service.PLMSubscriberMSServiceImpl.azureMessageSubscriber(PLMSubscriberMSServiceImpl.java:160) ~[classes/:na] com.jci で.subscriber.PLMSubscriberMSApplication.getXML(PLMSubscriberMSApplication.java:118) [classes/:na] at sun.reflect.GeneratedMethodAccessor101.invoke(Unknown Source) ~[na:na] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 43) ~[na:1.8.0_66] java.lang.reflect. java.lang.Thread. run(Thread.java:745) [na:1.8.0_66] 原因: org.xml.sax.SAXParseException: publicId と systemId の間に空白が必要です。com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239) で ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax で。 TransformerImpl.transformIdentity(TransformerImpl.java:641) ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:737) ~[na:1.8 .0_66] ... 15 個の共通フレームを省略 run(ThreadPoolExecutor.java:617) [na:1.8.0_66] java.lang.Thread.run(Thread.java:745) [na:1.8.0_66] 原因: org.xml.sax.SAXParseException: 空白publicId と systemId の間に必要です。com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239) で ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax で。 TransformerImpl.transformIdentity(TransformerImpl.java:641) ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:737) ~[na:1.8 .0_66] ... 15 個の共通フレームを省略 run(ThreadPoolExecutor.java:617) [na:1.8.0_66] java.lang.Thread.run(Thread.java:745) [na:1.8.0_66] 原因: org.xml.sax.SAXParseException: 空白publicId と systemId の間に必要です。com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239) で ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax で。 TransformerImpl.transformIdentity(TransformerImpl.java:641) ~[na:1.8.0_66] com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:737) ~[na:1.8 .0_66] ... 15 個の共通フレームを省略

4

1 に答える 1

0

例外によると、私の経験によると、この問題は、サービス バスからのメッセージのリモート DTD スキーマをpeek_lockモード viaで検証したことが原因であると考えられますDocumentBuilder

以下のような回避策があります。

  1. メソッド[DocumentBuilderFactory.setValidating(boolean validating)] 1を使用して、以下のようにメッセージの検証を無効にしてみてください。

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(false);
    DocumentBuilder builder = factory.newDocumentBuilder();
    
  2. メソッド経由でカスタムEntityResolverオブジェクトを設定してみてください。SO スレッドの anwser を参照してください。 Make DocumentBuilder.parse は DTD 参照を無視しますDocumentBuilderDocumentBuilder.setEntityResolver(EntityResolver er)

builder.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (systemId.contains("foo.dtd")) { return new InputSource(new StringReader("")); } else { return null; } } });

  1. dom4jメッセージを解析するのと同じように、サードパーティのライブラリを使用してみてください。

それが役に立てば幸い。ご不明な点がございましたら、お気軽にお問い合わせください。

于 2016-12-01T08:53:58.377 に答える