SeminaireSOA

vendredi 28 septembre 2007

Le séminaire SOA en Action de Softeam du 27 septembre 2007 se découpait en 4 parties:

  • présentation de Softeam et des offres
  • présentation de la méthode ouverte Praxeme
  • approche SOA et présentation de l’atelier objectering
  • retour d’expérience sur les projets d’intégration réalisés chez Softeam
  • le projet du groupe smabtp

Softeam

De part son passé, Softeam est naturellement très orienté objet et UML. L’approche SOA qu’ils ont choisi est MDA, c’est à dire une génération du code et modélisation des processus métiers à partir d’UML par l’enrichissement de stéréotype. Une approche MDA qui met en avant l’aspect conception des applications et des processus métiers. Selon eux, SOA par MDA permettrait de faire la liaison entre la MOA et la MOE et de rendre l’Architecture d’entreprise (EA) plus agile.

Présentation de la méthode Praxeme

Cette méthode nous a été présentée par Dominique Vauquier fondateur de l’initiative. Praxeme est présentée comme une méthodologie d’entreprise qui prend en compte tous les aspects:

  • recenser toutes les informations à traiter, les décisions à prendre, les représentations à élaborer
  • transformer la stratégie de l’entreprise, les fondamentaux de son métier, ses processus, son organisation, son outil informatique, sa géographie

La méthode Praxeme permet de répondre aux besoins des projets SOA en permettant de trouver les services, de définissant une bonne architecture, en liant l’urbanisation de SI et la conception détaillée des services. La représentation de l’entreprise peut se décliner en plusieurs aspects:

  • Sémantique
  • Pragmatique
  • Logique
  • Technique
  • Matériel
  • Géographique
  • Physique

La cycle Praxeme suit la dynamique suivante:

  • analyse stratégique
  • vision
  • conception globale
  • consolidation
  • surveillance

Approche SOA et utilisation d’Objectering

  • La MOA est concernée
  • Le SI est aligné sur les métiers
  • Le système est agile, rapidité de prise en compte des évolutions métiers
  • L’interopérabilité du systèmes, coopération entre organisations
  • La MOA doit participer à la définition des services
  • L’approche SOA impacte l’urbanisation des applications, et l’approche d’architecture d’entreprise
  • Permettre la connaissance collective
  • Assurer la continuité MOA / MOE
  • Supporter une cartographie applicative basée sur les services et composants de services

Les outils et techniques de représentation pour la MOA:

  • Dictionnaire: termes et définitions pertinentes relatifs au système
  • Analyse des besoins et des exigences
  • Approche systémique: représentation globale du système présent et futur
  • Modélisation des processus métiers
  • Règles métier
  • Cas d’utilisation
  • Modèle conceptuel
  • Supporter les problématiques des diverses intervenants
  • Offrir des représentations: centrées sur les problèmes de chaque acteur, compréhensibles et acceptées par les acteurs
  • S’appuyer sur les normes: UML, BPMN, …

Avec Objectering, on modélise tout suivant les aspects Praxeme. Les modèles correspondent au référentiel du SI. Ils permettent de générer la documentation, le code grace à la définition d’entités et de la réalisation de modèles BPMN

Retour d’expérience sur les projets d’intégration réalisés chez Softeam

Les projets n’étaient pas réellement des projets SOA au sens profond du terme mais juste une abstraction d’une couche métier pour une application. Oui certes, une partie des services encapsulait des services de technologie ancienne. On faisait déjà ça avec les EJBs en 2000 ! Une architecture SOA va bien plus loin, car on le sait, la grande force de SOA est d’ouvrir le SI, de standardiser les échanges entre partenaires et de permettre une transparence entre les systèmes et la technologie utilisée (interopérabilité). Les problèmes majeurs de SOA sont les conséquences de son avantage. La standardisation induit une demande forte en sécurité et en performance. Ils est à noter que tous les projets n’utiliser pas des Web services car peu performants à cause de la sérialisation et désérialisation du XML. Oui mais pourtant, on aurait pu en parler, il existe d’autres technologies comme REST qui sont performantes, standards et simples, l’alternative n’est pas forcément du côté des EJBs (oui pas d’EJB s’il vous plait).

Retours sur le projet SMABTP

