Maveniser l’intégration de Flex, Spring et BlazeDS
Posté par jbcazaux, le 20/08/2009.Ce tutoriel présente l’implémentation d’une application Flex consommant des services Java exposés via le framework BlazeDS.
Les particularités de ce tutoriel, par rapport à ceux que l’on peut trouver sur Internet, portent sur:
- l’industrialisation avec Maven, pour un développement professionnel
- l’intégration de Spring-Flex, pour simplifier la configuration de BlazeDS
Les sources sont disponibles et facilement compilables (voir les pré-requis et les instructions de compilation et de déploiement).
valtechflexblazedstuto-20090823.zip
I) Introduction
1) Flex
Flex est un framework Open Source dédié à au développement d’applications web de type RIA. Créée à l’origine par Macromedia en 2004, cette technologie a été reprise par Adobe en 2006.
Les applications développées en Flex s’exécutent indifféremment dans un navigateur web muni du module Adobe Flash® Player ou en local via le moteur d’exécution Adobe AIR™.
Son modèle de programmation s’appuie sur un langage déclaratif basé sur XML, le MXML, et sur un langage de script orienté objet, l’ActionScript. Le premier permet de décrire l’apparence et le comportement de l’interface utilisateur, le deuxième permet d’implémenter les traitements coté client.
Bien qu’il soit possible de développer en se limitant à l’utilisation du Flex SDK, vos développements seront nettement plus productifs s’ils s’appuient sur l’environnement dédié et commercialisé par Adobe sous le nom de « Flex Builder ». Basé sur Eclipse, cet IDE est distribué sous une forme packagée ou sous forme de plugin.
Parfaitement adapté à la création d’IHM riches et érgonomiques, Flex l’est beaucoup moins pour implémenter le code métier d’une application d’entreprise où les technologies telles que java ou .Net règnent en maitres absolus. De ce fait, une application Flex qui souhaite manipuler des données stockées en base doit de communiquer avec un composant de type serveur. Bien que Flex permette de consommer des services déployées sous la forme de services web de type SOAP ou REST, Adobe propose une autre solution technique élégante et bien plus productive.
2) BlazeDS
BlazeDs est un framework permettant de connecter une application cliente Flex à une application serveur Java.
Les principes mis en oeuvre sont relativement simples. Un client Flex envoie des requêtes à destination d’un serveur BlazeDS via un ‘canal’ (channel) dédié. Ces requêtes sont interceptées par une servlet fournie par BlazeDS (MessageBrokerServlet) puis traitée par un Adapter. Il existe plusieurs types d’Adapters, celui utilisé dans ce tutoriel permet d’exécuter des services implémentés sous forme de simples POJO (JavaAdapter), d’autres, tel que le JMSAdapter, permet de reléguer le traitement à un serveur distant via le protocole JMS.
La documentation officielle explique ceci en détail: http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=Part_ChannelsEndpoints_1.html.
II) Mise en œuvre
Il existe aujourd’hui deux solutions pour mettre en œuvre un projet Flex/Java/BlazeDS.
La plus rapide mais aussi la moins maintenable consiste à créer, directement dans l’environnement FlexBuilder, un projet regroupant l’application Flex, le code Java et la web application.
La 2ème solution, préconisée dans ce tutoriel, consiste à créer un projet Maven regroupant deux modules: un pour l’application Flex et un pour l’application web.
La première solution a été abordée dans différents articles sur le net et reste conseillée dans une optique de mise en œuvre rapide de POC (Proof Of Concept). La deuxième solution, totalement industrialisée (compilation, packaging et déploiement orchestrés par Maven et intégrée en continu) est clairement destinée à un développement professionnel.
La solution proposée permettrait presque de se passer de FlexBuilder. “Presque” car la plus value apportée par FlexBuilder en termes de développement et de debugging reste incontournable. Incontournable, certes, mais qui nécessite une double configuration: dans FlexBuilder et dans Maven.
1) Pré-requis
Ce tutoriel a été développé avec le JDK6, Maven 2.1.0, FlexBuilder3 sous Eclipse Ganymede (3.4) et Tomcat 6.0.20.
Pour faire fonctionner le tout, il faut au préalable avoir installé sur sa machine de développement les composants suivants:
- Java 5 minimum – http://java.sun.com/javase/downloads/index.jsp
- Maven 2 – http://maven.apache.org/download.html
- Un serveur d’application – http://tomcat.apache.org/download-60.cgi
- FlexBuilder 3 (évaluation 60 jours gratuite) – http://www.adobe.com/cfusion/entitlement/index.cfm?e=flexbuilder3
- Eclipse ganymede (Galileo ne semble pas encore supporté par FlexBuilder3) – http://www.eclipse.org/downloads/packages/release/ganymede/sr2
- Une connexion internet (environ 60Mo de téléchargement dans le repository maven)
Les sources de ce tutoriel se veulent les plus simples possibles afin d’êtres facilement réutilisables.
Pour éditer les sources, il suffit d’importer, depuis Eclipse/FlexBuilder, les différents projets en spécifiant le répertoire racine du projet valtechFlexBlazeDsTut.
2) Intégration avec Maven
Il y a encore quelques mois, aucun ‘repository’ Maven public n’hébergeait les archives nécessaires à la compilation de projets Flex. Heureusement, la société Sonatype a fait un gros travail et a mis à disposition tout ce qui est nécessaire à la construction d’une application Flex avec Maven. Le fichier de configuration Maven (settings.xml), livré avec les sources de ce tutoriel, doit être copié dans votre répértoire de settings C:\Documents and Settings\monNom\.m2\.
Dans le cas où vous disposeriez déjà d’un tel fichier, la modification à apporter porte sur sur la déclaration de ce nouveau dépot:
Note: Voir aussi le lien donné par VELO (commentaire en fin de page) sur la déclaration du repository: https://docs.sonatype.org/display/FLEXMOJOS/Referencing+Flexmojos+maven+repository
<...> <repository> <id>sonatype</id> <url>http://repository.sonatype.org/content/groups/flexgroup</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>false</enabled></snapshots> </repository> <...>
La ‘mavenisation’ de notre projet consiste à créer un projet multi-modules composé au minimum de l’application Flex et de l’application web exposant les services Java.
La première difficulté rencontrée concerne la mise en commun des fichiers de configuration permettant de lier les deux mondes Flex et Java. Pour éviter de copier/coller ces fichiers dans les deux projets, il est possible de créer un module dédié, dit de configuration, dont dépendront les modules Flex et Java.
Un projet parent ordonnancera la construction des différents modules. Voici comment ce projet multi-modules est organisé:
- valtechFlexBlazeDsTuto (le projet parent)
`– pom.xml
`– valtechBlazeDsFlexApp (l’application Flex)
`– valtechBlazeDsResources (les ressources communes à Flex et Java)
`– valtechBlazeDsWebApp (la web-app et les services Java)
3) Le projet parent: valtechFlexBlazeDsTuto
Il s’agit d’un simple projet contenant 3 répertoires, correspondant aux 3 modules, et un fichier pom.xml.
Dans ce pom, on déclare simplement les 3 modules enfants (l’ordre de compilation est important) et les différents plugins que l’on va utiliser.
Pour rappel, le premier module contient les fichiers de configuration de BlazeDs, le 2ème module contient l’application Flex et enfin le 3ème module contient la web-app et les services java.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>fr.valtech.flex</groupId> <artifactId>valtechFlexBlazeDsTuto</artifactId> <packaging>pom</packaging> <version>1.0</version> <name>valtechFlexBlazeDsTuto</name> <url>http://www.valtech.fr</url> <!-- les propriétés réutilisées dans les poms des différents projets--> <properties> <compileSource>1.6</compileSource> </properties> <!-- les 3 modules, dans l'ordre de compilation--> <modules> <module>valtechBlazeDsResources</module> <module>valtechBlazeDsFlexApp</module> <module>valtechBlazeDsWebApp</module> </modules> <build> <pluginManagement> <plugins> <!-- le plugin pour gérer les dépendances, dans notre cas des ressources vers les projets Flex et Java--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.0</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- le plugin qui nous permettra de créer le zip contenant les ressources communes aux projets Flex et Java--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-4</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <!-- Pour spécifier à maven de compiler les sources en autre chose que java 1.3 :) --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${compileSource}</source> <target>${compileSource}</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> <developers> <developer> <id>jbcazaux</id> <name>Jean-Baptiste Cazaux</name> <email>jean-baptiste.cazaux@valtech.fr</email> <organization>Valtech</organization> <organizationUrl>http://www.valtech.fr</organizationUrl> </developer> </developers> </project>
3) Le projet de configuration: valtechFlexBlazeDsResources
Ce module contient les 2 fichiers nécessaires au bon fonctionnement de BlazeDS. L’objectif de ce module est de générer une archive au format zip contenant ces fichiers. Cette archive sera installée dans le repository Maven puis automatiquement recopiée, lors de la compilation, dans les 2 projets Flex et Java.
- valtechBlazeDsResources
`– pom.xml
`– src
`– assembly
`– resources.xml
`– resources
`– remoting-config.xml
`– services-config.xml
Les fichiers de configuration servent principalement à décrire les canaux d’échange des requêtes entre le client Flex et la web-app contenant les services Java.
a) resources.xml
Ce fichier permet de configurer le plugin Maven en charge de génèrer le zip. Il sera donc référencé dans le pom.xml.
<assembly> <id>resources</id> <formats> <!-- Nous voulons créer un zip au final --> <format>zip</format> </formats> <!-- Pour ne pas inclure le chemin complet du répertoire de base des fichiers de configuration--> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <!-- le répertoire où sont stockés les fichiers de configuration BlazeDS --> <directory>src/resources/</directory> <!-- chemin du répertoire dans le zip et qui contiendra les fichier blazeDS, ici vide--> <outputDirectory></outputDirectory> </fileSet> </fileSets> </assembly>
b) pom.xml
Rien de spécial dans ce pom, si ce n’est l’utilisation du plugin “assembly” permettant de générer le fichier zip lors du lancement de la commande mvn:package
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <!-- Le projet parent--> <parent> <groupId>fr.valtech.flex</groupId> <artifactId>valtechFlexBlazeDsTuto</artifactId> <version>1.0</version> <relativePath>../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>fr.valtech.flex</groupId> <artifactId>valtechBlazeDsResources</artifactId> <version>1.0</version> <packaging>pom</packaging> <name>valtechBlazeDsResources</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-4</version> <executions> <execution> <id>make shared resources</id> <goals> <goal>single</goal> </goals> <phase>package</phase> <configuration> <descriptors> <!-- référence vers le fichier resources.xml que nous venons de voir--> <descriptor>src/assembly/resources.xml</descriptor> </descriptors> <encoding>UTF-8</encoding> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
c) services-config.xml
C’est le fichier qui permet de configurer les canaux sur les quels communiquent les applications Flex et Java. Il fait référence à un deuxième fichier que nous verrons juste après.
Dans le cadre du tutoriel, nous utilisons un seul canal de type “AMFChannel”. Ce type de canal permet l’échange de message au format AMF (Action Message Format), format propriétaire mais optimisé.
<?xml version="1.0" encoding="UTF-8"?> <services-config> <services> <service-include file-path="remoting-config.xml" /> <!-- le canal amf par défaut --> <default-channels> <channel ref="valtech-amf"/> </default-channels> </services> <channels> <!-- définition des canaux amf, ici un canal standard (non sécurisé, non crypté) --> <channel-definition id="valtech-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> </channels> <!-- Pour logger les messages AMF qui passent, indiquer level="Debug" --> <logging> <target class="flex.messaging.log.ConsoleTarget" level="Error"> <properties> <prefix>[BlazeDS] </prefix> <includeDate>false</includeDate> <includeTime>false</includeTime> <includeLevel>false</includeLevel> <includeCategory>false</includeCategory> </properties> <filters> <pattern>Endpoint.*</pattern> <pattern>Service.*</pattern> <pattern>Configuration</pattern> </filters> </target> </logging> <system> <redeploy> <enabled>false</enabled> </redeploy> </system> </services-config>
d) remoting-config.xml
C’est dans ce fichier que l’on déclare interagir avec du code java.
<?xml version="1.0" encoding="UTF-8"?> <service id="remoting-service" class="flex.messaging.services.RemotingService"> <adapters> <!-- on demande a BlazeDs d'interagir avec du code java --> <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/> </adapters> <default-channels> <!-- canal utilisé par défaut pour discuter, ce canal avait été déclaré dans services-config.xml --> <channel ref="valtech-amf"/> </default-channels> </service>
3) L’application Flex: valtechBlazeDsFlexApp
L’application est volontairement simple. Elle se limite à la consommation d’un service dont la signature déclare en entrée comme en sortie une chaine de caractère.
Le service Java prend un nom en entrée et retourne un message de bienvenue concaténé au nom passé en paramètre.
L’interface propose donc un champ dédié à la saisie du nom de l’utilsateur, un bouton pour déclencher l’appel au service et un champ pour en afficher le resultat.
Le module se compose des sources flex et du pom utilisé pour la compilation du projet. L’utilisation de FlexBuilder permet de génèrer les sources HTML nécessaire au lancement l’application dans un navigateur. Cette fonctionnalité nous évite ainsi de produire à la main du code HTML pas spécialement intéressant. Je ne détaillerai pas non plus les autres fichiers générés par FlexBuilder, comme les fichiers .actionScriptProperties et .flexProperties, utilisés pour conserver les paramètres de compilation (de FlexBuilder, pas ceux de maven !).
- valtechBlazeDsFlexApp
`– pom.xml
`– src
`– main
`– flex
`– flexApp.mxml
a) flexApp.mxml
Il s’agit du fichier principal de l’application Flex.
Dans ce fichier apparaissent une description de l’interface minimaliste de l’application, la déclaration du service distant et son appel.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="451" height="168" paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0"> <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; /** * Méthode appelée lors du clic sur le bouton d'envoie */ private function doCall():void{ // Appeler le service distant roWelcomeService.sayHello(tiLogin.text); } /** * Méthode invoquée en cas de succès de l'appel RPC */ private function onResult(event : ResultEvent):void{ // Afficher la réponse dans le textArea taReponse.text = event.result as String; } /** * Méthode invoquée en cas d'échec de l'appel RPC */ private function onFault(event : FaultEvent):void{ // Afficher le message d'erreur dans le textArea taReponse.text = event.fault.message; } ]]> </mx:Script> <!-- déclaration du remoteObject qui sait faire des appels distants --> <!-- la destination correspond au nom donné dans le fichier remoting-config.xml --> <!-- On déclare également 2 methodes de callback, qui seront appelées en cas de réussite ou --> <!-- d'échec de l'appel au service --> <mx:RemoteObject id="roWelcomeService" destination="welcomeServiceDest" result="onResult(event)" fault="onFault(event)"/> <!-- interface graphique minimaliste --> <mx:Panel width="451" height="168" layout="absolute" title="Hello World maven"> <mx:Label x="10" y="10" text="Login : "/> <mx:TextInput id="tiLogin" text="Guest" x="66" y="8" /> <mx:Button id="btnAppel" label="Appel de WelcomeService" x="234" y="8" click="doCall()"/> <mx:Label x="10" y="38" text="Réponse :"/> <mx:TextArea id="taReponse" x="81" y="37" width="327" height="81"/> </mx:Panel> </mx:Application>
b) pom.xml
Le pom du projet Flex a deux principaux rôles. Tout d’abord, il permet de configurer la phase de compilation. La liste des options de compilation, comme celles permettant de spécifier des locales par exemple, est consultable à l’adresse suivante: http://www.sonatype.com/books/maven-book/reference/flex-dev-sect-compiling.html. Le 2ème est la copie des fichiers de configuration BlazeDS que nous avions zippés dans le projet valtechFlexBlazeDsResources.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- Le projet parent--> <parent> <groupId>fr.valtech.flex</groupId> <artifactId>valtechFlexBlazeDsTuto</artifactId> <version>1.0</version> <relativePath>../pom.xml</relativePath> </parent> <groupId>fr.valtech.flex</groupId> <artifactId>flexClient</artifactId> <version>1.0</version> <!-- Il faut indiquer que nous voulons un swf en sortie (on peut aussi générer des swc) --> <packaging>swf</packaging> <name>Flex client</name> <build> <sourceDirectory>src/main/flex</sourceDirectory> <testSourceDirectory>src/test/flex</testSourceDirectory> <plugins> <plugin> <!-- le plugin dependency qui va nous permettre de dézipper les fichiers de configuration là où l'on le souhaite--> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack-shared-resources</id> <goals> <goal>unpack-dependencies</goal> </goals> <phase>generate-resources</phase> <configuration> <!-- on dézippe dans le répertoire target/generated-resources --> <outputDirectory> ${project.build.directory}/generated-resources </outputDirectory> <!-- il faut indiquer le nom de l'artefact à dézipper --> <includeArtifactIds>valtechBlazeDsResources</includeArtifactIds> <excludeTransitive>true</excludeTransitive> </configuration> </execution> </executions> </plugin> <plugin> <!-- le plugin de sonatype pour compiler les projets flex --> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-maven-plugin</artifactId> <version>3.2.0</version> <extensions>true</extensions> <configuration> <!-- il faut indiquer où est le fichier services-config.xml --> <services> ${project.build.directory}/generated-resources/flex/services-config.xml </services> <!-- url context de l'application java (web-app) qui sera appelée--> <contextRoot>valtechFlexDemo</contextRoot> </configuration> </plugin> </plugins> </build> <dependencies> <!-- la dépendance vers les fichiers de configuration BlazeDs. Ne pas oublier de stipuler le format (type) --> <dependency> <groupId>fr.valtech.flex</groupId> <artifactId>valtechBlazeDsResources</artifactId> <version>1.0</version> <classifier>resources</classifier> <type>zip</type> <scope>provided</scope> </dependency> <dependency> <groupId>com.adobe.flex.framework</groupId> <artifactId>flex-framework</artifactId> <version>3.3.0.4852</version> <type>pom</type> </dependency> <!-- Si jamais il y a des Test Unitaires dans votre application flex...--> <dependency> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-unittest-support</artifactId> <version>3.2.0</version> <type>swc</type> <scope>test</scope> </dependency> </dependencies> </project>
4) La web application: valtechBlazeDsWebApp
Ce projet représente l’application dans son ensemble. Il est composé des sources java des services exposés à l’applicaiton Flex, des fichiers de configuration de Spring (un pour gérer les beans, un autre pour configurer BlazeDS) et des sources de l’application web (le fichier web.xml, les fichiers html et autres fichiers javascript).
On utilisera de nouveau le plugin dependency pour copier les 2 fichiers de configuration BlazeDS (issus de l’archive zippée) et le fichier swf.
La déclaration des services java disponibles par l’application Flex se fait grâce à l’annotation @RemotingDestination fournie par le projet Spring BlazeDS integration, livré sous forme de jar.
- valtechBlazeDsWebApp
`– pom.xml
`– src
`– main
`– java
`– com.valtech
`– service
`– WelcomeService.java (le service exposé)
`– resources
`– applicationContext.xml (le fichier de configuration de Spring)
`– webapp
`– WEB-INF
`– web.xml (le descripteur de déploiement de la webapp)
`– flex-servlet-context.xml (la configuration de Spring-BlazeDS)
`– flexClient.html (la page qui affiche l’application Flex)
a) applicationContext.xml
Le fichier configuration standard de Spring où sont définis les beans managés par Spring.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- Les déclaration du bean WelcomeService n'est pas présente dans ce fichier de configuration car elle s'appuie sur les annotations) --> </beans>
b) L’implémentation du service: WelcomeService.java
Tout comme le service rendu, l’implémentation du service est minimaliste!
package com.valtech.service; import org.springframework.flex.remoting.RemotingDestination; import org.springframework.stereotype.Service; //déclare le bean comme étant managé par spring @Service // déclare le bean comme étant accessible par Flex @RemotingDestination(value = "welcomeServiceDest") public class WelcomeService { public String sayHello(String pLogin) { return "Bienvenue à toi " + pLogin; } }
c) web.xml
Il est nécessaire de déclarer dans le descripteur de déploiement, le fichier de configuration de Spring à charger au démarrage et la servlet Spring qui configure BlazeDS.
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>simple-form</display-name> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <!-- fichier de configuration de spring --> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <filter> <filter-name>encoding-filter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- configuration de la servlet qui gérera les messages AMF--> <servlet> <servlet-name>spring-flex</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/flex-servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-flex</servlet-name> <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>flexClient.html</welcome-file> </welcome-file-list> </web-app>
d) pom.xml
Mis à part la partie dédiée à la copie des 2 fichiers de ressources et de l’application Flex, ce pom est un classique pom de construction d’applications web.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <!-- Le projet parent--> <parent> <groupId>fr.valtech.flex</groupId> <artifactId>valtechFlexBlazeDsTuto</artifactId> <version>1.0</version> <relativePath>../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>fr.valtech.flex</groupId> <artifactId>valtechFlexBlazeDsWebApp</artifactId> <!-- Nous générons un war --> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>valtechFlexDemo Webapp</name> <build> <finalName>valtechFlexDemo</finalName> <resources> <!-- Le répertoire où seront copiés les fichiers de configuration de BlazeDs --> <resource> <directory>${project.build.directory}/generated-resources</directory> </resource> <resource> <!-- A partir du moment où l'on ajoute un 2ème répertoire de ressources, il faut redéclarer le répertoire par défaut--> <directory>${basedir}/src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack-shared-resources</id> <goals> <goal>unpack-dependencies</goal> </goals> <phase>generate-resources</phase> <configuration> <!-- le zip contenant les 2 fichiers de configuration de BlazeDs sera décompressé dans le répertoire target/generated-resources qui a été déclaré comme répertoire de ressources. C'est exactement le même principe que ce qui avait été fait dans le projet Flex--> <outputDirectory> ${project.build.directory}/generated-resources </outputDirectory> <includeArtifactIds>valtechBlazeDsResources</includeArtifactIds> <excludeTransitive>true</excludeTransitive> </configuration> </execution> <execution> <id>copy-flex-app</id> <phase>generate-resources</phase> <goals> <goal>copy</goal> </goals> <configuration> <!-- Cette fois ci, c'est l'application Flex qui est copiée dans la web-app. On copie le swf dans le répertoire target/generated-flex. Par la même occasion on renomme le swf en flexClient.swf, cela évitera de changer le fichier html qui charge le swf --> <artifactItems> <artifactItem> <groupId>fr.valtech.flex</groupId> <artifactId>flexClient</artifactId> <version>1.0</version> <type>swf</type> <outputDirectory> ${project.build.directory}/generated-flex </outputDirectory> <destFileName>flexClient.swf</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <!-- Il faut configurer le plugin maven-war pour ajouter un répertoire de ressources supplémentaire, ici le répertoire dans lequel le swf est copié (target/generated-flex) --> <webResources> <resource> <directory>${project.build.directory}/generated-flex</directory> </resource> </webResources> </configuration> </plugin> </plugins> </build> <dependencies> <!-- la dépendance vers le fichier zip qui contient les configurations BlazeDs--> <dependency> <groupId>fr.valtech.flex</groupId> <artifactId>valtechBlazeDsResources</artifactId> <version>1.0</version> <classifier>resources</classifier> <type>zip</type> <scope>provided</scope> </dependency> <!-- la dépendance vers le projet flex--> <dependency> <groupId>fr.valtech.flex</groupId> <artifactId>flexClient</artifactId> <version>1.0</version> <type>swf</type> <scope>provided</scope> </dependency> <!-- les dépendances BlazeDs--> <dependency> <groupId>com.adobe.flex.compiler</groupId> <artifactId>flex-messaging-common</artifactId> <version>3.3.0.4852</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-remoting</artifactId> <version>3.2.0.3978</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-core</artifactId> <version>3.2.0.3978</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-opt</artifactId> <version>3.2.0.3978</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-proxy</artifactId> <version>3.2.0.3978</version> </dependency> <!-- Les dépendances spring-flex --> <dependency> <groupId>org.springframework.flex</groupId> <artifactId>spring-flex</artifactId> <version>1.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>${spring.version}</version> </dependency> <!-- Les autres dépendences --> <dependency> <groupId>xalan</groupId> <artifactId>xalan</artifactId> <version>2.7.1</version> </dependency> </dependencies> <properties> <spring.version>2.5.6</spring.version> </properties> </project>
5) Déploiement
Un simple ‘mvn clean install’ exécuté à la racine du projet valtechFlexBlazeDsTuto devrait suffire pour compiler les sources et générer le war.
Lors de la configuration du serveur d’application, si le contexte de déploiement est demandé, il est important de bien spécifier le contexte indiqué dans le pom.xml de l’application Flex et le web.xml de la web-app (‘valtechFlexDemo‘ dans notre exemple). Par exemple pour tomcat:
<Context path="/valtechFlexDemo" debug="0" privileged="true" docBase="D:/JBC/valtechFlexBlazeDsTuto/valtechBlazeDsWebApp/target/valtechFlexDemo"> </Context>
Une fois le serveur démarré, il suffit de lancer un navigateur web et pointer sur l’adresse http://localhost:8080/valtechFlexDemo.
IV) Aller plus loin
L’implémentation de services Java déclarant en entrée et/ou en sortie des objets complexes qui collent plus à la réalité ne devrait pas révolutionner la configuration BlazeDS.
La bonne intégration de BlazeDs et de Spring permet d’associer ‘Spring Security’ très simplement.
Dans un prochain tutoriel, nous aurons l’occasion de créer une application intégrant également les bonnes pratiques de développement telles que la délégation des appels de services ou encore la mise en œuvre du pattern MVC via Flex-MVC (Cairngorm).
V) Références
- http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/index.html
- http://blog.springsource.com/2009/06/10/using-spring-blazeds-integration-10/
- http://www.springbyexample.org/examples/simple-flex-webapp.html
- http://www.sonatype.com/books/maven-book/reference/flex-dev.html
JB Cazaux, Consultant Valtech Java/JEE. jean-baptiste.cazaux[at]valtech.fr
August 31st, 2009 at 2:39 pm
## Traduction :
Salut Jean,
Je n’ai pas vraiment lu votre message, car je ne parle pas français (portugais ou anglais seulement = D)
Mais j’ai remarqué que vous suggérez aux gens d’utiliser le repository public de Sonatype. Or celui-ci sera décommissionné dans quelques temps. Celui a utiliser est :
http://repository.sonatype.org/content/groups/flexgroup
Nous avons aussi des instructions pour cela sur le wiki :
https://docs.sonatype.org/display/FLEXMOJOS/Referencing+Flexmojos+maven+repository
##Traduction
Hi Jean,
I didn’t really read your post, sorry don’t know french, just portuguese or english =D
But I did notice you suggesting people to use the public repo on sonatype, well, that repo will be decommissioned in some time. The right one to use is http://repository.sonatype.org/content/groups/flexgroup
We also have some instructions for it on wiki.
https://docs.sonatype.org/display/FLEXMOJOS/Referencing+Flexmojos+maven+repository
VELO
December 19th, 2009 at 11:42 am
Merci pour cet article intéressant pour prendre en main ces différentes technos.
Pour la compile, j’ai ajouté les repo suivants dans le pom parent (thanks VELO):
flexmojos-repository
http://repository.sonatype.org/content/groups/public/
flexmojos-repository
http://repository.sonatype.org/content/groups/public/
Au déploiement de la webapp dans Tomcat 6:
21 dÚc. 2009 23:27:01 org.apache.catalina.core.StandardContext filterStart
GRAVE: Exception starting filter encoding-filter
java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filter
Any idea ? Je finirai bien par trouver. Je vais essayer avec d’autres conteneurs de servlets au cas où.
Bonne continuation.
Olivier
December 19th, 2009 at 11:33 pm
Pour résoudre cette erreur, il faut passer la dépendance servlet-api en scope provided (au lieu de compile) dans le pom de la webapp.
Une fois que c’est fait, le déploiement de la webapp dans Tomcat échoue encore mais cette fois-ci sur l’erreur suivante:
GRAVE: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘_messageBrokerDefaultHandlerMapping’: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘_messageBroker’: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Flex configuration file does no
t exist at path: /WEB-INF/classes/flex/services-config.xml
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
O.
December 20th, 2009 at 2:16 am
Pour la 2ème erreur je pense que le fichier services-config.xml n’est pas copié dans le war ou dans le répertoire target. Est ce que le projet de ressource a bien été construit sans erreur ? Normalement ce fichier est dézippé au bon endroit.