3

コントラクトに定期的に要素を追加できる Web サービスを呼び出します。

例: SOAP 応答本文には以下が含まれます。

<picture>
   <active>true</active>
   <code>172</code>
   <label>Nikon D3200 Black</label>
   <downloadEnabled>true</downloadEnabled>
</picture>
<picture>
   <active>false</active>
   <code>177</code>
   <label>Nikon D5200 Red</label>
   <downloadEnabled>true</downloadEnabled>
   <extraField>none</extraField>
</picture>

CXF で生成された JAXB Bean は次のようになります。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "pictureListJAXB", propOrder = {
    "active",
    "code",
    "label",
    "downloadEnabled",
    "extraField"
})
public class PictureListJAXB {

    protected boolean active;
    protected String code;
    protected String label;
    protected boolean downloadEnabled;
    @XmlElement(nillable = true)
    protected String extraField

    // And Getters / Setters comes here after      

}

JAXB Bean は、Maven プラグインcxf-codegen-pluginバージョン 2.6.2 (apache.cxf から) で生成されます。

ここで、SOAP 応答に新しい要素が表示された場合に備えて、Bean をフォールト トレラントにするソリューションがあるかどうかを知りたいと思います。

<picture>
    <active>true</active>
    <code>172</code>
    <label>Nikon D3200 Black</label>
    <downloadEnabled>true</downloadEnabled>
    <newUnmappedElement>anything irrelevant</newUnmappedElement>
</picture>

今のところ、そのような反応を受け取ったときは、Unmarshalling Errorこの新しい要素があるためです。

私の JAXB には、管理したい最小限のフィールドが含まれていますが、Bean が新しい要素に対処し、それらを無視できるようにしたいと考えています。

JAXB Bean を再生成せずにそれを行う方法はありますか? (現在、Bean を再生成してプロジェクトをリリースする必要があります)

CXFオプション(およびxjc)を確認しましたが、ドキュメント(およびGoogle)には何も見つかりませんでした。アンマーシャリング操作はReferentialService、CXF によって生成されたものでも自動的に行われるため、この部分の生成を変更するオプションで十分です。

CXF で生成されたクラスを使用して Web サービスを呼び出すコードは次のとおりです。

public ReferentialService getReferentialService(String resource, String auth) throws RuntimeException {

    // These two classes are generated by CXF
    Referential referential;
    ReferentialService referentialService;


    // Get the resource URL in form http://myserver:port/remote-backend/resource?wsdl
    referential = new Referential(new URL(MyConfigUtil.getWSDL(resource)));

    referentialService = referential.getReferentialServicePort();
    BindingProvider bp = (BindingProvider) referentialService;

    // Get the endpoint URL in form http://myserver:port/remote-backend/resource
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, MyConfigUtil.getWebServiceEndPoint(resource));

    // Add SOAP credentials
    String username = HttpBasicAuthHelper.getUsername(auth);
    String password = HttpBasicAuthHelper.getPassword(auth);

    bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);

    return referentialService;
}

そして呼び出し:

// Throws Exception just for the sample code
public InputStream listPictures(QueryDTO request, String resource, String auth) throws Exception {

    InputStream is = null;
    if (request != null) {

        // This is the WS Call which failed with unmarshal error
        List<PictureListJAXB> result = getReferentialService(resource, auth).getPictures(request);

        // Some code to convert JAXB into a  XML stream
        is = convertObjectToXmlStream(result);
    }
    return is;
}

更新:この投稿を見ましたが、私の気持ちは同じでした: JAXB は、CXF なしで単独で使用された場合、マップされていない要素を無視します。を使用することによりcxf-codegen-plugin、そうではありません。

4

3 に答える 3

2

この問題を解決する 1 つの方法は、Jaxb アノテーション @XmlAnyElement(lax = true) を使用することです。つまり、そのフィールドでは、要素が @XmlRootElement または @XmlElementDecl を介してクラスに関連付けられている場合、対応するクラスのインスタンスが使用されます。要素が org.w3c.dom.Element.A サンプル コードのインスタンスとして設定されない場合は、フィールドに入力します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
    ..
    ....
    @XmlAnyElement(lax = true)
    protected List<Object> any;

クラスの明示的なプロパティに対応しない入力内の要素はすべて、このリストに追加されます。チェックアウト 詳細ここにリンクの説明を入力してください

于 2015-06-27T08:37:07.153 に答える