Category: Maven

J2EE7 – Pom minimal

By , 15/07/2014

J’ai souvent utilisé l’archetype Maven jboss-javaee6-webapp-archetype pour commencer un projet J2EE6. En cherchant sur internet la version suivante pour un projet de type J2EE7, j’ai découvert ce fichier pom.xml minimaliste :

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>groupId</groupId>
    <artifactId>artifactId</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>${artifactId}</finalName>
    </build>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
</project>

Voici la source : http://www.adam-bien.com/roller/abien/entry/essential_maven_pom_for_javaee.

Pour compléter ce fichier il est possible d’ajouter un des nombreux boms proposés par le projet wildfly en version 8.0.0.Final (https://github.com/wildfly/boms) :

  • jboss-javaee-7.0-with-all
  • jboss-javaee-7.0-with-hibernate
  • jboss-javaee-7.0-with-hibernate3
  • jboss-javaee-7.0-with-infinispan
  • jboss-javaee-7.0-with-logging
  • jboss-javaee-7.0-with-resteasy
  • jboss-javaee-7.0-with-security
  • jboss-javaee-7.0-with-tools
  • jboss-javaee-7.0-with-transactions

Par exemple :

<dependencyManagement>
    <dependencies>
        <dependency>
           <groupId>org.wildfly.bom</groupId>
           <artifactId>jboss-javaee-7.0-with-all</artifactId>
           <version>8.0.0.Final</version>
           <type>pom</type>
           <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Au final, je n’ai pas trouvé l’archetype que je souhaitais, mais je suis tout de même tombé sur une bonne astuce pour débuter un projet J2EE7 très rapidement.

Maven – Wildfly plugin

By , 08/03/2014

J’ai découvert qu’il existait un plugin maven pour le serveur d’application Wildfly qui se comporte exactement comme le plugin maven pour tomcat. Pour l’utiliser, il faut ajouter ces quelques lignes dans le fichier pom.xml.

<project>
    ...
    <build>
        ...
        <plugins>
            ...
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.0.1.Final</version>
            </plugin>
            ...
        </plugins>
        ...
    </build>
...
</project>

Le goal wildfly:run compile et package le projet, puis le déploie dans une instance du serveur. Deux possibilités, soit la variable d’environnement wildfly.home existe et le serveur installé à cet emplacement est utilisé, soit elle n’existe pas et le serveur wildfly est téléchargé puis déployé dans le répertoire target du projet.

Le plugin permet beaucoup plus de choses que le simple démarrage de l’application dans un conteneur piloté par Maven. Pour plus d’information, son adresse est la suivante : https://docs.jboss.org/wildfly/plugins/maven/latest/.

JRebel m2e connector

By , 08/02/2013

Le connecteur m2e de JRebel ne s’installe plus à partir du marketplace eclipse. Pour l’installer il faut passer par la mise à jour manuelle. Dans les menus de l’IDE : Help -> Install New software…

Le site d’update est : http://update.zeroturnaround.com/update-site. Le plugin à installer : JRebel m2eclipse.

Eclipse compiler & m2e

By , 24/01/2012

Récemment, j’ai appris que l’IDE eclipse n’utilisait pas le compilateur de la JDK (javac) pour transformer les fichiers Java en Class. C’est d’ailleurs pour cela qu’il est possible de développer et compiler du code sans avoir installer la JDK sur son ordinateur.

Par défaut, Maven utilise javac pour compiler les sources Java. Or, dans certains cas, le compilateur eclipse (JDT) accepte de compiler des classes là où javac sort en erreur. Par exemple, voici un code qui compile avec le JDT et pas avec javac :

package com.test;

public class GenericMethod {

    private Object value;

    @SuppressWarnings("unchecked")
    public <X> X getValue() {
        return (X) value;
        // le cast n'est obligatoire que pour que javac compile
        // avec le compilateur eclipse, il n'est pas nécessaire
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

Voici la classe pour appeler la méthode :

package com.test;

public class GenericMethodTest {

    public static void main(String[] args) {
        GenericMethod method = new GenericMethod();
        method.setValue(3);

        int[] array = new int[] {1, 2};

        array[0] = method.getValue();
        System.out.println(array[0]);
    }
}

Avec javac, la ligne 11 de la classe GenericMethodTest provoque l’erreur suivante :

type parameters of <X>X cannot be determined;no unique maximal instance exists for type variable X with upper bounds int,java.lang.Object

Il peut donc être essentiel d’utiliser dans le processus de build un autre compilateur que javac. Il est possible de configurer le plugin maven-compiler-plugin afin d’utiliser un compilateur alternatif. Par exemple, pour utiliser le compilateur eclipse c’est très simple :

<project>
  [...]
  <build>
    [...]
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <compilerId>eclipse</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
          </dependency>
        </dependencies>
      </plugin>
  [...]
</project>

Le build maven fonctionne parfaitement, en revanche l’utilisation du compilateur alternatif a des effets secondaires lorsqu’il est utilisé par le plugin eclipse m2e. La modification des fichiers .classpath et .project ne fonctionne plus correctement et cela provoque :

  • La nature java du projet n’est pas détectée,
  • Les dépendances ne sont plus récupérées,
  • Les répertoires sources (src/main/java, src/main/resources, etc.) ne sont plus référencés

Le problème du nouveau plugin m2e c’est qu’il ne reconnaît les projets maven en tant que projets java que lorsque le compilateur utilisé est javac. Pour configurer un projet eclipse utilisant le compilateur eclipse, il est donc nécessaire d’indiquer à m2e qu’il s’agit bien d’un projet Java :

<pluginManagement>
  <plugins>
    <plugin>
      <groupId>org.eclipse.m2e</groupId>
      <artifactId>lifecycle-mapping</artifactId>
      <version>1.0.0</version>
      <configuration>
        <lifecycleMappingMetadata>
          <pluginExecutions>
            <pluginExecution>
              <pluginExecutionFilter>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <versionRange>[2.0,)</versionRange>
                <goals>
                  <goal>compile</goal>
                  <goal>testCompile</goal>
                </goals>
              <parameters>
                <compilerId>eclipse</compilerId>
              </parameters>
             </pluginExecutionFilter>
             <action>
               <configurator>
                 <id>org.eclipse.m2e.jdt.javaConfigurator</id>
               </configurator>
             </action>
           </pluginExecution>
          </pluginExecutions>
        </lifecycleMappingMetadata>
      </configuration>
    </plugin>
  </plugins>
</pluginManagement>

Dès que m2e reconnaît le projet en tant que projet java, la fonction Update project configuration, configurera les répertoires sources et mettra à jour le classpath du projet.

Appliation J2EE6 avec JBoss 7 et Maven

By , 03/08/2011

JBoss propose un certain nombre d’archetypes dont un qui génère  une application J2EE6 pour JBoss 7 : org.jboss.spec.archetypes:jboss-javaee6-webapp. Or, par défaut, maven ne connait pas cet archetype. Voici comment réussir à l’utiliser dans Eclipse.

Avant toute chose, il faut vérifier que maven est configuré pour aller chercher des librairies sur le repository JBoss : le fichier settings.xml (~/.m2/settings.xml ou $MAVEN_HOME/conf/settings.xml) doit contenir le code XML suivant :

<settings>
 ...
  <profiles>
    ...
    <profile>
      <id>jboss-public-repository</id>
      <repositories>
        <repository>
          <id>jboss-public-repository-group</id>
          <name>JBoss Public Maven Repository Group</name>
          <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </releases>
          <snapshots>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>jboss-public-repository-group</id>
          <name>JBoss Public Maven Repository Group</name>
          <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </releases>
          <snapshots>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>

  </profiles>

  <activeProfiles>
    <activeProfile>jboss-public-repository</activeProfile>
  </activeProfiles>
  ...
</settings>

Ensuite, pour créer le projet dans Eclipse, il faut commencer par installer le catalogue JBoss : Windows -> Preferences… puis dans la fenêtre Maven -> Achetypes cliquer sur le bouton  Add Remote Catalog… Saisir https://repository.jboss.org/nexus/content/groups/public/archetype-catalog.xml dans l’intitulé Catalogue File et JBoss dans Description. Après l’opération, il ne reste plus qu’à accéder au wizard de création d’un projet Maven (File -> New -> Project… puis Maven project) et de sélectionner l’archetype jboss-javaee6-webapp.

Le squelette de l’application est celui-ci :

/home/…/jboss-webapp-j2ee6
|– pom.xml
|– readme.html
|– readme.md
`– src
|– main
|   |– java
|   |   `– test
|   |       `– jboss_webapp_j2ee6
|   |           |– controller
|   |           |   `– MemberRegistration.java
|   |           |– data
|   |           |   `– MemberListProducer.java
|   |           |– model
|   |           |   `– Member.java
|   |           |– rest
|   |           |   |– JaxRsActivator.java
|   |           |   `– MemberResourceRESTService.java
|   |           `– util
|   |               `– Resources.java
|   |– resources
|   |   |– import.sql
|   |   `– META-INF
|   |       `– persistence.xml
|   `– webapp
|       |– index.html
|       |– index.xhtml
|       |– resources
|       |   |– css
|       |   |   `– screen.css
|       |   `– gfx
|       |       |– banner.png
|       |       `– logo.png
|       `– WEB-INF
|           |– beans.xml
|           |– faces-config.xml
|           `– templates
|               `– default.xhtml
`– test
|– java
|   `– test
|       `– jboss_webapp_j2ee6
|           `– test
|               `– MemberRegistrationTest.java
`– resources
`– arquillian.xml

Ce qui équivaut à une application de départ avec un exemple JSF2 s’appuyant sur une base de données embarquée avec quelques classes constituant un modèle MVC, un exemple de service web REST, et un exemple de test unitaire avec Arquillian. A noter aussi, l’utilisation d’un EJB3 archivé dans un WAR et non un EAR comme il aurait fallu le faire avec J2EE5.

Pour déployer l’application il faut la packager et utiliser le plugin JBoss de déploiement déjà configuré par l’archetype (maven package jboss-as:deploy). Attention, pour que tout se déroule correctement, il faudra avoir démarré votre serveur JBoss7 au préalable.

C et C++ avec Maven : maven-nar-plugin

By , 14/07/2011

J’ai eu l’occasion de travailler sur plusieurs outils de build très différents comme MakeFile, Ant ou Maven. Chacun possède ses spécificités, ses avantages et ses inconvénients. Mais en règle générale, j’ai l’impression que les gens associent souvent un outil avec une technologie particulière : MakeFile pour C/C++, Ant ou Maven pour le Java. En réalité il est possible d’utiliser ces outils de build indépendamment des technologies utilisées.

Je pense que Maven est l’outil le plus abouti sur lequel j’ai travaillé jusqu’à présent. Il y a peu de temps, je découvrais qu’il était possible de l’utiliser avec des projets Flex grâce à l’extension FlexMojo. Cela m’a redonner envie de trouver une solution simple pour utiliser Maven dans un projet C/C++.

Jusqu’à aujourd’hui je ne connaissais que le plugin Native mais je l’ai toujours trouvé trop compliqué et au final, je n’ai jamais réussi à l’utiliser. C’est dans ce contexte d’échec que je viens de découvrir une extension C/C++ (et Fortran) qui fonctionne sans effort ou presque : maven-nar-plugin. Lorsque j’écris “presque” sans effort c’est tout simplement parce que les plugins nécessaires ne sont pas encore disponible sur le repository central.

Voici la structure standard des répertoires de cette extension :

/yourproject
    /src
        /main
            /java
            /resources
            /include
            /c++
            /c
            /fortran
        /test
            /java
            /resources
            /include
            /c++
            /c
            /fortran

Pour installer maven-nar-plugin dans le répository local, il est nécessaire d’installer au préalable la librairie net.sf.antcontrib:cpptasks-parallel qui se trouve sur le repository GIT http://github.com/duns/cpptasks-parallel.

git clone http://github.com/duns/cpptasks-parallel cpptasks-parallel

Puis

cd cpptasks-parallel
mvn clean install

Il faut procéder de la même façon pour installer le plugin nar qui se trouve sur le repository GIT https://github.com/duns/maven-nar-plugin.git et l’archetype maven-archetype-nar-exec sur le repository https://github.com/duns/maven-archetype-nar-exec.git. Cet archetype va permettre de créer un projet exemple pour débuter rapidement grâce à la commande suivante :

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-nar-exec
        -DarchetypeVersion=1.0-SNAPSHOT
        -DgroupId=com.mycompany.app
        -DartifactId=my-cpp-app

Après l’exécution du build Maven sur ce nouveau projet (mvn install par exemple), l’exécutable se retrouve dans le répertoire target/nar/my-cpp-app-1.0-SNAPSHOT-*-executable/bin/*/my-cpp-app.

tomcat-maven-plugin : debug

By , 29/04/2011

Le plugin tomcat de Maven est très pratique lors du développement d’une application web. Voici comment le configurer :

 <!-- Embedded Tomcat (package tomcat:run) -->
 <!-- Standalone Tomcat (package tomcat:deploy) -->
 <plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>tomcat-maven-plugin</artifactId>
   <configuration>
     <path>/${project.build.finalName}</path>
     <!-- Embedded port -->
     <port>9090</port>
   </configuration>
 </plugin>

Le plugin démarre le serveur dans la sa propre JVM. Pour pouvoir débuger votre application, il faut donc uniquement démarrer Maven avec l’option de debug comme cela :

mvn tomcat:run -DXdebug -DXnoagent -Djava.compiler=NONE -DXrunjdwp:transport=dt_socket,address=3998,suspend=n,server=y

Ou bien, si vous utilisez eclipse avec le plugin m2eclipse : cliquer avec le bouton droit de votre souris sur le projet : Debug As -> Maven build … .

Maven et SeamTest

By , 22/03/2011

L’intégration des tests unitaires SeamTest dans un projet Maven est assez compliquée. Voici un exemple concret :

Présentation du projet

Avant de rentrer dans des détails techniques, je préfère vous parler de l’application qui va me servir de base pour intégrer mon test SeamTest.

Vision fonctionnelle

J’ai choisi de me baser sur l’exemple “hello world” du livre Seam Framework: Experience the Evolution of Java EE 2nd edition. Vous pouvez retrouver les sources des exemples du livre à l’adresse suivante : http://solutionsfit.com/blog/books/. Malheureusement, l’auteur utilise Ant et non Maven pour gérer la compilation de ses projets.

J’ai rajouté l’utilisation d’un service EJB Stateless pour démontrer la possibilité d’utiliser SeamTest dans un contexte technique hétérogène. Voici le diagramme des cas d’utilisation de l’application :

Cas d'utilisation de l'application

Vision maven

Le projet est composé d’un module père ayant trois modules fils :

seamtest-parent
|– seamtest-ear
|– seamtest-ejb
`– seamtest-webapp

Vous pouvez checkouter les sources à l’adresse suivante : https://subversion.assembla.com/svn/everythingiswrong/seamtest-parent/.

Dans le reste de l’article, je vais me focaliser sur le module seamtest-ejb car c’est lui qui contient le composant Seam, la persistance et l’EJB Stateless à tester.

Composant Seam à tester

Nous allons tester le composant qui va :

  • Enregistrer une nouvelle personne dans la base de données
  • Rechercher toutes les personnes de la base de données
@Stateful
@Name("manager")
public class ManagerAction extends Manager {
  @In
  private Person person;

  @Out
  private List<Person> fans;

  @EJB
  private CalculService calculService;

  @PersistenceContext
  private EntityManager em;

  //Méthode à tester.
  public void sayHello () {
    em.persist (person);
    fans = em.createQuery("select p from Person p").getResultList();
  }

  // Méthode pour vérifier l'injection de l'EJB Stateless dans le composant Seam
  public int additionner(int a, int b) {
    return (int) calculService.addition(a, b);
  }

  @Remove
  @Destroy
  public void destroy() {
  }
}

Installation et configuration

Pour information, SeamTest utilise le serveur JBoss embedded.

Installation de JBoss Embedded

Cette installation se résume à la copie du répertoire booststrap qui est dans la distribution de Seam (par exemple ici) dans le répertoire src/test.

Le fichier “pom.xml”

Ce fichier doit contenir l’ensemble des librairies qui vont permettre de démarrer et d’exécuter le serveur JBoss embedded. Il doit aussi prendre en compte le répertoire de bootstrap ajouté précédemment dans les ressources des tests.

<dependencies>
  ...
  <!-- dépendances des tests unitaites : http://community.jboss.org/thread/18299 -->
  <!-- dependencies related to JBoss Embedded for Seam 2.X.X -->
  <dependency>
    <groupId>org.jboss.seam.embedded</groupId>
    <artifactId>jboss-embedded-all</artifactId>
    <version>beta3.SP12</version>
    <scope>test</scope>
    <exclusions>
      <exclusion>
        <groupId>org.jboss.microcontainer</groupId>
        <artifactId>jboss-deployers-client-spi</artifactId>
      </exclusion>
      <exclusion>
        <groupId>org.jboss.microcontainer</groupId>
        <artifactId>jboss-deployers-core-spi</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.jboss.seam.embedded</groupId>
    <artifactId>hibernate-all</artifactId>
    <version>beta3.SP12</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.jboss.seam.embedded</groupId>
    <artifactId>thirdparty-all</artifactId>
    <version>beta3.SP12</version>
    <scope>test</scope>
  </dependency>

  <!-- dependencies related to JBoss MicroContainer -->
  <!-- java.lang.NoClassDefFoundError: javax/faces/application/Application -->
  <dependency>
    <groupId>javax.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>1.2_09</version>
    <scope>test</scope>
  </dependency>

  <!-- java.lang.NoClassDefFoundError: org/jboss/el/ExpressionFactoryImpl -->
  <dependency>
    <groupId>org.jboss.el</groupId>
    <artifactId>jboss-el</artifactId>
    <version>1.0_02.CR4</version>    <!-- http://seamframework.org/Community/IllegalAccessErrorAfterUpgradingTo212CR1 -->
    <scope>test</scope>
  </dependency>

  <!-- dependencies related to TestNG -->
  <dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>5.8</version>
    <classifier>jdk15</classifier>
    <scope>test</scope>
  </dependency>
</dependencies>
<build>
  <testResources>
    <testResource>
      <directory>src/test/resources</directory>
      <filtering>true</filtering>
    </testResource>
    <testResource>
      <directory>src/test/bootstrap</directory>
      <filtering>false</filtering>
    </testResource>
    <testResource>
      <directory>src/test/bootstrap</directory>
      <filtering>true</filtering>
      <includes>
        <include>**/*.xml</include>
      </includes>
    </testResource>
  </testResources>
  ...
</build>

Remarque : à l’heure actuelle la version la plus récente du conteneur est la beta3.SP12.

Fichiers de tests

Dans la pratique, on ajoute toujours un fichier seam.properties vide dans le classpath des jar contenant des composants Seam. Dans le cas du test, ce fichier doit contenenir au minimum l’information sur le nom JNDI des EJB :

org.jboss.seam.core.init.jndiPattern = #{ejbName}/local

La classe de test doit étendre SeamTest. Elle peut ensuite utiliser l’EL pour référencer les composants Seam :

public class ManagerActionTest extends SeamTest {
  private static Logger LOGGER = Logger.getLogger(ManagerActionTest.class);

  @Test
  public void testSayHello() {
    try {
      new ComponentTest() {
        @Override
        protected void testComponents() throws Exception {
          setValue("#{person.name}", "Yan");
          invokeMethod("#{manager.sayHello}");
          List<Person> fans = (List<Person>) getValue("#{fans}");
          assertNotNull(fans);
          assertEquals(1, fans.size());
          assertEquals("Yan", fans.get(0).getName());
          // Test le service EJB
          assertEquals(3, invokeMethod("#{manager.additionner(1, 2)}"));
        }
      }.run();
    } catch (Exception e) {
      LOGGER.error("TEST KO : " + e.getMessage());
      fail("TEST KO : " + e.getMessage());
    }
  }
}

En utilisant Hibernate, vous pouvez exécuter des scripts SQL au déploiement de votre test en ajoutant un fichier import.sql dans le classpath de test (src/test/resources). Cela dit,  dans ce cas, je conseillerai plutôt d’utiliser l’intégration avec DBUnit.

Exécution

Pour exécuter les tests il faut lancer la commande mvn clean test.

Variantes

Intégration avec DBUnit

L’intégration est possible entre seamTest et DBUnit. La classe de test doit étendre DBunitSeamTest et implémenter la méthode prepareDBUnitOperations(). Il faut aussi donner à TestNg la nom JNDI de la source de données vers la base de données ainsi que le type de la base de données (HSQL ou MYSQL). Pour cela, il faut configurer le plugin surefire comme cela :

<build>
  ...
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
      <systemProperties>
        <property>
          <name>datasourceJndiName</name>
          <value>java:/DefaultDS</value>
        </property>
        <property>
          <name>database</name>
          <value>HSQL</value>
        </property>
      </systemProperties>
      <argLine>-Dsun.lang.ClassLoader.allowArraySyntax=true</argLine>
    </configuration>
 ...
</build>

Remarque : deux propriétés pour déclarer le type de la source de données et son nom JNDI ainsi qu’un argument pour permettre au serveur JBoss Embedded de s’éxécuter avec une JDK 1.6 (par défaut ce serveur n’est compatible qu’avec une JDK1.5).

Pour information, DBUnit propose deux implémentations différentes pour décrire les données d’une base : le FlatXmlDataSet et le XmlDataSet (http://dbunit.sourceforge.net/components.html).  SeamTest ne support que le FlatXmlDataSet.

Dépendances sur des projets ou modules de type EJB

Dans le cas où votre module dépende d’un autre module EJB, il faut arriver à déployer la dépendance de type EJB dans le conteneur JBoss embedded. Il est possible de faire cette opération avec le plugin maven maven-dependency-plugin comme cela :

<build>
  ...
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>copy</id>
        <phase>process-test-resources</phase>
        <goals>
          <goal>copy</goal>
        </goals>
        <configuration>
          <artifactItems>
            <artifactItem>
              <groupId>...</groupId>
              <artifactId>...</artifactId>
              <version>...</version>
              <type>...</type>
              <classifier>...</classifier>
              <overWrite>false</overWrite>
              <outputDirectory>${project.build.directory}/test-classes/deploy</outputDirectory>
            </artifactItem>
          </artifactItems>
        </configuration>
      </execution>
    </executions>
  </plugin>
  ...
</build>

Remarque : la copie de la dépendance se déroule avant la phase d’exécution des tests.

jaxb2-maven-plugin : plusieurs exécutions successives de jaxb2:xjc

By , 11/02/2011

Dans ce ticket, je vais expliquer comment bien configurer le plugin jaxb2-maven-plugin dans le cas où l’on souhaite transformer des fichiers XSD en classes java vers des packages différents. Il faut savoir qu’avec ce plugin il n’est pas possible de définir plusieurs packages de destination dans une même exécution.

Dans l’exemple choisi, je génère deux classes Java à partir de deux fichier XSD vers deux packages différents :

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jaxb2-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>id1</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>xjc</goal>
      </goals>
      <configuration>
        <clearOutputDir>false</clearOutputDir>
        <staleFile>${project.build.directory}/generated-sources/jaxb/.staleFlag-id1</staleFile>
        <schemaDirectory>${basedir}/src/main/resources/id1</schemaDirectory>
        <packageName>id1</packageName> <!-- The name of your generated source package -->
      </configuration>
    </execution>
    <execution>
      <id>id2</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>xjc</goal>
      </goals>
      <configuration>
        <clearOutputDir>false</clearOutputDir>
        <staleFile>${project.build.directory}/generated-sources/jaxb/.staleFlag-id2</staleFile>
        <schemaDirectory>${basedir}/src/main/resources/id2</schemaDirectory>
        <packageName>id2</packageName> <!-- The name of your generated source package -->
      </configuration>
    </execution>
  </executions>
  <dependencies>
     <dependency>
       <groupId>xerces</groupId>
       <artifactId>xercesImpl</artifactId>
       <version>2.8.1</version>
     </dependency>
  </dependencies>
</plugin>

A noter que pour chaque exécution :

  • Il est nécessaire d’utiliser un identifiant unique. Sinon maven n’arrivera pas à exécuter le plugin.
  • Il faut impérativement utiliser l’option staleFile pour associer un fichier différent à chaque exécution (ce fichier sert au plugin pour savoir si les classes Java sont déjà générées). Sans cela, la seconde exécution ne génèrera pas de classe Java.
  • Il faut indiquer au plugin de ne pas nettoyer le répertoire de génération avant l’exécution (option clearOutputDir à false) car c’est son comportement par défaut. Sans cela, la seconde exécution supprimera les classes générées pas la première.

Voici l’adresse de l’exemple associé : https://subversion.assembla.com/svn/everythingiswrong/tutorial-jaxb2-maven-plugin/.

jaxws-maven-plugin : générer des services SOAP à partir de plusieurs WSDL

By , 03/01/2011

Dans ce poste je vais générer des services SOAP java à partir de deux fichiers WSDL. La contrainte que je m’impose est de générer dans un même package toutes les classes java. Il faut paramétrer le plugin jaxws-maven-plugin en lui donnant un nom de package pour l’ensemble des WSDL (ou bien utiliser le même namespace pour les deux WSDL et leurs objets associés) :

<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>jaxws-maven-plugin</artifactId>
   <executions>
      <execution>
         <goals>
            <goal>wsimport</goal>
         </goals>
      </execution>
   </executions>
   <configuration>
      <packageName>com.example.myschema</packageName>
   </configuration>
...
</plugin>

Le problème c’est que le plugin génère les objets dans l’ordre de traitement des WSDL. Cela implique que la classe ObjectFactory.java qui permet d’instancier les objets issus de la génération est créée une première fois pour les objets du premier WSDL puis écrasée par la seconde génération avec les objets du second WSDL.

Pour résoudre ce problème, il est possible de mutualiser les objets des deux WSDL dans un même schéma XSD qui va englober tous les objets des deux WSDL. La première génération va toujours être écrasée par la seconde mais cette fois si, les deux générations produisent exactement les mêmes objets et l’objet ObjectFactory va pouvoir instancier tous les objets des deux WSDL.

Voici un exemple : https://subversion.assembla.com/svn/everythingiswrong/multiple-wsdl-same-package/

OfficeFolders theme by Themocracy