JAX-WS sur Axis2 1.5.4 / Tomcat 7

mars 8th, 2011 by Gibello

Point de départ : vous disposez d’un fichier jar contenant au moins une classe annotée JAX-WS (ou JSR 181, c’est pareil).

Exemple (à compiler et packager dans un jar, les tutos JAX-WS ne manquent pas) :

package calculette;
import javax.jws.*;

@WebService
public class Calculette {
  @WebMethod
  public int addition (int n1, int n2) { return n1 + n2; }
  @WebMethod
  public int soustraction (int n1, int n2) { return n1 - n2; }
}

Donc : installez axis2 (lancez Tomcat, et copiez axis2.war dans le répertoire webapps).

Ensuite : il manque le répertoire « servicejars » dans axis2/WEB-INF !
Donc, créez-le.

Il vous suffit maintenant de copier votre jar (celui du web service) dans le nouveau répertoire « servicejars », et Axis2 déploiera le Web Service (vérifiez dans logs/catalina.out, ou dans la console d’admin d’Axis2).

Reste un bug lors de l’accès au WSDL : le WSDL 2 fonctionne bien (url-de-votre-endpoint?wsdl2), mais le WSDL 1 (celui dont vous avez généralement besoin : url-de-votre-endpoint?wsdl) donne l’erreur suivante :

<error>
<description>Unable to generate WSDL 1.1 for this service</description>
−
<reason>
If you wish Axis2 to automatically generate the WSDL 1.1, then please set useOriginalwsdl as false in your services.xml
</reason>
javax.xml.ws.WebServiceException: Error occurred generating WSDL file for Web service implementation class {calculette.Calculette}: {java.lang.ClassNotFoundException: com.sun.tools.ws.spi.WSToolsObjectFactory}
	at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.generateWsdl(JAXWSRIWSDLGenerator.java:187)
	at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.initialize(JAXWSRIWSDLGenerator.java:371)
	at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.getWSDL(JAXWSRIWSDLGenerator.java:364)
	at org.apache.axis2.description.AxisService.printWSDL(AxisService.java:1340)
	at org.apache.axis2.transport.http.ListingAgent.processListService(ListingAgent.java:199)
	at org.apache.axis2.transport.http.AxisServlet.doGet(AxisServlet.java:254)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.ws.spi.WSToolsObjectFactory
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at org.apache.axis2.jaxws.description.builder.JAXWSRIWSDLGenerator.generateWsdl(JAXWSRIWSDLGenerator.java:166)
	... 22 more
</error>

Pour corriger ce problème, il faut faire pointer le CLASSPATH de Tomcat vers certaines librairies de votre JDK : dans mon cas (JDK 1.6.0_18),
lib/tools.jar et jre/lib/javaws.jar .

Le plus simple est d’ajouter dans le répertoire bin/ de Tomcat un fichier setenv.sh (ou .bat pour les amateurs de Windows, je suppose ?), dont je vous livre le contenu ci-dessous (adaptez à votre système et à vos répertoires) :

#!/bin/sh
echo "Hello from setenv.sh"
export CLASSPATH=/usr/local/java/lib/tools.jar:/usr/local/java/jre/lib/javaws.jar

Ensuite, relancez Tomcat. Votre session devrait ressembler à ceci (notez la trace « Using CLASSPATH: », en bas) :

gibello@colibri:~/apache-tomcat-7.0.8$ bin/startup.sh
Hello from setenv.sh
Using CATALINA_BASE:   /home/gibello/apache-tomcat-7.0.8
Using CATALINA_HOME:   /home/gibello/apache-tomcat-7.0.8
Using CATALINA_TMPDIR: /home/gibello/apache-tomcat-7.0.8/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/java/lib/tools.jar:/usr/local/java/jre/lib/javaws.jar:/home/gibello/apache-tomcat-7.0.8/bin/bootstrap.jar:/home/gibello/apache-tomcat-7.0.8/bin/tomcat-juli.jar

Et surtout, l’accès au WSDL doit maintenant fonctionner… Ouf, moi qui croyais que JAX-WS c’était « plug and play » !

