9

現在、Dynamics CRM 4.0 Web サービスを使用しています。Java/JAX-WS私が最初にしたことは、Web サービスの WSDL に基づいて wsimport を使用して適切なクラスを生成することでした。クラスを生成しているときに、いくつかのエラーが発生しました。

[ERROR] A class/interface with the same name
"com.microsoft.schemas.crm._2007.webservices.RetrieveResponse" is already in use. Use a class customization to resolve this conflict.
  line 979 of file://src/main/webapp/WEB-INF/classes/META-INF/wsdl/CrmServiceWsdl.wsdl

[ERROR] (Relevant to above error) another "RetrieveResponse" is generated from here.
  line 12274 of file://src/main/webapp/WEB-INF/classes/META-INF/wsdl/CrmServiceWsdl.wsdl

行 979 は次のことを示しています。

<s:element name="RetrieveResponse">
    <s:complexType>
      <s:sequence>
        <s:element name="RetrieveResult" type="s3:BusinessEntity" />
      </s:sequence>
    </s:complexType>
  </s:element>

そして、12274 行目からは次のようになります。

<s:complexType name="RetrieveResponse">
    <s:complexContent mixed="false">
      <s:extension base="tns:Response">
        <s:sequence>
          <s:element ref="s3:BusinessEntity" />
        </s:sequence>
      </s:extension>
    </s:complexContent>
  </s:complexType>

両方の部分が同じ名前空間にあります。どちらも RetrieveResponse.class として生成されるため、衝突しています。JAX-Bバインディングxmlファイルであるこの問題の解決策を見つけました:

<bindings node="//xsd:complexType[@name='RetrieveResponse']">
  <jaxb:class name="RetrieveResponseType"/>
</bindings>

これは機能します (これが正しいアプローチかどうかはわかりません..?)。

この後、Web サービスへの呼び出しを成功させることができました。これは素晴らしいことです。

ここで問題が発生します。動的 CRM の一部のビジネス エンティティはクラスPicklistを使用します。このタイプのエンティティは、メタデータ サービスで照会できます: http://msdn.microsoft.com/en-us/library/bb890248.aspx

次に私が行ったのは、やはり WSDL に基づいて、メタデータ サービスのクラスを生成することでした。生成されたクラスの結果は、私たちが例外としているものではありません。たとえば、クラス「com.microsoft.schemas.crm._2007.webservices.ExecuteResponse」を生成します。ただし、このクラスは、CrmService で生成されたクラスのまったく同じパッケージにも存在します。2つの違いは次のとおりです。

メタデータ サービス ExecuteReponse:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "response"
})
@XmlRootElement(name = "ExecuteResponse")
public class ExecuteResponse {

   @XmlElement(name = "Response")
   protected MetadataServiceResponse response;
etc...

CrmService ExecuteReponse:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "response"
})
@XmlRootElement(name = "ExecuteResponse")
public class ExecuteResponse {

   @XmlElement(name = "Response", required = true)
   protected ResponseType response;
etc...

現在、このクラスは 1 つの例 (別の例はCrmAuthenticationToken ) にすぎず、別のクラスのほぼ正確な複製です。同じクラスを使用できるようにするために、CrmService クラスに package-suffix を追加しました ( prefix . として表示されます)。そのため、CrmService を呼び出そうとすると、次の例外が発生します。

Two classes have the same XML type name "{http://schemas.microsoft.com/crm/2007/CoreTypes}CrmAuthenticationToken". Use @XmlType.name and @XmlType.namespace to assign different names to them.
this problem is related to the following location:
    at com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken
    at public com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken *prefix*.com.microsoft.schemas.crm._2007.coretypes.ObjectFactory.createCrmAuthenticationToken()
    at *prefix*.com.microsoft.schemas.crm._2007.coretypes.ObjectFactory
this problem is related to the following location:
    at *prefix*.com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken
    at public javax.xml.bind.JAXBElement *prefix*.com.microsoft.schemas.crm._2007.webservices.ObjectFactory.createCrmAuthenticationToken(*prefix*.com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken)
    at *prefix*.com.microsoft.schemas.crm._2007.webservices.ObjectFactory

個人的には、同じパッケージ構造に同じ名前の異なるクラスを配置するのは奇妙だと思います。つまり、2 つの Web サービスを同時に使用することはできません。

これは Microsoft、WSimport のバグですか、それとも私の愚かな間違いですか? 誰かがこの問題で私を助けてくれることを願っています!

御時間ありがとうございます!

4

1 に答える 1

1

これは、Microsoft の不一致と、wsimport の使用がやや難しいことを組み合わせたものです。

PickList と CRMAuthenticationToken はカスタム データ型のように聞こえますが、これらがサービスからサービスへと再利用されることを期待できます。また、特定の CRM 固有のエンティティ (顧客、ビジネス、住所など) がサービスからサービスへと再利用されることも期待できます。

Microsoft 側では、サービスごとに異なる定義を行うのはマナーの悪さです。これにより、あるサービスの回答を別のサービスに送信することが難しくなります。

サービスが 1 つ以上の共通スキーマを共有していれば、xjc を使用してそれらを最初にコンパイルできたはずです。次に、いわゆるエピソード ファイルを wsimport に提供して、新しいクラスを生成する代わりにそれらのクラスを使用するように指示することができます。地下鉄ガイドを参照してください。これはかなりのパズルです。経験から言えば、バグ JAXB-829 に遭遇しました。xjc は、エピソード ファイルに if-exists 属性を生成するのを忘れています。

私なら、各 wsdl を独自のパッケージにコンパイルし、生成されたクラスを単純でインテリジェントでないデータ転送オブジェクトとして扱います。あるサービスから取得したばかりのオブジェクトを 2 番目のサービスに送信したい場合は、両方の間で変換します。これが非常に扱いにくいコードになる場合、または特定のエンティティにロジックを追加したい場合は、共有したいエンティティに対して独自の適切なモデル クラスを作成し、Web サービスの DTO オブジェクトとの間でコンバーターを作成することをお勧めします。一緒に使用したいパッケージ。

于 2013-01-20T18:43:43.920 に答える