Scénarios de migration des services Web : JAX-RPC vers JAX-WS et JAXB

Cette rubrique décrit les scénarios de migration des services Web JAX-RPC (API Java™ pour le RPC basé sur XML) vers les services JAX-WS (API Java des services Web XML) et les services Web JAXB (Java Architecture for XML Binding).

Les modifications des outils peuvent être masquées à l'utilisateur par un environnement de développement tel que les outils d'assemblage disponibles avec WebSphere Application Server. Suivant les données indiquées dans le fichier XML, certaines méthodes qui étaient utilisées pour le service JAX-RPC peuvent également l'être avec peu ou pas de modifications dans un service JAX-WS. Certaines conditions requièrent également que des modifications soient apportées au service JAX-WS.

Du fait que les environnements EE Java mettent l'accent sur la compatibilité, la plupart des serveurs d'applications qui offrent la prise en charge des dernières spécifications JAX-WS et JAXB prennent également en charge la spécification JAX-RPC précédente. Il en résulte que les services Web existants peuvent rester de type JAX-RPC alors que les nouveaux services Web sont développés à l'aide des modèles de programmation JAX-WS et JAXB.

Cependant, au fur et à mesure de la révision ou de la réécriture des applications, il peut être parfois préférable de migrer un service Web de type JAX-RPC vers un service basé sur les modèles de programmation JAX-WS et JAXB. Ce peut être, par exemple, le cas lorsqu'un fournisseur choisit de proposer des améliorations des qualités de service disponibles uniquement dans les nouveaux modèles de programmation. Par exemple, la prise en charge de SOAP 1.2 et SOAP Message Transmission Optimization Mechanism (MTOM) est disponible uniquement dans les modèles de programmation JAX-WS 2.x et JAXB 2.x et pas dans JAX-RPC.

Les informations ci-dessous traitent des incidents qui peuvent se produire lors de la migration de JAX-RPC vers JAX-WS et JAXB.
Remarque : Lorsque les termes migrer migration et migré sont utilisés dans cette rubrique, sauf indication, il est fait référence au passage d'un environnement JAX-RPC à un environnement JAX-WS et JAXB.

Comparaison entre les modèles de programmation JAX-RPC et JAX-WS/JAXB

Si vous recherchez des informations supplémentaires décrivant les modification entre les modèles de programmation JAX-RPC d'une part et JAX-WS, JAXB, d'autre part, vous pouvez vous reporter aux conseils et astuces publiés par IBM developerWorks pour les services Web.

Modèles de développement

Les modèles de développement combinés de haut niveau pour JAX-RPC d'une part, et JAX-WS, JAXB, d'autre part, sont présentés dans la figure suivante : Compare development models

A un niveau supérieur, les modèles sont très similaires. La seule différence réside dans le fait que le modèle JAX-RPC génère des artefacts portables et non portables ; les modèles JAX-WS et JAXB ne génèrent pas d'artefacts non portables.