Installer WebSphere 6.1 + Web Services Feature Pack sur Ubuntu

janvier 19th, 2011 by Gibello

Ce post est destiné aux archéologues du web, qui pourraient avoir encore besoin d’un WebSphere 6, le cas échéant avec des Web Services déployés dessus…
Bonne chance pour télécharger WAS et le Web Services Feature Pack (voir ci-dessous). Si vous y parvenez… cette doc pourra vous être utile (d’autant que Ubuntu n’est normalement pas une plateforme supportée par WAS).

Téléchargement

Pas forcément le plus simple… IBM ne donne guère dans le shareware ;)
Vous devrez vous enregistrer pour obtenir un « IBM ID » servant ensuite à montrer patte blanche… puis à chaque fois, remplir quelques formulaires.

Ci-dessous, les URLs et noms des fichiers que j’ai utilisés… en espérant qu’IBM les maintienne en ligne encore quelques temps.

Pour télécharger WAS :
http://www.ibm.com/developerworks/downloads/ws/was/?S_CMP=TRIALS
(et « Previous version(s) » en bas de page).
Télécharger was.cd.6100.trial.base.linux.ia32.tar.gz .

Pour télécharger le « Web Services Feature Pack » :

https://www14.software.ibm.com/webapp/iwm/web/reg/download.do?source=swg-wasfpws&lang=en_US&S_PKG=linux&cp=UTF-8

Télécharger 6.1.0-WS-WAS-WSFEP-LinuxX32.tar.gz .

Installation de WAS 6.1 (sur Ubuntu 10.04 LTS)

D’abord, extrayez l’archive tar/gz, et allez dans le répertoire was61 .

Pour moi, tout a alors commencé par une erreur avec l’installeur (WAS/install) :
Le programme d’installation ne peut pas être exéctuté en mode graphique. Essayez d’exécuter le programme d’installation avec la commande -console ou -silent.

Donc, passage à l’installation manuelle (-silent) :
Editer WAS/install, et positionner DONT_REDIRECT=true (pour avoir des traces).

Créer votre répertoire d’install :
mkdir /mon_repertoire_d_install/WasTest

Installer :
WAS/install
-OPT silentInstallLicenseAcceptance="true"
-OPT allowNonRootSilentInstall="true"
-OPT disableOSPrereqChecking="true"
-OPT installType="installNew"
-OPT feature=samplesSelected
-OPT PROF_samplesPassword=test
-OPT PROF_enableAdminSecurity="true"
-OPT PROF_adminUserName=admin
-OPT PROF_adminPassword=admin
-OPT installLocation="/mon_repertoire_d_install/WasTest"
-silent

En cas d’échec : logs dans /mon_repertoire_d_install/WasTest/logs/install/log.txt

En cas de succès, message :
INSTCONFSUCCESS: Réussite : Le profil AppSrv01 existe. Pour plus d’informations sur ce profil, consultez /mon_repertoire_d_install/WasTest/profiles/AppSrv01/logs/AboutThisProfile.txt.

Si vous n’installez pas le Web Services Feature Pack, vous pouvez vous arrêter là.
Auquel cas, pour lancer votre serveur :

  • Aller dans /mon_repertoire_d_install/WasTest
  • Lancer : bin/startServer.sh server1

Les infos sur les ports (http/https/soap…) sont dans /mon_repertoire_d_install/WasTest/profiles/AppSrv01/logs/AboutThisProfile.txt

Test (ports valables seulement sans installation du Web Services Feature Pack, sinon, voir plus bas) :
SnoopServlet : http://localhost:9080/snoop
Console d’admin : https://localhost:9043/ibm/console/logon.jsp

Installation du Web Services Feature Pack

  • Extraire 6.1.0-WS-WAS-WSFEP-LinuxX32.tar.gz dans un répertoire créé pour l’occasion.
  • Descendre dans le sous-répertoire WSFP.
  • Editer « install », et mettre DONT_REDIRECT=true (pour avoir des traces).

Arrêter WebSphere, s’il tourne : dans /mon_repertoire_d_install/WasTest, exécuter : bin/stopServer.sh server1