Une excellente présentation de Jean Michel Detavernier DSI adjoint de SMABTP qui avait l’avantage d’être concrête, 5 ans de SOA qui peut en prétendre autant en France ? Une approche très intéressante qui montre que le SOA est progressif et passe par plusieurs étapes:

  • revamping de l’existant
  • externalisation des règles et paramêtres des systèmes existants
  • re-développement avec externalisation des règles et des paramêtres

Ceci se traduit par deux phases:

  • une phase d’approche technologique: buttom up, évolution de l’architecture, des règles dans le code
  • une phase d’approche métier: refonte d’une partie du SI, définition d’une méthodologie, prise en compte de la conception des paramêtres et des rêgles.

Quelle est l’architecture finale ?

  • Un bus applicatif contenant les services transverses d’infrastructure: échanges de données avec les partenaires (WBI), Moteur de règles, Editique, Portail, Habilitation
  • Des services métiers forte maille: recouvrement, sinistres, polices

Un point très intéressant qui a été soulevé par Jean Michel Detavernier est qu’il n’a aucun moyen de pouvoir tester ses services de façon unitaire, c’est à dire en pouvant controller le contexte du composant et de vérifier les appels aux composants dont il dépend.

Conclusion

Je trouve l’approche Praxeme intéressante sur un point: elle permet de voir le SI sous 7 aspects, c’est interessant à présenter à des DSI. Par contre MDA ne me séduit pas du tout pour plusieurs raisons, il induit:

  • un gros effort de conception
  • du temps passé pour de la conception qui au final peut être inutile
  • de la documentation qui ne sera jamais lue et validée
  • des clients non formés à UML
  • des développeurs non formés à UML, s’ils connaissent déjà le langage de programmation, c’est déjà une très bonne chose
  • un code généré non maitrisé car non testable

Comment fait on pour tester un modèle ? Comment peut on construire une application agile si on n’a pas définit les tests au préalable. Comment fait on du refactoring de modèle sans avoir des tests automatiques sur le code. Bon OK, on écrit des tests sur du code pour tester nos modèles, mais en fait c’est le code qu’on teste et pas les modèles, bref à quoi ça sert les modèles ? A parler à une MOA, à faire réflechir la MOA, à lui donner des jouets pour qu’elle s’amuse ;) Est ce que ça ne suffit pas à la MOA d’avoir une barre verte qui lui dit que son SI fonctionne comme souhaité ?

Comme il existe le développement guidé par les tests (TDD), n’est il pas possible d’avoir l’architecture guidée par les tests (TDA) ? Un composant n’est qu’une classe Java à plus grande échelle. En TDD, chaque classe est testée de manière unitaire de façon automatique indépendamment des autres interfaces grace à des mocks objects.

J’ai bien aimé la réponse à la question: “Peut on faire du SOA avec les méthode agiles ? ”

“Non les méthodes agiles, c’est pour les petits projets (hé oui Patrice, petit projet :o)), c’est pas professionnel, c’est pas documenté”.

Attention l’urbanisation de SI c’est pas pour les artisants ;)

C’est tellement amusant de voir pourtant que les projets utilisent des produits hautement agiles comme Spring issus de programmeurs extremes ! (Spring ne fait pas de l’objet, chuttt …, faut pas le dire trop fort, les UMListes pourraient sévir). Trève de plaisanteries, pour moi la modélisation UML n’a un intérêt que pour du reingeniering et donc avoir une vue statique du code mais pas pour la génération de code, c’est déjà assez compliqué comme ça, les applications souffrent déjà d’un manque de qualité car les entreprises ont décidé qu’un développeur ça ne coûte pas cher et donc c’est les débutants sortis de l’école qui codent. En plus, on demande aux développeurs qui sont de plus en plus débutant de connaitre un niveau langage UML. Non me dira t’on, c’est des concepteurs qui feront le travail, alors on se retrouve encore dans un système de castes hiérarchiques où la communication n’est pas mise en avant, où le concepteur aura raison du développeur. Faisons travailler notre cerveau droit de temps en temps et arrêtons de faire travailler notre cerveau gauche, soyons pragmatique, efficace, concrêt, tourné vers le client et pas vers les modèles, aidons les clients … Aidons la MOA à faire son métier: améliorer le métier et non à l'impliquer dans des modèles à la fois fonctionnelles et techniques, dans une conception où elle se perdra :(

Réfléchissons deux minutes, est ce qu’une DSI n’est pas au service des autres directions ? Si.

