Posts tagged: XML

Java EE 7 : Fichiers de déploiements (deployment descriptors)

By , 24/01/2014

Il est toujours compliqué de savoir quelles versions il faut utiliser pour les fichiers de description des déploiements (comme le fichier web.xml par exemple). Cet article a pour but de référencer les principaux fichiers utilisés dans le cadre d’une application java J2EE 7 avec une petite explication sur leur utilité.

CDI 1.1

Il s’agit du fichier beans.xml. Il est obligatoire si l’on souhaite utiliser l’injection de dépendance. Attention, il peut resté totalement vide.

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
</beans>

Ce fichier doit être déposé dans le répertoire WEB-INF/lib ou WEB-INF/classes/META-INF pour un archive web (WAR) et META-INF/ dans une archive java (JAR)

Pour plus d’information : JSR 346: Contexts and Dependency Injection for JavaTM EE 1.1

Bean Validation 1.1

Deux fichiers pour cette JSR (349) : validation.xml et constraints.xml

<validation-config
        xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.1.xsd"
        version="1.1">
</validation-config>
<constraint-mappings
        xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
        version="1.1">
</constraint-mappings>

Ces fichiers doivent être déposés dans le répertoire META-INF d’une archive Java (JAR).

Pour plus d’information : JSR 349: Bean Validation 1.1

JPA 2.1

Pour avoir accès à la base de données, il est obligatoire de posséder le fichier persistence.xml.

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
</persistence>

Il existe aussi un fichier de mapping des entités qui n’est pas obligatoire : orm.xml. Il permet, entre autre, de référencer des classes qui se trouvent dans une même application mais dans des librairies tierces (JAR).

<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
                 version="2.1">
</entity-mappings>

Ces deux fichiers doivent être positionnés dans le répertoire META-INF/ dans une archive java (JAR). Pour rappel, seul le fichier persistence.xml est obligatoire s’il est question d’avoir des accès avec une base de données.

Pour plus d’information : JSR 338: JavaTM Persistence 2.1 :

EJB 3.2

Ce fichier n’est pas non plus obligatoire : ejb-jar.xml.

<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"
         version="3.2">
</ejb-jar>

Ce fichier doit être positionné dans le répertoire META-INF/ dans une archive java (JAR).

Pour plus d’information : JSR 345: Enterprise JavaBeansTM 3.2

Servlet 3.1

Pour plus d’information : JSR 340: Java Servlet 3.1 Specification

JSF 2.2

Pour la partie vue de J2EE7, le fichier faces-config.xml n’est plus obligatoire.

<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">
</faces-config>

Un fichier JSF est un fichier XML avec l’extention *.xhtml. Il se présente sous cette forme :

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
</html>

Le fichier faces-config.xml doit se trouver dans le répertoire WEB-INF/ d’une archive web (WAR).

Pour plus d’information : JSR 344: JavaServerTM Faces 2.2

JAX-WS 2.2

Pour les services web, il s’agit du fichier webservices.xml :

<webservices xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/javaee_web_services_1_4.xsd"
             version="1.4">
</webservices>

Il doit être positionné dans le répertoire WEB-INF/ d’une archive web (WAR).

Pour plus d’information : JSR 224: JavaTM API for XML-Based Web Services (JAX-WS) 2.0, JSR 109: Implementing Enterprise Web Services, JSR 181: Web Services Metadata for the JavaTM 

Conclusion

Pour plus d’information et connaître les autres fichiers qui permettre de réaliser d’autres types de traitements, par exemple des batchs en J2EE7 ou décrire une archives entreprises (EAR) : http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html#7

Cet article est fortement inspiré de ce site internet : http://antoniogoncalves.org/2013/06/04/java-ee-7-deployment-descriptors/

JBoss 7 : Datasources dans un WAR

By , 28/09/2012

Avec JBoss 7, il est possible de déclarer une datasource JNDI dans une archive WAR. Pour cela, il faut déposer un fichier ma-datasource-ds.xml dans le répertoire WEB-INF avec la déclaration de la source de données. Par exemple :

<?xml version="1.0" encoding="UTF-8"?>

<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
   <!-- The datasource is bound into JNDI at this location. We reference
      this in META-INF/persistence.xml -->
   <datasource jndi-name="java:jboss/datasources/maDS"
          pool-name="mysqlds"
          enabled="true"
          use-java-context="true">
      <connection-url>jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8</connection-url>
      <driver>mysql</driver>
      <security>
         <user-name>root</user-name>
         <password>123456</password>
      </security>
   </datasource>
</datasources>

La valeur de l’élément driver, est le nom du driver installé sur le serveur. Pour l’installer, il est possible de copier le jar dans le répertoire de déploiement du serveur (cp mysql.jar <as7>/standalone/deployments).

Sources : https://community.jboss.org/thread/204245, https://community.jboss.org/wiki/DataSourceConfigurationInAS7, https://github.com/abstractj/as-quickstarts/blob/40f8cae2ce9388151e1a07f743df74e59c7848bc/kitchensink-html5-mobile/src/test/resources/arquillian-ds.xml

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.

Fiji 2.0 : Intégration de FusionCharts et JSF

By , 01/03/2011

Après avoir parlé de Fiji il y a quelques mois, j’ai souhaité développer un petit exemple pour mettre en pratique l’intégration Flex dans une page JSF 2. Pour cela j’ai choisis d’intégrer un graphique FusionCharts dans une page JSF. Pour information, FusionCharts est une librairie graphique qui permet de développer des graphiques à partir d’un fichier XML (lignes, histogrammes, cartes du monde, etc.).

Mise en place du projet