Lancer install avec les options suivantes :

-OPT silentInstallLicenseAcceptance="true"
-OPT allowNonRootSilentInstall="true"
-OPT disableOSPrereqChecking="true"
-OPT disableNonBlockingPrereqChecking="true"
-OPT installLocation="/mon_repertoire_d_install/WasTest"
-OPT createProfile="true"
-OPT profileType="standAlone"
-OPT PROF_enableAdminSecurity="true"
-OPT PROF_adminUserName=admin
-OPT PROF_adminPassword=admi-n
-OPT PROF_profilePath=/mon_repertoire_d_install/WasTest/profiles/WSProfile
-OPT PROF_profileName=WSProfile
-OPT PROF_isDefault="true"
-silent

Il est également possible d’éditer le fichier responsefile.WEBSV.txt, d’y positionner ces options, et de lancer :
install -options responsefile.WEBSV.txt -silent

Note : l’erreur suivante, si elle se produit, semble pouvoir être ignorée :
INSTCONFPARTIALSUCCESS : Le profil existe mais des erreurs se sont produites. Pour plus d’informations, consultez /mon_repertoire_d_install/WasTest/logs/manageprofiles/WSProfile_create.log.

Lancement de WAS

Dans /mon_repertoire_d_install/WasTest :
bin/startServer.sh server1

La console d’admin est maintenant sur :
https://localhost:9044/ibm/console
(les webapps déployées se trouvent sur localhost:9081).

Enjoy !

Et pour réinstaller (ou désinstaller) ?

Dans le répertoire racine de l’utilisateur (genre /home/moi), supprimer le répertoire .ibm et le fichier vpd.properties.

Supprimer ensuite le répertoire où vous avez installé WAS.

Et voilà… vous pouvez réinstaller, ci besoin (par exemple, en cas d’erreurs incompréhensibles, ou pour changer les options, etc…)

Génération d’un keystore JKS contenant un certificat signé (openssl + keytool)

décembre 2nd, 2010 by Gibello

Petite recette pour générer un keystore java (JKS) contenant un certificat signé par une autorité de certification (CA ou « certificate authority), en utilisant openssl et keytool… Très utile, par exemple, pour activer SSL.

(note : j’ai mis « motDePasse » partout, comme mot de passe, y compris quand openssl ou keytool le demandent au prompt… le plus simple étant de remplacer çà par le votre, et d’utiliser aussi le même partout !)

Tout d’abord, si vous ne diposez pas déjà d’un certificat provenant d’une autorité de certification (CA – « certificate authority »,  comme par exemple Verisign, Gandi ou CertEurope), vous allez créer votre propre CA (et son certificat, qui sera utilisé pour signer le votre) :


openssl genrsa -out ca.key


openssl req -new -x509 -days 365 -key ca.key -out ca.crt

A partir de là, on considèrera que le certificat de la CA est « ca.crt » (qu’il provienne d’une véritable autorité de certification, ou que vous l’ayez créé vous-même, comme ci-dessus).

Vous allez maintenant créer votre clé privée (server.key), et un « certificate signing request » (CSR) utilisée pour demander à la CA de vous produire un certificat signé :


openssl genrsa -out server.key


openssl req -new -key server.key -out server.csr

Maintenant, muni du certificat de la CA et de votre CSR, vous allez générer votre certificat signé par la CA (server.crt) :


openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Bien… Vous disposez de tout ce qu’il faut pour activer SSL, par exemple : à savoir, un certificat signé (server.crt) et une clé privée (server.key).

Supposons maintenant que vous souhaitez importer ceci dans un « keystore » java au format JKS (utilisé, par exemple, pour activer SSL dans un serveur d’appli java, comme jetty) : il faudra y stocker le certificat + la clé privée.

C’est possible avec keytool depuis le JDK 1.6 (sic… avant, il fallait écrire du code pour importer la clé !), moyennant quelques « incantations » : à savoir, génération d’un keystore au format PKCS12 contenant la clé + le certificat, et import de ce keystore dans un nouveau keystore au format JKS.