Qu’attendent les autres directions de la part de la DSI ? Que ça marche. Les modèles et les spécifications jamais à jour à quoi ça leur sert ? Rien

La DSI a besoin de se rassurer sur ses applications ? Oui.

Qu’est ce qu’a besoin la DSI ? D’une barre verte … les agilistes m’auront compris …

Un peu de lecture sur le métier d’architecte

Un bon architecte est plus un développeur sénior qu’un concepteur. Un architecte est capable de dire ce qui marche et ce qui ne marche pas, il conduit une équipe de développeurs vers des choix technologiques qu’il a éprouvé, pour ceux que ça intéresse de comprendre le métier d’architecte je vous conseille de lire ce livre The J2EE Architect's Handbook. Pour ceux qui ne l’ont pas lu, vous verrez c’est une vision très différente du métier d’architecte tel qu’il est perçu en France… Ha la France … Ha Merise … Tant de nostalgie … ;)

VMWareMaven2

dimanche 23 septembre 2007

L’installation d’une plate-forme d’intégration continue peut s’avérer longue à monter, c’est pour cela que des produits de virtualisation comme VMWare permettent de gagner du temps. J’ai donc créé une image VMWare d’une plate-forme d’intégration continue basée sur Maven 2 et Continuum.

Produits installés

Les produits installés sont les suivants:

  • Ubuntu Server 6.06.1
  • Un serveur SSH
  • Apache 2..55
  • Subversion 1.3.1
  • JDK 1.5.0_12
  • Maven 2.0.7
  • Trac 0.10.4
  • Continuum 1.0.3

Accès

Les identifiants:

  • identifiant / mot de passe linux: m2user / m2user
  • identifiant / mot de passe subversion: svnuser / svnuser
  • identifiant / mot de passe continuum: continuum / continuum

Les urls d’accès:

  • Serveur SSH sur le port 22

Installation de l’image:

  • Déziper le fichier
  • Importer le fichier Ubuntu.vmx dans le player vmware
  • Démarrer la machine virtuelle

MavenSVNContinuum

jeudi 20 septembre 2007

Cet article décrit comment installer une plateforme d’intégration continue avec Maven 2, Subversion et Continuum sur Ubuntu Server

Installation d’Ubuntu Server

  • Récupération des binaires

Activer le dépôt universel

  • Ouvrir le fichier sources.list
 sudo vi /etc/apt/sources.list
  • Repérer la ligne deb http://fr.archive.ubuntu.com/ubuntu dapper main restricted et la modifier comme suit:
deb http://fr.archive.ubuntu.com/ubuntu dapper main restricted universe multiverse
  • Mettre à jour le référentiel
sudo apt-get update

Passer par un proxy pour une connexion Internet

  • Ouvrir le fichier /etc/profile:
export “http_proxy=http://login:motdepasse@proxy.monfai.com:3128”
export “no_proxy=localhost”

Installer un serveur SSH

sudo apt-get install ssh

Installation d’apache

  • Installation d’apache 2:
 sudo apt-get install apache2
  • Vérifier l’installation:
 netstat -a | grep 80

Installation de subversion

  • Installation des binaires:
sudo apt-get install subversion libapache2-svn
  • Créer un fichier svn dans le répertoire /etc/apache2/sites-enabled
<Location /svn>
  DAV svn
  SVNPath /usr/local/subversion
  AuthType Basic
  AuthName “Documentation Team Repository”
  AuthUserFile /usr/local/passwd
  Require valid-user
</Location>
  • Redémarrez Apache
sudo /etc/init.d/apache2 force-reload
  • Créez le repository
sudo svnadmin create /usr/local/subversion
  • Créez un fichier de mot de passe
sudo htpasswd2 -c /usr/local/passwd username
  • Donnez les droits d’accès au repository à Apache
sudo chown -R www-data.www-data /usr/local/subversion
  • Tester l’accès
http://localhost/svn

Installation de Trac

Trac

Installation du JDK 5

  • Donner les droits d’exécution:
sudo chmod +x jdk-1_5_0_12-linux-i586.bin
  • Déplacer le fichier dans /usr/local
 sudo mv jdk-1_5_0_12-linux-i586.bin /usr/local
  • Installer le JDK
 sudo ./jdk-1_5_0_12-linux-i586.bin
  • Ajouter les alias suivants:
