web-dev-qa-db-ja.com

JAXBを使用してサービスから返されたJava 'anyType'からオブジェクトを作成する方法は?

Webサービスは、WSDLによって次のように定義されたオブジェクトを返します。

_<s:complexType mixed="true"><s:sequence><s:any/></s:sequence></s:complexType>
_

このオブジェクトのクラス情報を出力すると、次のようになります。

_class com.Sun.org.Apache.xerces.internal.dom.ElementNSImpl
_

しかし、このオブジェクトを次のクラスのオブジェクトとして非整列化する必要があります。

_@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = {
        "info",
        "availability",
        "rateDetails",
        "reservation",
        "cancellation",
        "error" }) 
@XmlRootElement(name = "ArnResponse") 
public class ArnResponse { }
_

このオブジェクトのXMLをマーシャリングする方法を知っているので、応答が正しいことを知っています。

_Marshaller m = jc.createMarshaller();
m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
m.marshal(rootResponse, System.out);
_

どちらが出力されるか:

_<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:SubmitRequestDocResponse xmlns:ns2="http://tripauthority.com/hotel">
    <ns2:SubmitRequestDocResult>
        <!-- below is the object I'm trying to unmarshall -->
        <ArnResponse>
            <Info />
            <Availability>
                <!-- etc--> 
             </Availability>
        </ArnResponse>
    </ns2:SubmitRequestDocResult>
</ns2:SubmitRequestDocResponse>
_

表示されているElementNSImplオブジェクトを、それが表すArnResponseオブジェクトに変換するにはどうすればよいですか?

さらに、ファイルアクセスが制限されているAppEngineで実行しています。

助けてくれてありがとう

更新

次のように、@XmlAnyElement(lax=true)アノテーションを追加しました。

_  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlType(name = "", propOrder = {
      "content"
  })
  @XmlSeeAlso(ArnResponse.class)
  public static class SubmitRequestDocResult {

    @XmlMixed
    @XmlAnyElement(lax = true)
    protected List<Object> content;
_

しかし、違いはありません。

これはコンテンツがListであるという事実と関係がありますか?

サーバーからコンテンツを取得した後、コンテンツにアクセスしようとしているコードは次のとおりです。

_List list = rootResponse.getSubmitRequestDocResult().getContent();

for (Object o : list) {
  ArnResponse response = (ArnResponse) o;
  System.out.println(response);
}
_

これには出力があります:

2012年1月31日10:04:14 AM com.districthp.core.server.ws.alliance.AllianceApi getRates SEVERE:com.Sun.org.Apache.xerces.internal.dom.ElementNSImplをcom.districthp.coreにキャストできません.server.ws.alliance.response.ArnResponse

答え:

axtavtの答えはトリックをしました。これはうまくいきました:

_Object content = ((List)result.getContent()).get(0);
JAXBContext context = JAXBContext.newInstance(ArnResponse.class);
Unmarshaller um = context.createUnmarshaller();
ArnResponse response = (ArnResponse)um.unmarshal((Node)content);
System.out.println("response: " + response);
_
18
Cuga

そのオブジェクトをUnmarshaller.unmarshal(Node)に渡すと、非整列化できるはずです。

19
axtavt

@XmlAnyElement(lax=true)を使用できます。これにより、既知のルート要素(@XmlRootElementまたは@XmlElementDecl)をドメインオブジェクトに。例については、以下を参照してください。

5
bdoughan

私がXMLでの作業で見つけたものから、anyTypeは任意のオブジェクトを表すことができるので、それにマッピングできる最も近いものはJava.lang.Object。 (anyTypeは技術的にはセキュリティホールとなる可能性があるという事実に加えて、悪意のあるバイナリを含め、誰かがその場所に何かを注入することを可能にし、スキーマで許可されているため、何も阻止しません。)

カスタムオブジェクトへのマッピングを許可するようにスキーマを変更することをお勧めします。これは、プログラミングの観点、消費の観点、およびセキュリティの観点の両方からよりクリーンです。

あなたがそれを行うことができないので、あなたの要素の属性としてタイプを保存することをお勧めします。次に、anyTypeをそのオブジェクトに戻すのを助けるためにカスタムコードを書く必要があるかもしれませんが、少なくともあなたはそのタイプを知っています。

私の2セントは、私の経験に基づいています(主に統合の領域で)。

2
Chris Aldrich