openssl pkcs12 -export -in server.crt -inkey server.key -out keystore.p12 -name monAlias -CAfile ca.crt -caname root


keytool -importkeystore -deststorepass motDePasse -destkeypass motDePasse -destkeystore server.jks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass motDePasse -alias monAlias

Et voilà : votre keystore s’appelle server.jks ! Ouf…

Note : en ce qui concerne Petals, cetet recette sera utile pour activer SSL dans des composants encore en gestation, à l’heure où cet article est publié : à savoir, la prochaine release du BC-SOAP, et le BC-PRESTO (déjà disponibles dans les sources de Petals).

P.S. L’absence de clé privée dans le keystore (si vous y importez uniquement le certificat, par exemple) peut être la cause d’erreurs assez peu explicites. Dans mon cas :
- côté client (FireFox), « Impossible de communiquer en mode sécurisé avec le pair : aucun algorithme de chiffrement en commun (Code d’erreur : ssl_error_no_cypher_overlap) ».
- côté serveur (Jetty), « javax.net.ssl.SSLHandshakeException: no cipher suites in common »

Comment utiliser le SE-POJO (en 1 leçon)

mars 1st, 2010 by Gibello

Avez-vous entendu parler du SE-POJO ?

Son principal avantage : pouvoir assez simplement scripter en java des traitements internes à Petals, éventuellement complexes. Par exemple :

  • Consommer des Endpoint, les orchestrer librement en fonction de conditions.
  • Faire des traitements spécifiques (comme lire un fichier à un format exotique, le convertir en XML, et l’envoyer à un autre Endpoint)
  • Etc…