sudo ln -s /usr/local/jdk1.5.0_12/bin/java /usr/local/bin/java
sudo ln -s /usr/local/jdk1.5.0_12/bin/policytool /usr/local/bin/policytool
  • Ajouter la variable d’environnement JAVA_HOME dans le fichier /etc/environment:
JAVA_HOME=/usr/local/jdk1.5.0_12
  • Vérifier l’installation
java -version

Installation de Maven 2

  • Déziper le fichier:
 sudo tar -zxvf maven-2.0.7-bin.tar.gz
  • Ajouter la variable MVN_HOME dans le fichier /etc/environment:
MVN_HOME=/usr/local/maven-2.0.7
  • Ajouter dans le PATH le répertoire $MVN_HOME/bin dans le fichier /etc/environment:
PATH=“…:/usr/local/maven-2.0.7/bin”
  • Ajouter un lien symbolique sur mvn (ce sera utile pour Continnum):
 sudo ln -s /usr/local/maven-2.0.7/bin/mvn /usr/bin/mvn
  • Vérifier l’installation:
 mvn -v

Installation de continuum

  • Déplacer le fichier dans le répertoire /usr/local
  • Déziper le fichier:
sudo tar -zxvf continuum-1.0.3-bin.tar.gz
  • Ajouter la variable CONTINUUM_HOME dans le fichier /etc/environment
 CONTINUUM_HOME=/usr/local/continuum-1.0.3
  • Démarrer Continuum:
 sudo /usr/local/continuum-1.0.3/bin/linux/run.sh start
  • Vérifier l’installation (ou <ip> est l’url de votre serveur):
 http://<ip>:8080/continuum
  • Lancer continuum au démarrage:
sudo ln -s /usr/local/continuum-1.0.3/bin/linux/run.sh /etc/init.d/continuum
sudo update-rc.d continuum defaults
  • Enlever continuum du démarrage:
sudo update-rc.d -f continuum remove

Maven et Continuum

  • Modifier le fichier pom.xml pour que Continuum le comprenne avec une notification par email:
<projet>
…
<scm>
 <connection>
  scm:svn:http://192.168.0.5/svn/monprojet
 </connection>
</scm>
…
<developers>
 <developer>
  <id>jfhelie</id>
  <name>Jean-François Hélie</name>
  <email>jfhelie@norsys.fr</email>
 </developer>
</developers>
…
<ciManagement>
 <system>continuum</system>
 <notifiers>
  <notifier>
   <type>mail</type>
   <configuration>
    <address>jfhelie@norsys.fr</address>
   </configuration>
  </notifier>
 </notifiers>
</ciManagement>
…
</projet>

Pour utiliser la console d’administration continuum, je vous recommande l’article suivant http://today.java.net/pub/a/today/2006/05/30/continuous-integration-with-continuum.html

OSCache

dimanche 9 septembre 2007

OSCache est une solution de cache qui include un taglib pour les JSP, un filtre pour les servlets et une API pour les objets. Dans le cadre d’une application faisant plusieurs appels à annuaire LDAP qui ne bénéficie pas des jointures externes ou de vue dématérialisée d’un SGBDR, il est plus que nécessaire de positionner un cache pour les données qui ne changent pas souvent.

Utilisation de la classe GeneralCacheAdministrator

Voici un exemple d’utilisation de la classe GeneralCacheAdministrator:

List l = null;
try {
	l = (List) cacheAdministrator.getFromCache(“users”);
} catch (NeedsRefreshException nre) {
	try {
		l = new ArrayList();
		for (int i = 0; i < 10000; i++)
			l.add(“test” + i);
		cacheAdministrator.putInCache(“users”, l);
	} catch (Exception ex) {
		l = (List) nre.getCacheContent();
		cacheAdministrator.cancelUpdate(“users”);
	}
}

AOP avec Spring pour la gestion du cache

La solution de cache est une solution qui peut intervenir à plusieurs niveaux dans une application, il doit être possible de l’ajouter par de la configuration sans avoir à modifier le code déjà présent. Grâce à Spring et l’AOP, il est facile d’ajouter un cache au niveau des appels des méthodes des beans Spring:

<bean name=“cacheAutoProxy”
	class=“org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”>
	<property name=“beanNames”>
		<value>otherUserManager</value>
	</property>
	<property name=“interceptorNames”>
		<list>
			<value>cacheInterceptor</value>
		</list>
	</property>
</bean>    

