Posts tagged: Java

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/

Eclipse : Expressions régulières

By , 16/07/2013

Les expressions régulières sont très importantes lors qu’il s’agit de rechercher des informations dans du texte. Cependant, elles peuvent, dans certain, devenir très compliquées. C’est d’ailleurs la principale raison pour laquelle beaucoup de monde préfère utiliser autre chose pour rechercher des informations dans une chaîne de caractères, par exemple à l’aide de découpage arbitraire de cette même chaîne. En utilisant la fonction Java split par exemple.

Un plugin Eclipse offre la possibilité de vérifier en directe une expression régulière : myregexp. Ce plugin existe aussi en version en ligne ici.

JBoss 7 : Plusieurs instances standalone sur un même serveur

By , 13/06/2013

Pour démarrer une instance JBoss en mode standalone avec les configurations par défaut, il faut exécuter la commande suivante : $JBOSS_HOME/bin/standalone.sh

Pour créer sa propre instance, il est uniquement nécessaire de copier les fichiers de configuration originaux du serveur standalone dans un répertoire quelconque du système de fichier puis d’exécuter la commande précédente avec l’option -Djboss.server.base.dir=XX. Par exemple :

xxxx@xxxx:~/tmp/testsJboss1$ tree
.
├── configuration
│   ├── application-roles.properties
│   ├── application-users.properties
│   ├── logging.properties
│   ├── mgmt-users.properties
│   └── standalone.xml
└── deployments
xxxx@xxxx:~/$ $JBOSS_HOME/bin/standalone.sh -Djboss.server.base.dir=~/tmp/testsJboss1/

Remarque : L’option jboss.socket.binding.port-offset associée à un entier (-Djboss.socket.binding.port-offset=1), vous permet de démarrer une instance en décalant tous les ports du serveur et ainsi éviter toute interférence avec un autre serveur.

Tomcat + weld + JSF : java.lang.OutOfMemoryError: PermGen space

By , 01/06/2013

Après avoir démarré une application utilisant tomcat, weld-servet et JSF2, je me suis rendu compte que j’obtenais rapidement des erreurs de mémoire sur la PermGen space. En gros mon application, aussi petite soit elle, utilisait beaucoup plus de classes que ce que je pensais et surtout que ce que la JVM de Sun pouvait contenir par défaut.

Pour rappel, cette partie de la mémoire est utilisée dans les JVM de Sun pour stocker les classes chargées par le classloader, elle ne se vide jamais sauf si l’on fait des actions directement sur le classloader. La valeur par défaut de cette mémoire est de 64Mo.

A priori, cette valeur n’est pas assez grande pour contenir l’ensemble des classes chargées par weld-servlet et JSF2 dans un tomcat. Pour éviter de retrouver ces erreurs de mémoire, il faut donc l’augmenter avec le paramètre dans la JVM :

-XX:MaxPermSize=256m

Il est possible de voir l’évolution de cette mémoire avec le programme VisualVM qui est fourni par défaut dans une JDK.

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.

JSF Charts : graphiques avec JSF

By , 31/01/2013

Cela fait longtemps que je souhaite consacrer un article sur les graphiques en JSF. Après avoir essayé plusieurs solutions je n’ai été convaincu par aucune librairie. Il me semble que la plus intéressante est la solution proposée par PrimeFaces. Ce que je n’aime pas dans cette approche c’est d’utiliser les classes spécifiques de la librairie JSF pour décrire les séries et non des collections simples. De plus, je ne trouve pas les graphiques très dynamiques. En tout cas pas à la hauteur des librairies Javascripts ou Flex qui existent actuellement.

Deux librairies Javascipts me semblent très performantes d’un point de vue utilisateur et développeur :

  • amCharts :
    • graphiques dynamiques, diversifiés, professionnels
    • licence gratuite
  • Highchart :
    • graphiques dynamiques, diversifiés, professionnels
    • approche déclarative des graphiques
    • licence nécessaire selon le type d’utilisation

