2012-05-09 22 views
9

Attualmente sto lavorando con il servizio web Dynamics CRM 4.0. La prima cosa che ho fatto è stata la generazione delle classi corrette con wsimport per Java/JAX-WS in base al WSDL del servizio web. Durante la generazione delle classi ho ottenuto alcuni errori:WSImport genera XMLTypes in conflitto per più Dynamics CRM 4.0 WSDL

[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 

Linea 979 ci dice:

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

e la linea di 12274 ci dà:

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

Entrambe le parti sono nello stesso spazio dei nomi. Entrambi saranno generati come RetrieveResponse.class e quindi sono in collisione. Ho trovato una soluzione per questo problema, che è il file XML JAX-B binding:

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

Questo funziona (non so se questo è l'approccio corretto ..?) ..

Così, dopo questo , Sono riuscito a creare alcune chiamate di successo al webservice, che è fantastico!

Ora viene il problema: alcune entità aziendali in dynamics crm utilizzano la classe Elenco di selezione. Questo tipo di entità può essere interrogato con il servizio Metadata: http://msdn.microsoft.com/en-us/library/bb890248.aspx

Quindi la prossima cosa che ho fatto è stata, ancora una volta, la generazione delle classi per il servizio di metadati, basato sul suo WSDL. Il risultato delle classi generate non è come noi eccetto. Ad esempio, genera una classe 'com.microsoft.schemas.crm._2007.webservices.ExecuteResponse'. Ma questa classe esiste anche nello stesso identico pacchetto delle classi generate da CrmService. Le differenze tra il 2 sono:

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

Ora questa classe è solo un esempio (un altro esempio è CrmAuthenticationToken), che è un quasi duplicato esatto di un'altra classe. Per poter utilizzare le stesse classi, ho aggiunto un suffisso del pacchetto alle classi CrmService (visualizzato come prefisso.). Così ora quando provo a chiamare il CrmService, ottengo la seguente eccezione:

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 

io personalmente penso che sia strano hanno messo classi diverse con lo stesso nome nella stessa struttura del pacchetto. Ciò significa che non puoi mai utilizzare i 2 servizi web contemporaneamente.

Si tratta di Microsoft, un bug di WSimport o solo uno stupido errore alla mia estremità? Spero che qualcuno possa aiutarmi con questo problema!

Grazie per il vostro tempo!

risposta

1

Questa è incoerenza di Microsoft in combinazione con wsimport che è alquanto difficile da utilizzare.

PickList e CRMAuthenticationToken suonano come tipi di dati personalizzati, ci si aspetta che questi vengano riutilizzati dal servizio al servizio. Ci si aspetterebbe anche che determinate entità specifiche del CRM (ad esempio, Cliente o Azienda o Indirizzo) vengano riutilizzate dal servizio al servizio.

È maleducazione sul lato Microsoft delle cose che le definiscono in modo diverso per servizi diversi. Ciò rende difficile prendere la risposta di un servizio e inviarlo a un altro servizio.

Se i servizi avessero condiviso uno o più schemi comuni, potreste averli compilati per primi, usando xjc. Quindi potresti aver fornito un cosiddetto file episodio a wsimport per dirgli di usare quelle classi invece di generarne di nuove. Vedi the metro guide. Questo è un bel rompicapo, posso dirti dall'esperienza, mi sono imbattuto nel bug JAXB-829, xjc si dimentica di generare gli attributi if-exists nel file episodio.

Cosa farei, vorrei compilare ogni wsdl nel proprio pacchetto e considerare le classi generate come oggetti di trasferimento dati semplici e non intelligenti. Se volessi inviare un oggetto che avevo appena recuperato da un servizio a un secondo servizio, mi convertirei tra entrambi. Se questo risulta in un codice terribilmente ingombrante, o se si desidera aggiungere la logica a determinate entità, suggerirei di scrivere le proprie classi modello appropriate per le Entità che si desidera condividere e scrivere convertitori da e verso gli oggetti DTO nel web pacchetti di servizi che desideri utilizzare con.

Problemi correlati