A chaque appel d’une méthode du bean otherUserManager, l’interceptor cacheInterceptor sera exécuté:

import java.util.List;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;
public class CacheInterceptor implements MethodInterceptor {
	private GeneralCacheAdministrator cacheAdministrator;
	public Object invoke(MethodInvocation invocation) throws Throwable {
		List l = null;
		try {
			l = (List) cacheAdministrator.getFromCache(“users”);
		} catch (NeedsRefreshException nre) {
			try {
				l = (List) invocation.proceed();
				cacheAdministrator.putInCache(“users”, l);
			} catch (Exception ex) {
				l = (List) nre.getCacheContent();
				cacheAdministrator.cancelUpdate(“users”);
			}
		}
		return l;
	}
	public GeneralCacheAdministrator getCacheAdministrator() {
		return cacheAdministrator;
	}
	public void setCacheAdministrator(
			GeneralCacheAdministrator cacheAdministrator) {
		this.cacheAdministrator = cacheAdministrator;
	}
}

Ressources

CommonsCollections

Après CommonsCli, j’ai eu besoin pour une application de comparer deux listes d’objets selon des critères de recherche, j’ai découvert que la librairie Commons Collections permettait de faire un filtre sur les objets de manière plus propre, c’est à dire qu’on évite de mettre les comparaisons à l’intérieur de la boucle de l’itérateur:

public void testFilterCollection() throws Exception {
	List l = new ArrayList();
	Map m1 = new HashMap();
	m1.put(“attr”, “value1”);
	l.add(m1);
	Map m2 = new HashMap();
	m2.put(“attr”,“value2”);
	m2.put(“attr2”,“toto”);
	l.add(m2);
	Iterator it=new FilterIterator(l.iterator(),new MapFilter(“value2”));
	assertTrue(it.hasNext());
	it.next();
	assertFalse(it.hasNext());
}

avec MapFilter:

import java.util.Map;
import org.apache.commons.collections.Predicate;
public class MapFilter implements Predicate {
	private String value;
	public MapFilter(String value) {
		this.value = value;
	}
	public boolean evaluate(Object obj) {
		Map map = (Map) obj;
		if (value.equals(map.get(“attr”)))
			return true;
		return false;
	}
}

Par contre, grande déception, je n’ai pas trouvé de gain de performance pour 200000 maps. Néanmoins, le parcours met 32 ms pour trouver le dernier élément, pour mon besoin c’était négligeable.

Pour compter le nombre d’éléments dans une liste suivant un filtre:

public void testCountFilterCollection() throws Exception {
	List l = new ArrayList();
	Map m1 = new HashMap();
	m1.put(“attr”, “value1”);
	l.add(m1);
	Map m2 = new HashMap();
	m2.put(“attr”,“value2”);
	m2.put(“attr2”,“toto”);
	l.add(m2);
	assertEquals(1,CollectionUtils.countMatches( l, new MapFilter(“value2”)));
}

FrameworksWeb

Struts a longtemps été le vainqueur avec son MVC. Compte tenu de son ancienneté Struts 1.x n’est plus d’actualité car il n’est pas testable unitairement ou plutôt difficilement. Bien sûr, il existe StrutsTestCase sauf que cela ne permet pas de faire des tests unitaires au sens propres mais plutôt des tests d’intégration car on passe par toutes les couches. Une solution propre existe et MockRunner avec JMock même dans le cas où on utilise des DynaActionForm, j’avais trouvé une solution. Mais en tout cas, ce n’est pas ça qu’on attend d’un framework web en 2007. Heureusement, Struts 2 est beaucoup plus orienté TDD.

Spring MVC, lui est testable unitairement; de plus, il peut se coupler avec Spring Web Flow. Bien que ce framework est beaucoup de bénéfices, développer des vues JSP et des actions reste couteux en développement et typiquement c’est pas le problème du client. Il faut donc trouver une solution plus rapide.

C’est alors que JSF vient à la rescousse avec une approche composant. Peu de personnes l’utilise car JSF est difficile à utiliser et s’accompagne d’une baterie d’atelier de développement à la visual basic pour créer les composants graphiques visuellement… Ca ne perse pas et ne persera probablement pas en France vu qu’on a quelques années de retard avec les US, chez nous il faut que la technologie dure pour que nos clients la choisissent.