C’est l’approche déclarative des graphiques qui m’a convaincue de la fiabilité d’une librairie JSF basée sur Hightchart. On retrouve le même principe déclaratif dans les interfaces xhtml proposées par JSF. Je me suis donc lancé dans la création de cette librairie qui est un wrapper JSF de Highchart : jsfcharts. La demo ce trouve hébergée ici : http://showcase-jsfcharts.rhcloud.com/home.jsf.

Mon objectif : proposer une solution efficace à développer, agréable à utiliser et compatible avec plusieurs systèmes (PC, mobile, multi-navigateurs). C’est à dire :

  • Rapide : peu de lignes à coder
  • Simple :
    • objets simples sans préparation
    • Utilisation transparente de la librairie

Au final, créer un graphique dynamique en JSF est presque aussi simple que créer un tableau (h:dataTable). Par exemple, pour le graphique ci-dessous, il faut écrire ce fichier xhtml et cette classe java :

<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:jsfcharts="http://everythingiswrong.org/jsfcharts"
   template="/WEB-INF/templates/default.xhtml">
   <ui:define name="content">
       <jsfcharts:chart id="test" marginRight="130" marginBottom="25">
          <jsfcharts:title text="Monthly Average Temperature" />
          <jsfcharts:subtitle text="Source: WorldClimate.com" />
          <jsfcharts:xAxis categories="#{chartBean.abscisse}" />
          <jsfcharts:yAxis>
          <jsfcharts:title text="Temperature (˚C)" />
          </jsfcharts:yAxis>
          <jsfcharts:legend layout="vertical" align="right" verticalAlign="top" x="-10" y="100" borderWidth="0"/>
          <jsfcharts:tooltip valueSuffix="˚C" />
          <jsfcharts:series>
              <jsfcharts:serie label="Tokyo" value="#{chartBean.tokyo}" />
              <jsfcharts:serie label="New York" value="#{chartBean.newYork}" />
              <jsfcharts:serie label="Berlin" value="#{chartBean.berlin}" />
              <jsfcharts:serie label="London" value="#{chartBean.london}" />
          </jsfcharts:series>
       </jsfcharts:chart>
...
</ui:composition>
package org.everythingiswrong.jsf.jsfchartsdemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;

@Model
public class ChartBean {

   private Double[] tokyo;
   private Double[] newYork;
   private Double[] berlin;
   private Double[] london;
   private List<String> abscisse;

   // Getter, Setter  ...

   @PostConstruct
   public void initialize() {
      tokyo = new Double[] {7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6};
      newYork = new Double[] {-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5};
      berlin = new Double[] {-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0};
      london = new Double[] {3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8};
      abscisse = Arrays.asList(new String[] {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"});
   }
}

Pour aller plus loin, je vous invite à visiter le projet github de JSFCharts : https://github.com/yanLanglois/jsfcharts.

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

JRebel gratuit !

By , 24/04/2012

Cette information date déjà de quelques mois, mais je viens de la découvrir : il existe une version gratuite de JRebel (https://social.jrebel.com). Ce logiciel permet aux développeurs Java d’éviter les redéploiements à répétition de leurs applications grâce à un système de synchronisation du code développé et du code déployé.

Bien entendu, il existe des contraintes :

  • Disponible uniquement pour les développements non commerciaux (impossible à utiliser en entreprise par exemple)
  • Publication mensuelle de statistiques sur Tweeter ou/et facebook

Bean Spring et java.util.List

By , 25/01/2012

Voici deux façons de déclarer une liste d’objet en tant que propriété d’un bean Spring :

  • A partir d’une liste de valeur
<bean name="name" class="Class">
      <property name="myList">
            <value>a</value>
            <value>b</value>
            <value>c</value>
      </property>
</bean>
  • A partir d’une valeur unique à décomposer en plusieurs valeurs (sorte de CSV)
<bean id="name" class="Class">
    <property name="myList">
        <bean class="org.springframework.util.CollectionUtils" factory-method="arrayToList">
            <constructor-arg type="java.lang.Object">
                <bean class="org.springframework.util.StringUtils" factory-method="tokenizeToStringArray">
                    <constructor-arg type="java.lang.String" value="a b c"/>
                    <constructor-arg type="java.lang.String" value=" "/>
                </bean>
            </constructor-arg>
        </bean>
    </property>
</bean>

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.

OfficeFolders theme by Themocracy