2

私のアプリケーションは 2 つのレイヤーに分かれています。バックエンド レイヤーは一連の Web サービスを公開し、プレゼンテーション レイヤーはそれらを使用してビジネス データを取得します。

構築を可能な限り自動化するために、すべての結果の WSDL ファイルと関連する XSD ファイルを (Maven アセンブラー プラグインを使用して) ZIP 依存関係にパッケージ化し、インストール フェーズで nexus にアップロードします。

次に、UI POM で、この ZIP ファイルを (maven 依存関係プラグインを使用して) ローカル ディレクトリ ( src/main/resources/wsdl) に解凍し、CXF-CODEGEN プラグインを使用してクライアントを生成します。

問題は、これらのサービスの多くが共通のモデル エンティティを共有していることです。たとえば、多くのメソッドがCatalogueクラスを使用しています。これは、ID とテキスト値で構成されるオブジェクトに使用するエンティティです。

CXF で生成されたコードを使用すると、CatalogueWeb サービスごとに異なるクラス (異なるパッケージ名を持つ) になり、実際にはすべて異なるクラスであるため、コード内の OO ポリモーフィズム機能が失われます。

この問題を回避するには、XSD クラスを最初に「エピソード」と呼ばれるものにコンパイルし、次にそれらのエピソード ファイルを CXF に供給して、クラスを生成する代わりにそれらを利用するように指示することで、この問題を回避できると聞いています。

maven-jaxb2-plugin を実行して XSD からクラスを生成する追加のコンパイル手順を追加しようとしましたが org.xml.sax.SAXParseException; (...) 'catalogueDTO' is already defined 、このクラスが XSD ファイルに沿って繰り返されるため、例外が発生します。

誰かが私を正しい方向に向けることができますか?

4

1 に答える 1

2

Web サービスに複数のサービスおよび操作で使用されるいくつかの基本クラスがある場合、これらのクラスを単一の XSD で宣言し、プロジェクト全体でこの XSD を含めて使用するのが最善です。

次の例は、その方法を示しています。この例は、提供された情報に基づいているため、必要なものに正確に適合しない場合がありますが、概念を示します。

まず、Catalog.xsd ファイルを作成し、次のコードを使用してこのファイルでカタログ オブジェクトを宣言します。

<?xml version="1.0" encoding="utf-8" ?>

<xs:schema xmlns="http://www.yourcompany.com/Services_V1/CommonType"
       elementFormDefault="qualified"
       targetNamespace="http://www.yourcompany.com/Services_V1/CommonType"
       xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="CatalogueID_Type">
    <xs:annotation>
        <xs:documentation>The Catalogue ID is an integer value that is used to uniquely identify the catalog item on the database.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:int" />
</xs:simpleType>
<xs:simpleType name="CatalogueValue_Type">
    <xs:annotation>
        <xs:documentation>The catalog is a string value that will contain the information describing the catalog key.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string" />
</xs:simpleType>
<xs:complexType name="Catalogue_Type">
    <xs:sequence>
        <xs:element ref="CatalogID"
                    minOccurs="1"
                    maxOccurs="1" />
        <xs:element ref="CatalogueValue"
                    minOccurs="0"
                    maxOccurs="1" />
    </xs:sequence>
</xs:complexType>
<xs:element name="CatalogID"
            type="CatalogueID_Type" />
<xs:element name="CatalogueValue"
            type="CatalogueValue_Type" />
<xs:element name="Catalogue"
            type="Catalogue_Type" />

または、視覚的な表現が好きな場合:

カタログ XML オブジェクト

注意すべきことは、カタログ クラス/オブジェクトには の名前空間があるhttp://www.yourcompany.com/Services_V1/CommonTypeことです。この名前空間を WSDL で再度使用します。このオブジェクトは現在、BathroomCatalogue Service と KicthenCatalogue Service の 2 つのサービスで使用されます。簡単にするために、GetCatalogueItem というサービスで 1 つの操作だけを行います。これらのサービスごとにcatalog.xsdファイルを含め、このカタログ オブジェクトを再利用します。

バスルーム サービスの WSDL は次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="BathroomCatalogueSRV"
              targetNamespace="http://www.yourcompany.com/Services_V1/BathroomCatalogueService"
              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
              xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
              xmlns:tns="http://www.yourcompany.com/Services_V1/BathroomCatalogueService"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
              xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
              xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
              xmlns:catalogue="http://www.yourcompany.com/Services_V1/CommonType">
<wsdl:types>
    <xs:schema elementFormDefault="qualified"
               targetNamespace="http://example.com/">
        <xs:import schemaLocation="Catalog.xsd"
                   namespace="http://www.yourcompany.com/Services_V1/CommonType" />

    </xs:schema>
</wsdl:types>
<wsdl:message name="GetCatalogueItemReq">
    <wsdl:part name="GetCatalogueItemReq"
               element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:message name="GetCatalogueItemRs">
    <wsdl:part name="GetCatalogueItemRs"
               element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:portType name="BathroomCataloguePortType">
    <wsdl:operation name="GetCatalogueItem">
        <wsdl:input message="tns:GetCatalogueItemReq" />
        <wsdl:output message="tns:GetCatalogueItemRs" />
    </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BathroomCatalogueBinding"
              type="tns:BathroomCataloguePortType">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
                  style="document" />
    <wsdl:operation name="GetCatalogueItem">
        <wsdl:input />
        <wsdl:output />
    </wsdl:operation>