Bien sûr, il y a Google Web Toolkit qui est un très bon framework qui réunit beaucoup d’adeptes dont je ne fais pas partie. En effet pour faire du GWT, il faut faire un peu du Swing, faire du Web avec du Swing, je trouve ça curieux, surtout qu’après on utilise un compilateur qui génére un code HTML, CSS et Javascript illisible. Moi qui est suivi la tendance OpenWeb et CSS Zen Garden, j’accroche pas. De plus faire des tests unitaires, c’est pas évident, en fait on fait des tests d’intégration avec un browser caché… beurk. Faire du GWT consiste à ne plus faire de Web, le HTML y’a rien de plus simple…dommage.

Rassurez vous il y a des solutions…Wicket en est un exemple, il permet de créer des composants Web en ajoutant dans le code HTML existant des attributs wicket et la gestion des composants est faite en Java et de plus cerise sur le gâteau il est testable unitairement.

Mais ça ne me satisfait pas encore, je ne veux pas de Java pour faire mon interface graphique, Java pour moi c’est juste pour développer mes services, c’est alors qu’Ajax rentre en jeu. Je code mon HTML avec des CSS proprement et puis j’ajoute du dynamique à mes pages à l’aide de jQuery: un framework javascript qui supporte un nombre important de navigateurs et qui possède une syntaxe minimaliste et intuitive. Je code mes services en Java avec Spring et j’utilise DWR pour les appels aux services Spring. Il y a un probleme de sécurité car on peut appeler un service à partir d’un javascript, néanmoins je protège les appels de mes beans avec Spring Acegi. L’application est rapide car nécessite moins d’appels au serveur, découpler (on peut imaginer un graphiste qui fait l’interface) car avec jquery on fait du javascript non intrusif, les données sont bien séparées des traitements et surtout ce qui est le plus important pour moi elle est rapide à développer et plus rapide dans son utilisation. Par contre, il faut pouvoir gérer les bookmarks, le multi langue, la session…

Dans une approche future, on peut imaginer que l’on fera des applications Web sans framework Java Web mais plutôt avec des frameworks javascript modernes comme jquery et appeler des web service SOAP, REST, des services RSS, WebCal, WebDav et autres. Les principaux avantages sont une interface simple à développer et une communication avec les serveurs standardisées. C’est l’apparition des widgets comme celles de netvibes, Dashboard ou iGoogle. On n’est pas si loin du futur, on pourrait imaginer de créer un site qui vend des articles issus d’un catalogue d’un partenaire accessible en SOAP, puis d’ajouter un mode de paiement PayPal accessible en SOAP et d’utiliser le web service Google pour la recherche et Google Gmail SOAP pour l’envoi de mail, l’appel d’un flux RSS pour les nouveautés. L’avantage des standars, c’est l’ouverture, par contre la difficulté est de gérer la sécurité des données échangées.

A suivre…

CommonsCli

lundi 3 septembre 2007

Cet article s’attache à décrire l’API Commons Cli, une API qui permet de gérer facilement des options passées en arguments à une méthode main d’une classe Java.

Deux types d’option sont possibles:

  • option sans valeur: exemple -h
  • option avec valeur: exemple -msg=message

Créer le projet Java

  • Créer un projet Java
  • Télécharger la version commons-cli-1.1.jar
  • Ajouter ce jar dans le classpath du projet Java
  • Créer une classe DisplayMessage avec une méthode main()

Option sans valeur

  • L’ajout de l’option sans valeur se fait de la façon suivante:
Options options = new Options();
Option help = new Option(“h”, “message d’aide”);
options.addOption(help);

Option avec valeur

  • L’ajout de l’option avec valeur se fait de la façon suivante:
Options options = new Options();
OptionBuilder.withArgName(“msg”);
OptionBuilder.hasArg();
OptionBuilder.withDescription(“valeur du message en paramêtre”);
Option msgOption = OptionBuilder.create(“msg”);
options.addOption(msgOption);

Parseur des options

  • Le parseur des options s’utilise de la manière suivante:
CommandLineParser parser = new GnuParser();
CommandLine line = parser.parse(options, args);
if (line.hasOption(“h”)) {
	displayHelp(options);
} else if(line.hasOption(“msg”)) {
	msg = line.getOptionValue(“msg”);
	System.out.println(“message: ” + msg);
} else {
	displayHelp(options);
}