La figure ci-dessous contient les composants suivants :
  • Fichier WSDL (Web Services Description Language) : Un document conforme à la recommandation WSDL telle que publiée par l'organisation W3C.
  • (Facultatif) Fichiers de configuration :
    • Outil de génération WSDL vers Java : Les spécifications décrivent les mappages requis et pas le nom des outils. Généralement, l'outil utilisé pour JAX-WS et JAXB est wsimport, et wscompile et wsdeploy pour JAX-RPC.
    • Artefacts portables : Il s'agit de fichiers créés par l'outil de génération WSDL vers Java pour lesquels des mappages sont parfaitement définis dans les spécifications JAX-RPC ou JAX-WS/JAXB, suivant celle qui est applicable. Ces artefacts peuvent être utilisés sans modifications entre les différentes implémentations de JAX-RPC ou de JAX-WS et JAXB.
    • Artefacts non portables : Il s'agit de fichiers créés par l'outil de génération WSDL vers Java pour lesquels des mappages ne sont pas parfaitement définis dans les spécifications JAX-RPC ou JAX-WS/JAXB, suivant celle qui est applicable. Ces artefacts doivent généralement être modifiés entre les différentes implémentations de JAX-RPC ou JAX-WS/JAXB.
    • Code d'implémentation : Il s'agit du code requis pour répondre aux besoins particuliers d'une implémentation.
    • Informations de déploiement : Informations supplémentaires requises pour exécuter l'application dans un environnement particulier.
    • Fichier WAR (fichier d'archive Web) : Dans le contexte de l'image SampleService, un fichier WAR est un fichier d'archive contenant tous les éléments requis pour le déploiement d'un service Web dans un environnement particulier. On parle parfois de fichier WAR affiné.

Environnements de développement et d'exécution

Un environnement de développement spécialisé qui simplifie la migration des services Web en automatisant la plupart des tâches. Pour développer des application basées sur WebSphere, y compris des services Web, vous pouvez utiliser les outils d'assemblage fournis avec WebSphere Application Server.

Le code exemple fourni dans cette rubrique a été testé dans l'environnement d'exécution suivant :
  • IBM WebSphere Application Server V6.1, avec prise en charge de la spécification JAX-RPC.
  • IBM WebSphere Application Server V6.1 Feature Pack for Web Services, avec prise en charge des spécifications JAX-WS et JAXB.

Exemples

Les exemples suivants illustrent certaines des modifications qui peuvent être nécessaires pour migrer vos services Web JAX-RPC vers les services Web JAX-WS et JAXB. L'accent est particulièrement mis sur la modification du code d'implémentation que vous devez écrire à la fois côté client et côté serveur. S'il n'y a aucune nouvelle fonction à introduire, les modifications requises pour passer de JAX-RPC à JAX-WS et JAXB seront minimes.

Le premier exemple est un exemple de service Web basé sur JAX-RPC qui a été créé à partir d'un fichier WSDL (développement descendant) ; le même fichier WSDL est utilisé pour générer le service basé sur JAX-WS et JAXB. Le fichier WSDL décrit le service Web, SampleService, avec les opérations présentées dans la figure ci-dessous :

Comme illustré par la figure, les cinq opérations proposées sont :
  • xsd:int calcShippingCost(xsd:int, xsd:int)
  • xsd:string getAccountNumber(xsd:string)
  • xsd:dateTime calculateShippingDate(xsd:dateTime)
  • xsd:string ckAvailability(xsd:int) creates invalidDateFault
  • Person findSalesRep(xsd:string)
Considérez également que Person est défini par le fragment de schéma ci-dessous dans le fichier WSDL :
<complexType name="Personne">
	<sequence>
		<element name="name" type="xsd:string"/>
		<element name="age" type="xsd:int"/>
		<element name="location" type="impl:Address/>
	</sequence>
</complexType>
L'adresse est définie par :
<complexType name="Address">
	<sequence>
		<element name="street" type="xsd:string"/>
		<element name="city" type="xsd:string"/>
		<element name ="state" type="xsd:string"/>
		<element name="zip" type="xsd:int"/>
	</sequence>
</complexType>
La figure ci-dessous montre également que l'opération ckAvailability(xsd:int) génère une exception invalidDateFault. Sample service

Consultez le code de service créé par les outils. Les informations suivantes portent sur la vérification des éléments créés pour un environnement d'exécution JAX-RPC et également JAX-WS et JAXB.

Pour JAX-RPC, les outils acceptent le fichier WSDL comme entrée, et parmi les autres fichiers, génère les interfaces SampleService.java et SampleServiceImpl.java. L'interface SampleService.java définit une interface et le code généré peut être consulté dans le bloc de code ci-dessous. L'interface SampleServiceSoapBindingImpl.java fournit le squelette d'une implémentation que vous pouvez modifier pour ajouter votre propre logique.

Version JAX-RPC de SampleService.java :
/**  
* SampleService.java  
*  
* This file was auto-generated from WSDL  * by the IBM web services WSDL2Java emitter.  
* cf20633.22 v82906122346  
*/  
package simple;  
public interface SampleService extends java.rmi.Remote { 	
	public java.lang.Integer calcShippingCost(java.lang.Integer shippingWt, 			
		java.lang.Integer shippingZone) throws java.rmi.RemoteException;  	
	public java.lang.String getAccountNumber(java.lang.String accountName)  		
		throws java.rmi.RemoteException;  	
	public java.lang.String[] ckAvailability(int[] itemNumbers) 			
		throws java.rmi.RemoteException, simple.InvalidDateFault;  	
	public java.util.Calendar calculateShippingDate( 			
		java.util.Calendar requestedDate)                      
		throws java.rmi.RemoteException;  	
	public simple.Person findSalesRep(java.lang.String saleRepName) 			
		throws java.rmi.RemoteException; }   
Pour JAX-WS et JAXB, les outils acceptent le fichier WSDL comme entrée, et comme c'est le cas pour JAX-RPC, génèrent les interfaces SampleService.java et SampleServiceImpl.java. Comme pour JAX-RPC, l'interface SampleService.java définit également une interface, ainsi que le montre le bloc de code ci-dessous. L'interface SampleServiceImpl.java fournit le squelette d'une implémentation que vous pouvez modifier pour ajouter votre propre logique.
Remarque : Le code a été annoté par les outils.
Version JAX-WS et JAXB de l'interface SampleService.java :
package simple;  
	import java.util.List; 
	import javax.jws.WebMethod; 
	import javax.jws.WebParam; 
	import javax.jws.WebResult; 
	import javax.jws.WebService; 
	import javax.xml.datatype.XMLGregorianCalendar; 
	import javax.xml.ws.RequestWrapper; 
	import javax.xml.ws.ResponseWrapper;   

/**  
* This class was generated by the JAX-WS SI.  
* JAX-WS RI IBM 2.0_03-06/12/2007 07:44 PM(Raja)-fcs  * Generated source version: 2.0  
*   
*/ 
@WebService(name = "SampleService", targetNamespace = "http://simple") public interface SampleService {       

	/**      
	*       
	* @param shippingWt      
	* @param shippingZone      
	* @return      
	* returns java.lang.Integer      
	*/     
	@WebMethod     
	@WebResult(name = "shippingCost", targetNamespace = "")     
	@RequestWrapper(localName = "calcShippingCost", targetNamespace = "http://simple", className = "simple.CalcShippingCost")     
	@ResponseWrapper(localName = "calcShippingCostResponse", targetNamespace = "http://simple", 
className = "simple.CalcShippingCostResponse")     
	public Integer calcShippingCost(         
	@WebParam(name = "shippingWt", targetNamespace = "")         
	Integer shippingWt,         
	@WebParam(name = "shippingZone", targetNamespace = "")         
	Integer shippingZone);      

	/**      
	*       
	* 
	@param accountName      
	* @return      
	*     returns java.lang.String      
	*/     
	@WebMethod     
	@WebResult(name = "accountNumber", targetNamespace = "")     
	@RequestWrapper(localName = "getAccountNumber", targetNamespace = "http://simple", 
className = "simple.GetAccountNumber")     
	@ResponseWrapper(localName = "getAccountNumberResponse", targetNamespace = "http://simple", 
className = "simple.GetAccountNumberResponse")     
	public String getAccountNumber(         
		@WebParam(name = "accountName", targetNamespace = "")         
		String accountName);      
	/**      
	*       
	* @param requestedDate      
	* @return      
	*     returns javax.xml.datatype.XMLGregorianCalendar      
	*/     
	@WebMethod     
	@WebResult(name = "actualDate", targetNamespace = "")     
	@RequestWrapper(localName = "calculateShippingDate", targetNamespace = "http://simple", 
className = "simple.CalculateShippingDate")     
	@ResponseWrapper(localName = "calculateShippingDateResponse", targetNamespace = "http://simple", 
className = "simple.CalculateShippingDateResponse")     
	public XMLGregorianCalendar calculateShippingDate(         
		@WebParam(name = "requestedDate", targetNamespace = "")         
		XMLGregorianCalendar requestedDate);      
	/**      
	*       
	* @param itemNumbers      
	* @return      
	*     returns java.util.List<java.lang.String>      
	* @throws InvalidDateFault_Exception      
	*/     
	@WebMethod     
	@WebResult(name = "itemAvailability", targetNamespace = "")     
	@RequestWrapper(localName = "ckAvailability", targetNamespace = "http://simple", className = "simple.CkAvailability")     
	@ResponseWrapper(localName = "ckAvailabilityResponse", targetNamespace = "http://simple", 
className = "simple.CkAvailabilityResponse")     
	public List<String> ckAvailability(         
		@WebParam(name = "itemNumbers", targetNamespace = "")         
		List<Integer> itemNumbers)         
		throws InvalidDateFault_Exception     
	;      
	/**      
	*       
	* @param saleRepName      
	* @return      
	*     returns simple.Person      
	*/     
	@WebMethod     
	@WebResult(name = "salesRepInfo", targetNamespace = "")     
	@RequestWrapper(localName = "findSalesRep", targetNamespace = "http://simple", className = "simple.FindSalesRep")     
	@ResponseWrapper(localName = "findSalesRepResponse", targetNamespace = "http://simple", 
className = "simple.FindSalesRepResponse")     
	public Person findSalesRep(         
	@WebParam(name = "saleRepName", targetNamespace = "")         
	String saleRepName);  

}   

Comparaison des codes exemple

A première vue, les interfaces semblent avoir peu de similarités. Abstraction faite des informations supplémentaires ajoutées par les annotations effectuées pour JAX-WS et JAXB, les codes exemples sont similaires. Par exemple, pour la méthode calcShippingCost de la version JAX-WS et JAXB, les lignes de code suivantes existent :
@WebMethod     
	@WebResult(name = "shippingCost", targetNamespace = "")     
	@RequestWrapper(localName = "calcShippingCost", targetNamespace = "http://simple", className = "simple.CalcShippingCost")     
	@ResponseWrapper(localName = "calcShippingCostResponse", targetNamespace = "http://simple", 
className = "simple.CalcShippingCostResponse")     
	public Integer calcShippingCost(         
		@WebParam(name = "shippingWt", targetNamespace = "")         
		Integer shippingWt,         
		@WebParam(name = "shippingZone", targetNamespace = "")         
		Integer shippingZone);
Mais si vous supprimez les annotations, les lignes de code sont les suivantes :
public Integer calcShippingCost(
        Integer shippingWt,
        Integer shippingZone);
Ces lignes sont pratiquement identiques à ce qui a été généré pour JAX-RPC. La seule différence réside dans le fait que le code JAX-RPC peut générer l'erreur java.rmi.RemoteException comme suit :
public java.lang.Integer calcShippingCost(java.lang.Integer shippingWt,
			java.lang.Integer shippingZone) throws java.rmi.RemoteException;
Selon cette logique, trois des méthodes ont essentiellement les mêmes signatures :
public Integer calcShippingCost(Integer shippingWt, Integer shippingZone)
	public String getAccountNumber(String accountName)
	public Person findSalesRep(String saleRepName) 
Cela signifie que la migration de JAX-RPC vers JAX-WS n'affecte pas directement ces méthodes et que le code d'implémentation original exécuté avec succès dans l'environnement basé sur JAX-RPC peut selon toute probabilité être utilisé sans modification pour ces méthodes.

Cependant, deux des méthodes ont des signatures différentes :

Pour JAX-RPC :
public java.util.Calendar calculateShippingDate( 			
	java.util.Calendar requestedDate)  
public java.lang.String[] ckAvailability(int[] itemNumbers) 					
	throws java.rmi.RemoteException,                                  
	simple.InvalidDateFault
JAX-WS et JAXB :
public XMLGregorianCalendar calculateShippingDate( 			
	XMLGregorianCalendar requestedDate)  	
public List<String> ckAvailability(List<Integer> itemNumbers) 
	throws InvalidDateFault_Exception 
Remarque : Il pourra être plus facile de comparer les fichiers d'implémentation car il n'y a pas d'annotations dans SampleServiceImpl.java :
  • SampleServiceSoapBindingImpl.java
  • SampleServiceImpl.java
Les différences de signature s'expliquent par les raisons suivantes :
  • Mappages des différences des noms XML sur les noms Java

    Pour la méthode calculateShippingDate, le paramètre d'entrée et le paramètre de retour sont passés du type java.util.Calendar au type XMLGregorianCalendar. Ceci est dû au fait que WSDL à indiqué le type xsd:dateTime pour ces paramètres ; JAX-RPC mappe ce type de données sur java.util.Calendar, alors que JAX-WS et JAXB le mappent sur XMLGregorianCalendar.

  • Mappages différents de tableaux de XML vers Java

    Pour la méthode ckAvailability, la modification est due aux mappages de données pour les tableaux XML.

    JAX-RPC mappe les éléments WSDL suivants :
    <element maxOccurs="unbounded" name="itemNumbers" type="xsd:int"/>
    <element maxOccurs="unbounded" name="itemAvailability" type="xsd:string"/>
    Les éléments précédents sont mappés sur le source Java suivant :
    int[] itemNumbers
    java.lang.String[] itemAvailability
    JAX-WS et JAXB mappent les éléments WSDL suivants :
    List<Integer> itemNumbers 
    List<String> ckAvailability
  • Mappages différents d'exceptions
    Pour la méthode ckAvailability, le code JAX-RPC a généré l'erreur suivante :
    simple.InvalidDateFault
    Le code JAX-WS génère l'erreur suivante :
    InvalidDateFault_Exception
    Sauf en ce qui concerne les noms, les constructeurs sont différents pour ces exceptions. Par conséquent, le code JAX-RPC réel qui génère l'erreur peut s'afficher comme suit :
    throw new InvalidDateFault("this is an InvalidDateFault");
    Pour JAX-WS, le code utilise une commande similaire à ce qui suit :
    throw new InvalidDateFault_Exception(
    "this is an InvalidDateFault_Exception", new InvalidDateFault()); 
    Dans les cas ou des exceptions sont utilisées, le code qui utilise la commande doit être modifié.

Migration du code

Maintenant que les différences de code ont été décrites, consultez le code original pour identifier les méthodes qui nécessitent des modifications et savoir comment modifier ce code afin qu'il fonctionne dans un environnement JAX-WS et JAXB.

Considérons que le code d'implémentation original (JAX-RPC) est similaire à ce qui suit :
public java.util.Calendar calculateShippingDate(
     java.util.Calendar requestedDate) throws java.rmi.RemoteException {
// Set the date to the date that was sent to us and add 7 days.
requestedDate.add(java.util.Calendar.DAY_OF_MONTH, 7);

// . . .

return requestedDate;
}
Vous pouvez écrire le nouveau code pour utiliser directement les nouveaux types comme dans les exemples suivants :
public XMLGregorianCalendar calculateShippingDate(
XMLGregorianCalendar requestedDate) {
try {
// Create a data type factory.
DatatypeFactory df = DatatypeFactory.newInstance();
// Set the date to the date that was sent to us and add 7 days.
Duration duration = df.newDuration("P7D");
requestedDate.add(duration);

} catch (DatatypeConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// . . .

return requestedDate;
}
Lors de la migration du code pour la méthode ckAvailability, des modifications ont été nécessaires car le mode de mappage des tableaux et des exceptions à partir de XML est différent entre JAX-RPC et JAX-WS. Considérons que code de service Web JAX-RPC est semblable à ce qui suit :
public java.lang.String[] ckAvailability(int[] itemNumbers)
{
    
    String[] myString = new String[itemNumbers.length];
    for (int j = 0; j < myString.length; j++) {
 
            . . .
             if ( ... )

	   throw new simple.InvalidDateFault(“InvalidDateFault”);

            . . .
            if ( . . .) 
               myString[j] = “available:  “ + jitemNumbers[j] ;
            else
               myString[j] = “not available:  “ + jitemNumbers[j];
 
    }
    return myString;
}
Le code précédent accepte un élément int[] comme entrée et renvoie un élément String[]. Pour la version JAX-WS et JAXB, il s'agit des éléments List<Integer> et List<String>, respectivement. Lors du traitement de ces tableaux avec suppression du code Exception, le code JAX-RPC est similaire à ce qui suit :
public java.lang.String[] ckAvailability(int[] itemNumbers)
{
    
    String[] myString = new String[itemNumbers.length];
    for (int j = 0; j < jitemNumbers.length; j++) {
 

            . . .
            if ( . . .) 
               myString[j] = “available:  “ + itemNumbers.get(j);
            else
               myString[j] = “not available:  “ + itemNumbers.get(j); 
    }
    return myString;
}
Le code JAX-WS et JAXB équivalent ci-dessous existe et utilise des listes au lieu de tableaux :
List <String> ckAvailability(List <Integer> itemNumbers)
{
    
    ArrayList<String> retList = new ArrayList<String>();
    for (int count = 0; count < itemNumbers.size(); count++) {
 

            . . .
            if ( . . .) 
               retList.add(“available:  “ + itemNumbers.get(j));
            else
               retList.add(“not available:  “ + itemNumbers.get(j)); 
    }
    return retList;
}
Les différences dans les mappages d'exceptions de XML vers Java forcent le code JAX-WS à utiliser. InvalidDateFault_Exception au lieu de InvalidDateFault.
Cela signifie que vous devez remplacer throw new simple.InvalidDateFault(“InvalidDateFault”); par un autre code. En conséquence, la ligne suivante est utilisée pour le nouveau code :
throw new InvalidDateFault_Exception( "test InvalidDateFault_Exception", new InvalidDateFault());  
L'implémentation JAX-WS et JAXB finale de la méthode peut être similaire au code suivant :
List <String> ckAvailability(List <Integer> itemNumbers)
{
    
    ArrayList<String> retList = new ArrayList<String>();
    for (int count = 0; count < itemNumbers.size(); count++) {
 
if ( . . . ) {
   throw new InvalidDateFault_Exception(
   "test InvalidDateFault_Exception",
   new InvalidDateFault());
}

. . .
if ( . . .) 
   retList.add(“available:  “ + itemNumbers.get(count));
else
   retList.add(“not available:  “ + itemNumbers.get(count)); 
   }
   return retList;
}
Vous avez le choix entre plusieurs méthodes pour migrer le code. Avec l'expérience et un environnement de développement efficace, la migration de JAX-RPC vers JAX-WS s'effectue sans difficulté.

Icône indiquant le type de rubrique Rubrique de référence



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rwbs_migjaxrpc2jaxws
Nom du fichier : rwbs_migjaxrpc2jaxws.html