Le problème, c’est que le POJO est assez peu documenté, à ce jour : la doc est quand même utile, donc lisez-là (http://download.forge.objectweb.org/petals/petals-se-pojo-2.0.2-en.pdf).

Etape 1 : Développer un POJO compatible avec Petals et le SE-POJO

Sous PetalsStudio :

- Créer un projet java « classique », qui contiendra le code de votre POJO. Ce projet aura besoin de librairies de Petals, notamment celles du CDK (component development kit).

Le meilleur moyen de se les procurer, c’est de dézipper un composant : par exemple, téléchargez le SE-POJO (de toutes façons, vous en aurez besoin), et dézippez-le.

Les librairies dont vous aurez besoin sont les suivantes ([version] désigne les numéros de version, qui peuvent varier… selon la version ! Prenez celles qui sont dans votre composant POJO) :

  • petals-jbi-[version].jar
  • petals-cdk-jbidescriptor-[version].jar
  • petals-cdk-api-[version].jar
  • petals-cdk-core-[version].jar

Copiez ces librairies dans un répertoire de votre projet java (par exemple, un répertoire « lib/ »), et faites pointer le « Build path » d’Eclipse dessus.

- Créez un package et une classe dans les sources : ce sera l’implémentation de votre POJO.

Voici un exemple (cet exemple consomme un autre EndPoint : dans mon cas, un « FileTransfer » pour enregistrer le message, soit une SU déployée sur le BC-FILETRANSFER. Mais vous pouvez commenter tout le code qui consomme cet Endpoint, et vous contenter d’un POJO genre « Hello world » !) :


package org.ow2.petals.test;

import java.io.StringReader;

import javax.jbi.component.ComponentContext;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;

import org.ow2.petals.component.framework.api.Message.MEPConstants;
import org.ow2.petals.component.framework.api.message.Exchange;
import org.ow2.petals.component.framework.jbidescriptor.generated.Consumes;
import org.ow2.petals.component.framework.listener.AbstractJBIListener;

public class TestPojo {
  AbstractJBIListener jbiListener;
  ComponentContext ctx;

  public void setJBIListener(AbstractJBIListener jbiListener) {
    this.jbiListener = jbiListener;
  }
  public void setComponentContext(ComponentContext ctx) {
    this.ctx = ctx;
  }

  public boolean onExchange(Exchange exchange)
  throws Exception {

    // Consume a "provides" endpoint (referenced by Interface/Service/Endpoint name,
    // as specified in the "provides" endpoint's jbi.xml)
    Consumes ep = new Consumes();
    ep.setInterfaceName(new QName("http://petals.test.com", "WriteContentInterface"));
    ep.setServiceName(new QName("http://petals.test.com", "WriteContent"));
    ep.setEndpointName("TestFileEndpoint");

    System.out.println("POJO: before consume");
    Exchange out =
       jbiListener.createConsumeExchange(ep,MEPConstants.IN_ONLY_PATTERN);
    out.setInMessageContent(
       new StreamSource(new StringReader(
         "<pojo>Hello from Pojo !</pojo>")));

    jbiListener.sendSync(out);
    System.out.println("POJO: consume done");

    // Answer if needed (In[Optional]Out)
    if(exchange.isInOutPattern() || exchange.isInOptionalOutPattern()) {
      System.out.println("POJO: sending response");
      exchange.setOutMessageContent(
         new StreamSource(new StringReader("<pojo>Ok</pojo>")));
    }

    return true;
  }

  public void init() {
    System.out.println("SamplePojo inits.");
  }
}

- Une fois votre POJO prêt, vous devrez le packager sous forme de fichier .jar (File/Export/General/Java/Jar file).
Le fichier .jar résultant pourra ensuite être intégré à votre SU POJO.

Etape 2 : Créer la SU pour y intégrer votre POJO

Sous PetalsStudio : File / New / Project / Petals / Use a Petals Technical Service / Use POJO.

Dans la fenêtre « WSDL File » (etc…)

  • Spécifiez des « namespace » identiques pour l’interface et le service (çà doit ressembler à des URL… exemple : http://pojo.test.org).
  • Nommez vos Interface / Service / Endpoint à votre convenance.
  • Inutile de spécifier un WSDL.

Dans la fenêtre « Jar Files » (etc…)

  • Donnez le chemin d’accès vers le jar créé lors de l’étape précédente (bouton « browse », sélectionnez le fichier jar)
  • Faites ensuite « Browse » pour la boîte « Service Class », vous pourrez y choisir la classe du POJO présent dans votre jar.

Terminez le processus (allez jusqu’à « Finish », et cliquez dessus).

PetalsStudio va alors générer un projet « su-POJO-<nom-du-projet>-provide, avec un dossier « resources/ » contenant le fichier jar du POJO, et un dossier META-INF contenant le descripteur de déploiement Petals (jbi.xml).

Attention : la version 1.0 Beta2 de PetalsStudio comporte un bug… à tout hasard, éditez META-INF/jbi.xml. Si vous y trouvez la chaîne suivante :

« http://petals.ow2.org/components/extensions/version-4.0″

remplacez « 4.0″ par « 5″, comme ceci :

« http://petals.ow2.org/components/extensions/version-5″

(puis sauvegardez).

Cliquez le projet avec le bouton droit, puis « Petals / Package for Petals ».

Vous aurez alors un fichier « sa-POJO-<nom-du-projet>-provide.zip », prêt à être déployé dans Petals (comme SU associée au SE-POJO).

Etape 3 : Déploiement sur Petals

  • Démarrez Petals
  • Déployez le SE-POJO
  • Déployez votre SU générée à l’étape 2 (sa-POJO-<nom-du-projet>-provide.zip).

Et voilà le travail !

PetalsStudio ou Eclipse Linux : problème de clic souris sur les boutons ?

janvier 25th, 2010 by Gibello

Symptôme : le clic sur certains boutons (particulièrement les wizards de création de projet – boutons « next », « cancel », etc…) reste sans effet, alors que les raccourcis clavier fonctionnent.
Le même problème se produit sur un Eclipse « standard ».
Constaté sur un Ubuntu 9.10, ce problème a également été signalé sur d’autres Linux.

Solution : positionner la variable d’environnement GDK_NATIVE_WINDOWS à « true ».

Exemple :
$ GDK_NATIVE_WINDOWS=true PetalsStudio

Ou:
$ export GDK_NATIVE_WINDOWS=true
$ PetalsStudio