Affichage des options, usage de l’appel du script

  • L’affichage des options se fait à l’aide de la classe HelpFormater:
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(“monbatch.bat [options]”, “\nOptions:”, options,
		“\nDescription du batch”);

Exemple complet

  • Exemple pour un lancement de batch:
usage: monbatch.bat options
Options:
 -h           message d’aide
 -msg <msg>   valeur du message en paramêtre
Description du batch
  • Code Java:
package fr.jfhelie.commonscli.sample;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
public class DisplayMessage {
	public static void main(String args) throws Exception {
		String msg = null;
		Options options = new Options();
		Option help = new Option(“h”, “message d’aide”);
		options.addOption(help);
		OptionBuilder.withArgName(“msg”);
		OptionBuilder.hasArg();
		OptionBuilder.withDescription(“valeur du message en paramêtre”);
		Option msgOption = OptionBuilder.create(“msg”);
		options.addOption(msgOption);
		CommandLineParser parser = new GnuParser();
		CommandLine line = parser.parse(options, args);
		if (line.hasOption(“h”)) {
			displayHelp(options);
		} else if (line.hasOption(“msg”)) {
			msg = line.getOptionValue(“msg”);
			System.out.println(“message: ” + msg);
		} else {
			displayHelp(options);
		}
		System.exit(1);
	}
	private static void displayHelp(Options options) {
		HelpFormatter formatter = new HelpFormatter ;
		formatter.printHelp(“monbatch.bat [options]”, “\nOptions:”, options,
				“\nDescription du batch”);
	}
}

Ressources

Axis2Introduction

Axis 2 est un moteur de Web services, c’est une implémentation du protocole SOAP. Cet article présente comment créer un web service Axis 2 de type JAX-RPC. Cet article est le premier article d’une série d’articles sur Axis 2:

  • Introduction d’Axis 2
  • Console d’administration d’Axis 2
  • Le modèle objet AXIOM d’Axis 2
  • Plugin Axis 2 d’Eclipse
  • Axis 2 et REST
  • Axis 2 et les attachements SOAP
  • Axis 2 et Maven 2
  • Axis 2 et Spring
  • Sécuriser les web services Axis2
  • Axis 2 et Spring Acegi
  • Fiabilité l’envoi des messages Axis 2
  • Axis 2 et TDD
  • Axis 2 et Performances
  • Axis 2 et Apache Synapse

Téléchargement des binaires Axis 2

  • Télécharger le binaire axis2-1.3-bin.zip
  • Déziper le contenu du fichier binaire dans le répertoire C:

Création du projet Java

  • Créer un projet Java sous votre IDE (Eclipse,Netbeans)
  • Ajouter dans le classpath du projet les librairies jar d’Axis qui se trouvent dans C:\axis2-1.3\lib
    • Sous Eclipse: Bouton droit sur le projet Java > Properties > Java Build Path > Add External JARS… (ou Ajouter une variable AXIS2_LIB correspond au répertoire lib des binaires d’Axis2 à partir d’Eclipse)

Création de l’implémentation du web service

  • Créer une entité métier User:
package fr.jfhelie.axis2.sample;
import java.io.Serializable;
/**
* Entité utilisateur
*
* @author jeff
*
*/
public class User implements Serializable {
 public User() {
  super();
 }
 public User(String email, String firstName, String lastName) {
  super();
  this.firstName = firstName;
  this.lastName = lastName;
  this.email = email;
 }
 // prénom
 private String firstName;
 // nom
 private String lastName;
 // email
 private String email;
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}
  • Créer la classe d’implémentation du web service UserManager:
package fr.jfhelie.axis2.sample;
import java.util.ArrayList;
import java.util.List;
/**
* Classe d’implémentation du web service
* Permet de récupérer des utilisateurs
* @author jeff
*
*/
public class UserManager {
 public User getUser(String email) {
  return new User(“user1@gmail.com”,“prénom1”,“nom1”);
 }
 public List<User> listUsers() {
  List<User> users = new ArrayList<User>();
  users.add(new User(“user1@gmail.com”,“prénom1”,“nom1”));
  users.add(new User(“user2@gmail.com”,“prénom2”,“nom2”));
  return users;
 }
}

Création du fichier services.xml

  • Le fichier services.xml permet de decrire le déploiement du web service sur le serveur Axis 2
  • Créer un fichier services.xml dans le répertoire du projet java
