2

私の問題は、次のように定義された Message 項目を含む MessageList 型のクラスがあることです。

<xsd:complexType name="MessageType">
    <xsd:sequence>
        <xsd:any/>
    </xsd:sequence>
</xsd:complexType>
<xsd:element name="Message" type="tns:MessageType"/>
<xsd:complexType name="MessageListType">
    <xsd:sequence>
        <xsd:element name="Message" maxOccurs="unbounded"/>
    </xsd:sequence>
</xsd:complexType>
<xsd:element name="MessageList" type="tns:MessageListType"/>

私のメッセージクラスは次のようになります(ここでは省略したゲッターとセッターを使用)

public class Message
{
private String referenceId;
private String messageType;
private Timestamp createdTime;
private String transactionIdForeignKey;
private String xmlDetail;
}

このクラスをサーブレットでマーシャリングしようとすると、次のようになります。

         List<Message> retrievedMessages = new ArrayList<Message>();
         retrievedMessages.add(new Message);
         retrievedMessages.add(new Message);

         MessageListType messageListType = new MessageListType();
         for(Message message: retrievedMessages){
             messageListType.getMessage().add(message);
         }

次のエラーが表示されます。

[#|2013-04-25T16:43:40.434+0100|WARNING|sun-appserver2.1|javax.enterprise.system.stream.err|_ThreadID=188;_ThreadName=p: thread-pool-1; w: 76;_RequestID=40c6fe10-c12f-4d0b-8912-c960381910d7;|
javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.JAXBException: class uk.co.test.test.audit.model.Message nor any of its super class is known to this context.]
    at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:322)
    at com.sun.enterprise.jbi.serviceengine.comm.WrappedMessage.writePayloadTo(WrappedMessage.java:419)
    at com.sun.enterprise.jbi.serviceengine.comm.WrappedMessage$DocumentStyleWrapper.wrap(WrappedMessage.java:215)
    at com.sun.enterprise.jbi.serviceengine.comm.WrappedMessage.wrap(WrappedMessage.java:170)
    at com.sun.enterprise.jbi.serviceengine.comm.ProviderInOut.send(ProviderInOut.java:143)
    at com.sun.enterprise.jbi.serviceengine.bridge.transport.NMRServerConnection.sendResponse(NMRServerConnection.java:81)
    at com.sun.enterprise.jbi.serviceengine.bridge.transport.JBIAdapter$WSToolkit.handle(JBIAdapter.java:127)
    at com.sun.enterprise.jbi.serviceengine.bridge.transport.JBIAdapter.handle(JBIAdapter.java:86)
    at com.sun.enterprise.jbi.serviceengine.bridge.JAXWSMessageProcessor.doWork(JAXWSMessageProcessor.java:93)
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.JAXBException: class uk.co.test.test.audit.model.Message nor any of its super class is known to this context.]
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:282)
    at com.sun.xml.bind.v2.runtime.BridgeImpl.marshal(BridgeImpl.java:100)
    at com.sun.xml.bind.api.Bridge.marshal(Bridge.java:141)
    at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:315)

なぜこれが起こっているのか知っている人はいますか?マーシャリングを行っているサーブレットは、どのクラスを見るべきかを知る必要があると思いますが、これを行う方法がわかりませんか?

4

1 に答える 1

5

クラスで正確にしたい場合は、スキーマでより正確にする必要があります。

JAXB は、JAXB が非整列化する構造と同じ構造を定義するスキーマに依存しています。

説明のために、次を使用してスキーマをコンパイルしましょxjcう。これにより、JAXB が自動的に umarhall して注釈を付けることができるクラスが作成されます。

クラスは次のとおりです。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MessageType", propOrder = {
    "any"
})
public class MessageType {

    @XmlAnyElement(lax = true)
    protected Object any;

    public Object getAny() {
        return any;
    }

    public void setAny(Object value) {
        this.any = value;
    }

}

MessageTypeスキーマから JAXB が判断できるのは、不明な量のものを含むクラスがあることだけであることがわかります<xsd:any/>。たとえば、設定が必要なString呼び出しがあることを JAXB が判断する方法はありません。referenceId

スキーマを変更できる場合は、次のように更新します

<xsd:complexType name="MessageType">
    <xsd:attribute name="referenceId" type="xsd:string"/>
    <xsd:attribute name="messageType" type="xsd:string"/>
    <xsd:attribute name="transactionIdForeignKey" type="xsd:string"/>
    <xsd:attribute name="xmlDetail" type="xsd:string"/>        
    <xsd:attribute name="createdTime" type="xsd:integer"/>        
</xsd:complexType>

クラスを構築するために必要な情報を JAXB に伝えます (この場合TimeStampは、カスタム ロジックが必要です)。longTimeStamp

生成されたクラスは、独自のクラスに似ています。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MessageType")
public class MessageType {

    @XmlAttribute(name = "referenceId")
    protected String referenceId;
    @XmlAttribute(name = "messageType")
    protected String messageType;
    @XmlAttribute(name = "transactionIdForeignKey")
    protected String transactionIdForeignKey;
    @XmlAttribute(name = "xmlDetail")
    protected String xmlDetail;
    @XmlAttribute(name = "createdTime")
    protected BigInteger createdTime;

    public String getReferenceId() {
        return referenceId;
    }

    public void setReferenceId(String value) {
        this.referenceId = value;
    }

    public String getMessageType() {
        return messageType;
    }

    public void setMessageType(String value) {
        this.messageType = value;
    }

    public String getTransactionIdForeignKey() {
        return transactionIdForeignKey;
    }

    public void setTransactionIdForeignKey(String value) {
        this.transactionIdForeignKey = value;
    }

    public String getXmlDetail() {
        return xmlDetail;
    }

    public void setXmlDetail(String value) {
        this.xmlDetail = value;
    }

    public BigInteger getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(BigInteger value) {
        this.createdTime = value;
    }

}

xml の属性がクラスのフィールドに直接マップされていることがわかります。JAXB が使用する注釈も表示されます。これらは必須ではありませんが、何をどこにマップするかを伝えるのに役立ちます。

スキーマを変更できない場合は、カスタム ロジックを実装して<xsd:any/>、関連するプロパティを検索し、手動でマップする必要があります。そのルートをたどれば、これで始められるはずです。

于 2013-04-25T16:35:40.723 に答える