Pour faire simple, j’ai choisis de commencer une nouvelle application Java J2EE6 grâce au squelette de projet weld : org.jboss.weld.archetypes:weld-jsf-servlet-minimal. Je suis ensuite aller chercher les librairies tierces suivantes :

Développement

Mon but est de reproduire le premier exemple de graphique proposé sur la gallerie du site internet de FusionCharts :

Tout d’abord, il faut déposer la librairie Fiji 2.0 dans le répertoire src/main/webapp/WEB-INF/lib puis un graphique fusionChart (*.swf) dans un répertoire web du projet. Ensuite, deux fichiers sont nécessaires :

  • Un fichier XHTML pour générer le XML qui décrit le graphique
  • Un fichier XHTML pour  décrire la page JSF qui va intégrer le graphique

Voici le fichier XHTML qui va décrire le graphique :

<?xml version="1.0" encoding="UTF-8"?>

<f:view xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core" contentType="text/xml">

 <graph yAxisName='Sales Figure' caption='Top 5 Sales Person' numberPrefix='$'
    decimalPrecision='1' divlinedecimalPrecision='0' limitsdecimalPrecision='0'>
   <ui:repeat var="item" value="#{dynaGraphique.listPersonne}">
      <set name='#{item.name}' value='#{item.sales}' color='#{item.color}' />
   </ui:repeat>
 </graph>

</f:view>

On peut remarquer que j’utilise le tag <ui:repeat/> pour itérer sur une liste de données qui va représenter plusieurs séries sur mon histogramme. Ci-dessous, le fichier qui décrit le même graphique en static :

<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core" contentType="text/xml">

   <graph yAxisName='Sales Figure' caption='Top 5 Sales Person' numberPrefix='$'
      decimalPrecision='1' divlinedecimalPrecision='0' limitsdecimalPrecision='0'>
        <set name='Alex' value='25000' color='AFD8F8' />
        <set name='Mark' value='35000' color='F6BD0F' />
        <set name='David' value='42300' color='8BBA00' />
        <set name='Graham' value='35300' color='FF8E46' />
        <set name='John' value='31300' color='008E8E' />
   </graph>

</f:view>

Les deux classes java qui vont contenir les données pour le graphique. Vous allez retrouver les données précédentes dans la première classe :

@Model
public class DynaGraphique {
 private List<Personne> listPersonne = new ArrayList<Personne>();

 @PostConstruct
 public void initialize() {
   listPersonne.add(new Personne("Alex", 25000, "AFD8F8"));
   listPersonne.add(new Personne("Mark", 35000, "F6BD0F"));
   listPersonne.add(new Personne("David", 42300, "8BBA00"));
   listPersonne.add(new Personne("Graham", 35300, "FF8E46"));
   listPersonne.add(new Personne("John", 31300, "008E8E"));
 }
 // Getter et Setter

}
public class Personne {
 private String name;
 private int sales;
 private String color;

 public Personne() {
 }

 public Personne(String name, int sales, String color) {
 super();
 this.name = name;
 this.sales = sales;
 this.color = color;
 }
//Getter et Setter ...
...
}

Le fichier XHTML qui va générer la page JSF :

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:fiji="http://exadel.com/fiji"
   template="/WEB-INF/templates/default.xhtml"
   xmlns:a4j="http://richfaces.org/a4j">
      <ui:define name="content">
         <!-- static : voir le fichier fusionChart/fusion01.jsf -->
         <fiji:swf src="fusionChart/FCF_Column3D.swf" bgcolor="#FFFFFF" width="520" height="400">
            <f:param name="dataURL" value="fusionChart/fusion01.jsf" />
         </fiji:swf>
         <!-- dynamique -->
         <fiji:swf src="fusionChart/FCF_Column3D.swf" bgcolor="#FFFFFF" width="520" height="400">
            <f:param name="dataURL" value="fusionChart/fusion02.jsf" />
         </fiji:swf>
      </ui:define>
</ui:composition>

Pour information, il ne faut pas oublier de préciser les attributs bgcolor, width et height pour éviter une erreur d’exécution de Fiji.

Exécution du projet

Pour exécuter le projet, j’utilise la commande maven mvn compile tomcat:run. L’application est alors disponible à l’adresse : http://localhost:9090/jsf.servlet.minimal.

Vous pouvez checkouter le projet à l’adresse suivante : http://subversion.assembla.com/svn/everythingiswrong/tutorial-fiji-fusionchart/

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/

Ecrire un document XML avec Facelets

By , 05/06/2010

Générer un document XML à partir d’un application web Java est très simple. Il suffit d’écrire une servlet qui va écrire du XML sur la réponse HTTPResponse avec le bon type de contenu. Voici un exemple :

try {
 FacesContext ctx = FacesContext.getCurrentInstance();
 final HttpServletResponse resp = (HttpServletResponse)ctx.getExternalContext().getResponse();
 String xml = "<settings>...</settings>";
 resp.setContentType("text/xml");
 resp.setContentLength(xml.length());
 resp.getOutputStream().write(xml.getBytes());
 resp.getOutputStream().flush();
 resp.getOutputStream().close();
 ctx.responseComplete();

} catch (IOException e) {
 e.printStackTrace();
}

L’opération s’avère plus difficile lorsqu’il faut l’écrire à partir d’une page XHTML en utilisant Facelets. Voici une solution possible :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" contentType="text/xml">

<settings>...</settings>

</f:view>

La déclaration de la dtd HTML (deuxième et troisième lignes) n'est pas nécessaire sauf si vous utilisez des caractères latins ("é", "è", etc.) car facelets les traduit automatiquement en caractères HTML du style "&eacute;" et cela provoque l'erreur "Erreur d'analyse XML : entité non définie" sans ce fichier dtd.

OfficeFolders theme by Themocracy