</wsdl:binding>
<wsdl:service name="BathroomCatalogueService">
    <wsdl:port name="BathroomCataloguePort"
               binding="tns:BathroomCatalogueBinding">
        <soap:address location="http://www.yourcompany.com/Services_V1/BathroomCatalogueService" />
    </wsdl:port>
</wsdl:service>

または、視覚的な表現が必要な場合:

バスルームサービス

Kitchen WSDL は次のようになります。

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions name="KitchenCatalogueSRV"
              targetNamespace="http://www.yourcompany.com/Services_V1/KitchenCatalogueService"
              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
              xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
              xmlns:tns="http://www.yourcompany.com/Services_V1/KitchenCatalogueService"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
              xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
              xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
              xmlns:catalogue="http://www.yourcompany.com/Services_V1/CommonType">
<wsdl:types>
    <xs:schema elementFormDefault="qualified"
               targetNamespace="http://example.com/">
        <xs:import schemaLocation="Catalog.xsd"
                   namespace="http://www.yourcompany.com/Services_V1/CommonType" />

    </xs:schema>
</wsdl:types>
<wsdl:message name="GetCatalogueItemReq">
    <wsdl:part name="GetCatalogueItemReq"
               element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:message name="GetCatalogueItemRs">
    <wsdl:part name="GetCatalogueItemRs"
               element="catalogue:Catalogue" />
</wsdl:message>
<wsdl:portType name="KitchenCataloguePortType">
    <wsdl:operation name="GetCatalogueItem">
        <wsdl:input message="tns:GetCatalogueItemReq" />
        <wsdl:output message="tns:GetCatalogueItemRs" />
    </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="KitchenCatalogueBinding"
              type="tns:KitchenCataloguePortType">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
                  style="document" />
    <wsdl:operation name="GetCatalogueItem">
        <wsdl:input />
        <wsdl:output />
    </wsdl:operation>
</wsdl:binding>
<wsdl:service name="KitchenCatalogueService">
    <wsdl:port name="KitchenCataloguePort"
               binding="tns:KitchenCatalogueBinding">
        <soap:address location="http://www.yourcompany.com/Services_V1/KitchenCatalogueService" />
    </wsdl:port>
</wsdl:service>

そしてもう一度視覚的に:

キッチンサービス

これら両方の WSDL ファイルに、catalog.xsd ファイルを含めました。これは、次のコード行で確認できます。

<xs:import schemaLocation="Catalog.xsd" 
 namespace="http://www.yourcompany.com/Services_V1/CommonType" />

これらの WSDL と XSD を cxf と一緒に使用すると、両方のサービスで使用されるカタログ オブジェクト/クラスは 1 つだけになります。すぐにシェル プロジェクトを実行すると、次の構造が生成されました。

プロジェクト フォルダ

私が宣言した CatalogueType は、私が宣言した名前空間を持つ 1 つのパッケージに含まれていることに注意してください。

サービス クラスを表示すると、Bathroom サービスと Kitchen サービスの両方がこの 1 つのクラスを使用します。キッチン サービス クラスでは を使用しますcom.yourcompany.services_v1.commontype.CatalogueType

@WebService(targetNamespace = "http://www.yourcompany.com/Services_V1/KitchenCatalogueService", name = "KitchenCataloguePortType")
@XmlSeeAlso({com.yourcompany.services_v1.commontype.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface KitchenCataloguePortType {

@WebResult(name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType", partName = "GetCatalogueItemRs")
@WebMethod(operationName = "GetCatalogueItem")
public com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItem(
    @WebParam(partName = "GetCatalogueItemReq", name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType")
    com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItemReq
);
}

そして、キッチン サービス クラスでは を使用しますcom.yourcompany.services_v1.commontype.CatalogueType

@WebService(targetNamespace = "http://www.yourcompany.com/Services_V1/BathroomCatalogueService", name = "BathroomCataloguePortType")
@XmlSeeAlso({com.yourcompany.services_v1.commontype.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface BathroomCataloguePortType {

@WebResult(name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType", partName = "GetCatalogueItemRs")
@WebMethod(operationName = "GetCatalogueItem")
public com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItem(
    @WebParam(partName = "GetCatalogueItemReq", name = "Catalogue", targetNamespace = "http://www.yourcompany.com/Services_V1/CommonType")
    com.yourcompany.services_v1.commontype.CatalogueType getCatalogueItemReq
);
}

これらのクラスは CXF によって派生および生成され、変更内容が失われるため、決して編集しないでください。したがって、WSDL ファースト アプローチを実行することで、XSD ファイルと WSDL ファイルを正しく構造化する必要があります。

これが理にかなっているかどうか教えてください。

于 2015-02-05T22:46:38.357 に答える