Ce billet complète la série de billets sur les Services Web. Il s’agit d’une actualisation de la série dans le cadre d’une utilisation avec le serveur d'application WebSphere 8.5.5 et Java 1.7.
Vous pouvez trouver le début de la série à l’url suivante :
http://jl2tho.blogspot.fr/2011/11/tutorial-approche-contract-first-avec.html. Elle présente la création d'un service web avec les annotations JAX-WS et JAXB.
La norme JAX-WS a pour objectif d'assurer la portabilité des services web réalisés à travers les différents serveurs d'application. Néanmoins, on constate que le passage d'un serveur JEE à un autre peut nécessiter un certain nombre d'adaptations.
Ce billet a pour objectif de préciser les modifications faites pour assurer le déploiement du service web sur WebSphere 8.5. Il a également vocation à conserver une trace des erreurs spécifiques rencontrées dans le déploiement du service.
On verra que la modification principale a concerné la simplification du fichier web.xml.
Environnement de travail
Un environnement de travail mal maitrisé est une des sources principales de problèmes dans la mise en œuvre des services web. C'est pour cette raison que je précise l'environnement utilisé pour réaliser mon test.
L'élément le plus important est l'utilisation à la fois en développement et en exploitation d'un JDK 1.7. L'utilisation d'une version différente (et surtout inférieure) nécessitera probablement de nombreuses adaptations.
J’ai utilisé un Eclipse Luna (version 4.4) for JEE Web developper sur un MacOs Yosemite. Le JDK utilisé pour la compilation est un JDK 1.7.
Les tests ont été réalisés sur un WebSphere tournant dans une VM Virtual Box de type Fedora.
Le runtime Java utilisé est le 1.7.
L’utilisation d’un JDK 1.7 est importante car elle a permis de s’affranchir de l’ajout de Jar dans la configuration du projet Eclipse. Le JDK 1.7 contient la description des interfaces JAX-WS et JAXB.
L’utilisation d’un runtime Java 1.7 pour WebSphere est importante car il existe un certain nombre de remarques sur le Web indiquant des problèmes quand le WebSphere est configuré avec une version 1.6 du runtime Java.
Création du projet
Cette étape fait référence au billet :
http://jl2tho.blogspot.fr/2011/11/etape-2-du-tutorial-configuration-dun.html
Nous créons comme dans le billet, un projet de type Dynamic Web : c’est important pour avoir une structure de projet Web.
J’utilise comme server runtime le Tomcat 8.0 que j’utilise pour mes autres projets.
La version du serveur d'application n'a pas grande importance, il ne sera pas utilisé autrement que pour en déduire l'environnement de compilation : ce qui a de l'importance c'est le runtime java 1.7 qu'il utilise.
Mon serveur Tomcat 8.0 utilise un runtime Java 1.7.
Pour éviter les problèmes, je vous recommande l'utilisation d'un serveur JEE configuré avec un runtime 1.7.
Lors de la création du projet, je force le « Dynamic Web Module version » pour prendre la 3.0.
Attention à ne pas utiliser une version antérieure avec WebSphere 8.5. Cela semble poser des problèmes.
C'est l'unique différence dans la phase de création d'un projet avec le billet d'origine.
Pour le test, on a coché l’option « Generate web.xml deployment descriptor ».
Une fois le projet Eclipse créé, je n'ai pas eu besoin d'ajouter aucun jar pour disposer des annotations JAX-WS et JAXB. Ces annotations sont incluses (depuis la 1.7) dans le runtime Java.
Ce point est une différence vis à vis du tutoriel.
Configuration du web.xml
Par rapport au billet d'origine (
http://jl2tho.blogspot.fr/2011/11/etape-2-du-tutorial-configuration-dun.html), c'est le contenu du fichier web.xml qui a été la source de tous les problèmes rencontrés lors de nos tests.
Dans WebContent/WEB-INF/web.xml, j’ajoutai, dans le tutoriel, la déclaration du web service en définissant un mapping d’url du type « /* ».
<servlet>
<servlet-name>WebContractHelpdesk</servlet-name>
<servlet-class>fr.j2ltho.webcontracthelpdesk.server.HelpdeskServiceBean</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WebContractHelpdesk</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Il n’est plus nécessaire de modifier le web.xml : la déclaration de la servlet est inutile. C’est même pour WebSphere une source d’erreur.
Avec la déclaration de ma servlet et de son mapping, j’avais initialement l’erreur suivante au démarrage de l’application:
[29/05/15 11:27:26:212 CEST] 00000087 WASSessionCor I SessionContextRegistry getSessionContext SESN0176I: Un nouveau contexte de session va être créé pour la clé d'application default_host/exContartFirst
[29/05/15 11:27:26:294 CEST] 00000087 webapp W com.ibm.ws.webcontainer.webapp.WebApp initializeStaticFileHandler SRVE0278E: Erreur lors de l'ajout du mappage de servlet --> /*.
La documentation WebSphere recommande l’ajout d’un fichier ibm-web-ext.xml dans le WebContent/WEB-INF du projet.
SRVE0278E: Erreur lors de l''ajout du mappage de servlet --> {0}.
Explication
Il s'agit d'une erreur d'application.
Action
Définissez fileServingEnabled=false dans le fichier ibm-web-ext.xmi situé dans le dossier WEB-INF.
J'ai donc créé le fichier ibm-web-ext.xml (attention en WebSphere 8.5, c’est bien une extension xml qu’il faut utiliser) avec le contenu suivant :
L’erreur s’est alors transformée en :
[29/05/15 14:07:30:667 CEST] 000000ff WSModuleDescr E WSWS7027E: Les descriptions de service JAX-WS n'ont pas pu être générées correctement en raison de l'erreur suivante : javax.servlet.ServletException: WSWS7067E: Le servlet WebContractHelpdesk ne peut pas spécifier le caractère * comme masque d'URL.
at com.ibm.ws.websvcs.desc.WSModuleDescriptorImpl.updateEndpointURLS(WSModuleDescriptorImpl.java:1550)
at com.ibm.ws.websvcs.desc.WSModuleDescriptorImpl.buildJAXWSServices(WSModuleDescriptorImpl.java:1313)
On notera que cette seconde erreur survient à l’installation/déploiement du war.
Ce second message est clair : le pattern /* n'est pas apprécié par le module JAX-WS de WebSphere.
J'ai également constaté dans les exemples d'implémentation de la norme JAW-WS, que le servlet restait vide.
En conséquence, j'ai corrigé le web.xml afin d'obtenir cette version qui sera la finale
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>JaxWsContractFirst</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Cette version résout le problème et permet de se passer du fichier ibm-web-ext.xml qui est donc inutile pour notre test.
Vous noterez le numéro de version à 3.0 et sa cohérence avec le web_app_3_0.xsd. Ce point peut être important pour un serveur WebSphere 8.5 : on trouve beaucoup de billets indiquant des problèmes quand le numéro de version n'est pas 3.0.
Suppression des annotations EJB
Mon tutorial s’appuyait sur la création d’un EJB que l’on
transformait ensuite en Web Service.
Ainsi dans le billet :
http://jl2tho.blogspot.fr/2011/12/etape-4-annotations-jax-ws-et-jaxb-des.html
on ajoute plusieurs annotations celles des EJB et celles spécifiques
aux Services Web.
Pour simplifier ma configuration et la rendre plus portable (certain
container WebService comme CXF ne supporte pas les EJB), j’ai
supprimé les annotations suivantes :
-
@Remote au niveau de l’interface
-
@Stateles au niveau du bean implémentant l’interface.
ll s’agit d’une suppression simple : elles n’ont pas été
remplacée par une autre annotation.
Déploiement dans WebSphere 8.5
Je n’utiliserai pas la fonctionnalité de test intégré à
Eclipse, car je n'ai jamais eu la patience de configurer mon Eclipse
pour qu'il fonctionne en développement avec WebSphere.
La solution repose, sur la production d'un war que je déploie
ensuite dans WebSphere.
La première étape est la réalisation du war. Il est créé
manuellement depuis Eclipse grâce à la fonctionnalité
Export
-> Export war.
Mon war porte le nom de mon projet Eclipse :
JaxWsContractFirst.war
Pour réaliser le déploiement sur WAS 8.5, il faut se connecter à
la console d'administration.
Attention ! Dans WebSphere, le port de la console
d'administration diffère de celui des applications. Dans mon cas,
l'url était : http://vmwebsphere:9060/ibm/console
Une fois connecté, on ouvre le nœud Application puis on clique sur
le lien « Nouvelle application ».
Le panneau « Nouvelle application » apparaît.
On clique sur le lien « Nouvelle application d'entreprise ».
Le panneau « Préparation de l'installation de l'application »
s'affiche.
Dans chemin de la nouvelle application, on sélectionne « Système
de fichiers local » pour récupérer un fichier qui se trouve
sur l'ordinateur qui exécute le navigateur.
Pour information, le système de fichiers éloigné fait référence
aux disques du serveur sur lequel s'exécute le serveur WebSphere.
On utilise le bouton parcourir pour récupérer le war que l'on a
créé plus tôt.
Si on clique sur Suivant, on arrive à l'écran du choix « Comment
voulez-vous installer l'application ?».
Je sélectionne l'option Raccourci - Ne demander que si des
informations supplémentaires sont requises. »
Ensuite, on conserve le défaut jusqu’à l’étape 4 « Mappage
des racines de contexte des modules Web » pour laquelle on
complète la colonne « Racine du contexte » avec la
valeur /wsContractFirst.
Cette valeur est libre à condition qu’il n’existe pas d’autres
applications sur le serveur qui utilise la même valeur.
Ensuite, on conserve les valeurs par défaut jusqu’à la fin.
On termine en appuyant sur le lien « Sauvegarder ».
Si on retourne sur les « Applications d’entreprise
WebSphere », on doit avoir dans la liste une application
« JaxWsContractFirst_war » dont l’état est Arrêter
(croix rouge).
Si on clique sur le lien « JaxWsContractFirst_war » on
obtient la page « Application d’entreprise >
JaxWsContractFirst_war.
Cette page doit impérativement contenir un pavé « Propriétés
des services Web ».
Le lien « Publication des fichiers WSDL » permet la
récupération du fichier WSDL et XSD. C’est le seul mécanisme
pour avoir accès à la totalité du WSDL.
Attention, si le pavé « Propriétés des services Web »
n’est pas présent, c’est qu’une erreur a eu lieu lors du
déploiement.
Pour en savoir plus, vous pouvez aller dans le répertoire :
/opt/IBM/WebSphere/AppServer/profiles/NatSystemWAS/logs/natsystem où
natsystem est le nom du serveur.
Le fichier SystemOut.log contient les erreurs.
Il faut ensuite démarrer l’application depuis la page
« Applications d’entreprise ».
Une fois, démarrée, la page
http://vmwebsphere:9080/wsContractFirst/WebContractHelpdesk?WSDL
doit renvoyer le WSDL.
Si vous obtenez, l’erreur suivante :
Error 404:
com.ibm.ws.webcontainer.servlet.exception.NoTargetForURIException: No
target servlet configured for uri:
/wsContractFirst/WebContractHelpdesk
Cela peut vouloir dire que vous avez oublié de la démarrer ou
qu’une erreur a eu lieu lors du démarrage.
Quelques erreurs de déploiement
Property {} is present but not
specified in @XmlType.propOrder
On a dans la log, une première erreur :
[01/06/15 13:56:28:883 CEST] 00000090 WSModuleDescr E WSWS7027E:
Les descriptions de service JAX-WS n'ont pas pu être générées
correctement en raison de l'erreur suivante :
javax.xml.ws.WebServiceException: WSWS7054E: Le fichier WSDL (Web
Services Description Language) n'a pas pu être généré pour la
classe d'implémentation du service Web
fr.j2ltho.webcontracthelpdesk.server.HelpdeskServiceBean en raison de
l'erreur suivante : javax.xml.ws.WebServiceException: Unable to
create JAXBContext
at
com.ibm.ws.websvcs.wsdl.WASWSDLGenerator.generateWsdl(WASWSDLGenerator.java:238)
at
org.apache.axis2.jaxws.description.impl.EndpointDescriptionImpl.generateWSDL(EndpointDescriptionImpl.java:2084)
at
org.apache.axis2.jaxws.description.impl.EndpointDescriptionImpl.<init>(EndpointDescriptionImpl.java:449)
Caused by: java.security.PrivilegedActionException:
com.ibm.jtc.jax.xml.bind.v2.runtime.IllegalAnnotationsException: 1
counts of IllegalAnnotationExceptions
Property lastModification is present but not specified in
@XmlType.propOrder
this problem is related to the following location:
at private java.util.Date
fr.j2ltho.webcontracthelpdesk.server.QuestionMsg.lastModification
at fr.j2ltho.webcontracthelpdesk.server.QuestionMsg
at private fr.j2ltho.webcontracthelpdesk.server.QuestionMsg
fr.j2ltho.webcontracthelpdesk.server.jaxws.CreateQuestion.inputQUESTION
at fr.j2ltho.webcontracthelpdesk.server.jaxws.CreateQuestion
La propriété indiquée (en l’occurence lastModification) de la
classe indiquée (QuestionMsg) possède une annotation @XmlElement
mais n’est pas présente dans la liste propOrder de l’annotation
@XmlType de la classe.
Soap UI dispose d’une fonctionnalité « New SOAP project »
qui permet à partir d’un « Initial WSDL », la
génération d’un jeu de requête pur ce WSDL.
Pour importer, le WSDL, il faut le récupérer depuis la console
d’administration (comme décrit précédemment) puis le dezipper
dans un répertoire.
Ensuite, on pointe sur le fichier récupéré.
Ce billet complète la série sur les Web Services en l'actualisant
dans un contexte WebSphere 8.5 et un JDK 1.7
Je ne connaissais pas cette alternative mais pour ma part j'utilise ScribeFire http://www.scribefire.com/ une petite extension firefox qui utilise le correcteur orthographique (français ou autre de firefox) et qui permet d'importer des images. Je publie tous les billets de mes 2 blogs (http://certificats.blogspot.com/ et un autre blog perso dont je ne souhaite pas publier l'adresse) avec Scribefire.
RépondreSupprimerMais je testerai WLW pour me faire une idée.
BOnjour,
RépondreSupprimerJ'aime beaucoup WLW pour rediger mes billets et depuis qques temps j'ai une erreur 403 lorsque que je veux passer à la publication.
Savez-vous ce que cela signifie?
Audrwey
Je ne connais pas cette erreur mais elle est très proche des codes erreurs http 403 et 404 : on dirait qu'il y a un problème de connexion Internet : pc deconnecté serveur ne répondant plus... Peut être l'adresse du serveur a été modifiée...
RépondreSupprimerQuelle plateforme de blog est utilisée ?