<service>
 <description>Exemple de web service</description>
 <parameter name=“ServiceClass”>fr.jfhelie.axis2.sample.UserManager</parameter>
 <operation name=“getUser”>
  <messageReceiver class=“org.apache.axis2.rpc.receivers.RPCMessageReceiver” />
 </operation>
 <operation name=“listUsers”>
  <messageReceiver class=“org.apache.axis2.rpc.receivers.RPCMessageReceiver” />
 </operation>
</service>
  • Le paramètre ServiceClass correspond au chemin de la classe d’implémentation complet du web service, dans notre cas: fr.jfhelie.axis2.sample.UserManager
  • Les operations permettent de définir les méthodes de la classe d’implémentation qui seront accessibles en SOAP, ainsi que le protocole d’accès, dans notre cas c’est du JAX-RPC

Créer le packetage du web service

  • Les fichiers packatage des web services Axis 2 sont du type *.aar
  • Créer le fichier usermanager.aar avec votre IDE
    • Sous Eclipse: Selectionner le projet > Bouton droit > Export… > Java > JAR file > JAR file: C:\usermanager.aar > Finish
  • Créer un répertoire META-INF et copier le fichier services.xml dans ce répertoire.

Démarrer le serveur Axis 2

  • Le serveur Axis 2 peut être lancé indépendamment ou dans un conteneur de servlets, dans notre cas nous choisirons de lancer indépendamment
  • Lancer le script C:\axis2-1.3\bin\axis2server.bat (vérifier bien que le port 8080 est disponible par netstat -a)
  • Normalement le message suivant doit s’afficher dans la console de commande:
[INFO] Listening on port 8080
  • Lancer votre navigateur web sur l’adresse suivante: http://localhost:8080/axis2/services/
  • Normalement vous devez voir un web service déployé appelé Version

Déployer le web service sur le serveur Axis 2

  • Copier le fichier usermanager.aar dans le répertoire C:axis2-1.3repositoryservices, l
  • Normalement le message suivant doit s’afficher sur la console de commande:
[INFO] Deploying Web service: usermanager.aar
  • Rafraichir la page http://localhost:8080/axis2/services/, normalement le web service usermanager est visible avec ses deux méthodes: listUsers et getUser
  • Cliquer sur le lien usermanager pour voir le WSDL généré

Générer le client du web service

  • A partir du WSDL, il est possible de générer du code client pour appeler facilement le web service
  • Positionner la variable d’environnement AXIS_HOME
    • Sous Windows, Bouton droit sur le poste de travail > Avancé > Variables d’environnement > Nouvelle variable système (Nom de la variable: AXIS_HOME, Valeur de la variable: C:axis2-1.3bin)
  • Ouvrir une console de commande et aller dans le répertoire C:\axis2-1.3\bin:
 cd C:\axis2-1.3\bin
  • Lancer la commande suivante:
wsdl2java.bat -uri http://localhost:8080/axis2/services/usermanager?wsdl -o D:\ressources\workspace\axis2-introduction
  • Le paramètre uri spécifie l’adresse du WSDL du web service et le paramêtre o spécifie le chemin où générer le code client
  • Par défaut, le code généré se trouve dans un répertoire src suivi du nom de package du web service, dans notre cas, le code est généré dans D:\ressources\workspace\axis2-introduction\src\fr\jfhelie\axis2\sample
  • Deux fichiers ont été générés: UsermanagerCallbackHandler et UsermanagerStub

Appeler le web service avec le client généré

  • Créer une classe UserManagerClient:
package fr.jfhelie.axis2.sample;
import fr.jfhelie.axis2.sample.UsermanagerStub.GetUser;
import fr.jfhelie.axis2.sample.UsermanagerStub.GetUserResponse;
/**
* Classe d’appel du web service
* @author jeff
*
*/
public class UserManagerClient {
 public static void main(String args) throws Exception {
  UsermanagerStub stub = new UsermanagerStub(
    “http://localhost:8080/axis2/services/usermanager”);
  GetUser request = new GetUser();
  request.setEmail(“user1@gmail.com”);
  GetUserResponse response = stub.getUser(request);
  UsermanagerStub.User user = response.get_return();
  System.out.println(user.getFirstName() + “ ” + user.getLastName() + “ ” + user.getEmail());
 }
}
  • Les paramêtres d’appel et de réponse sont encapsulés dans des classes générées par le moteur Axis 2, ici GetUser et GerUserResponse.

Ressources