WSImport为多个Dynamics CRM 4.0 WSDL生成冲突的XMLType

时间:2012-05-09 12:01:41

标签: jaxb jax-ws dynamics-crm dynamics-crm-4 wsimport

我目前正在使用Dynamics CRM 4.0网络服务。我做的第一件事是基于webservice的WSDL为Java/JAX-WS生成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生成的类的完全相同的包中。两者之间的差异是:

Metadataservice 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...

现在这个类只是一个例子(另一个例子是 CrmAuthenticationToken ),这是另一个类的几乎精确复制。为了能够使用相同的类,我在CrmService类中添加了一个包后缀(显示为前缀。)。 所以现在当我尝试调用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服务..

这是微软,WSimport错误还是我最后的一个愚蠢的错误?希望有人可以帮我解决这个问题!

谢谢你的时间!

1 个答案:

答案 0 :(得分:1)

这是微软的不一致,而且wsimport有点难以使用。

PickList和CRMAuthenticationToken听起来像自定义数据类型,您期望从服务到服务重用这些数据类型。 您还希望某些特定于CRM的实体(例如,客户或业务或地址)可以从服务重用于服务。

微软方面的不礼貌是他们为不同的服务定义了不同的东西。这使得很难获得一项服务的答案并将其发送到另一项服务。

如果服务共享一个或多个公共模式,您可以先使用xjc编译它们。然后你可以为wsimport提供一个所谓的剧集文件,告诉它使用这些类而不是生成新的类。见the metro guide。这可能是一个难题,我可以从经验告诉你,我遇到了错误JAXB-829,xjc忘记在剧集文件中生成if-exists属性。

我要做的是,我将每个wsdl编译为自己的包,并将生成的类视为简单的非智能数据传输对象。 如果我想将我刚从一个服务检索到的对象发送到第二个服务,我将在两者之间进行转换。 如果这导致非常笨拙的代码,或者如果您希望向某些实体添加逻辑,我建议您为要共享的实体编写自己的正确模型类,并在Web服务中为DTO对象编写转换器你希望用它们的包。