Posts tagged: JSF

Primefaces : releases non-officielles

By , 24/06/2013

Primefaces n’est pas sous github. Malgré tout, un projet du même nom existe sur cet hébergement. C’est à partir de ce projet, copie du SVN officiel de Primefaces qu’il est possible de récupérer des releases non officielles, c’est à dire intermédiaires, de la librairie JSF. Ces versions sont, en effet, accessibles en version compilées uniquement pour les personne ayant un compte ELITE auprès de l’entreprise éditrice de Primefaces.

Pour en profiter, il faut ajouter le repository suivant dans maven :

<repository>
  <id>prime-github-repo</id>
  <name>Unofficial PrimeFaces Maven Repository</name>
  <url>http://primefaces.github.io/repository</url>
  <layout>default</layout>
</repository>

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.

PrimeFaces 3.5 incompatible avec RichFaces 4

By , 10/02/2013

Aujourd’hui, je décide de mettre à jour ma version de PrimeFaces. Je passe de la 3.4.2 à la 3.5. Résultat, mes composants RichFaces ne s’affichent plus correctement. Après recherche dans le code HTML généré, je remarque que les inclusions CSS et Javascript de Richfaces ne sont plus là. Je ne suis pas le seul à avoir le problème : http://forum.primefaces.org/viewtopic.php?f=3&t=28398.

Le problème vient de la façon dont PrimeFaces inclue les dépendances CSS et Javascript.

La solution : retour en version 3.4.2 en attendant une version intégrant une correction.

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.

JSF : générer un fichier à partir d’un managed bean

By , 18/05/2011

Dans cet exemple, je vais générer un fichier Excel à partir d’un managed bean.

L’idée de base est de récupérer le context de la servlet pour créer une réponse et rediriger l’utilisateur vers cette dernière. Voici à quoi ressemble mon bean :

@Model
public class MonBean {

	public String execute() throws IOException {
		// Création du fichier excel :
		String fileName = "azerty.xls";
		HSSFWorkbook wb = new HSSFWorkbook();
		HSSFSheet sheet = wb.createSheet(fileName);
		HSSFHeader header = sheet.getHeader();
		header.setCenter(fileName);

		// Récupération de la réponse HTTP
		ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
		HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-disposition", "attachment; filename="+ fileName);

		// Ecriture de la réponse
		ServletOutputStream out = response.getOutputStream();
		wb.write(out);
		out.close();

		FacesContext.getCurrentInstance().responseComplete();

		return null;
	}
}

Ensuite, il suffit de demander la méthode execute() du bean.

<h:form>
        <h:commandButton action="#{monBean.execute}" value="download" />
</h:form>

Vous pouvez trouver le code source de cet exemple ici. Pour exécuter l’exemple il faut lancer la commande mvn compile tomcat:run et se diriger vers l’adresse http://localhost:9090/home.jsf

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/

Eclipse Helios : UTF-8 pour Facelet

By , 03/12/2010

En changeant de version d’Eclipse, je me suis rendu compte que mes fichiers facelet (xhtml) avaient l’encoding UTF-8 par défaut. Le problème c’est que sur mon ancienne installation d’Eclipse ces mêmes fichiers étaient en CP1252 (encoding par défaut sous Windows). C’est dans un forum que j’ai compris que WTP associe automatiquement et systématiquement l’encoding UTF-8 aux fichiers facelet. Pour modifier l’encoding de ces fichiers :

  1. Window -> Preferences
  2. General -> Content Types
  3. Associer CP1252 aux types : Text -> HTML -> Facelet et Text -> HTML -> Facelet -> Facelet Composite Component

Richfaces et Ajax

By , 03/11/2010

Sur une interface web faisant des appels AJAX, il est parfois très complexe de comprendre ce qu’il se passe lors des saisies utilisateurs et des multiples rafraichissements. Les développeurs  qui utilisent Richfaces ont à leur disposition un composent JSF plus qu’intéressant depuis la version 3.0.0 : <a4j:log/>. Il affiche tout simplement les échanges entre le client et le serveur dans la page HTML résultat. Voici une possibilité d’utilisation :

<4j:log level="ALL" popup="false" width="400" height="200" />

En utilisant ce “logger”, j’ai remarqué qu’il était souvent nécessaire d’utiliser une queue AJAX dans les interfaces utilisant massivement cette technologie. Là encore, Richfaces propose un composant clé en main pour implémenter cette queue : <a4j:queue/>.

Vous pouvez retrouver ces composants dans le showroom de Richfaces : <a4j:log/> et <a4j:queue/>.

JSF : Unicode Encoding

By , 13/10/2010

Par défaut, l’implémentation de référence de JSF (Mojarra 1.2) convertit tous les caractères non ASCII en entités HTML. Cela peut provoquer des problèmes d’encoding. Il est possible de modifier ce comportement en ajoutant le paramètre com.sun.faces.disableUnicodeEscaping dans le fichier web.xml avec l’une de ces valeurs :

  • true : aucun caractère ne sera transformé
  • false : tous les caractères non ASCII seront encodés en entités HTML quelque soit l’encoding de la réponse (c’est le comportement par défaut)
  • auto : suivant le type d’encoding de la réponse :
    • UTF : pas d’encoding effectué
    • ISO-8859-1 : les caractères sont transformés en entité HTML

Voici comment cela se traduit dans le fichier web.xml :

<context-param>
    <param-name>com.sun.faces.disableUnicodeEscaping</param-name>
    <param-value>true<param-value>
</context-param>

De mon coté, je n’ai jamais eu de problème avec le mode par défaut à l’exception d’un développement qui utilisait Fiji et amChart car amChart n’affiche pas les entités HTML en caractères latins.

c:forEach (java.lang.OutOfMemoryError: Java heap space)

By , 04/10/2010

Il m’ait arrivé récemment d’avoir une erreur de mémoire sur une page xhtml alors que les autres interfaces de mon application fonctionnaient correctement. L’erreur provenait de mon tag <c:forEach/>. Voici la boucle provoquant le problème de mémoire :


<c:forEach value="#{myList}">
   ...
</c:forEach>

En réalité, j’avais transformé une boucle <ui:repeat/> en <c:forEach/> sans modifier le nom de l’attribut correspondant au bean sur lequel il faut faire l’itération : value pour <ui:repeat/> et items pour <c:forEach/>. Voici les deux bonnes syntaxes :


<ui:repeat value="#{myList}">
   ...
</ui:repeat>

<c:forEach items="#{myList}">
   ...
</c:forEach>

Je ne suis visiblement pas le seul à avoir eu ce problème, si vous voulez avoir plus d’information sur la cause exacte de cette exception voici comment j’ai trouvé la solution : http://wiki.foochal.org/index.php/ForEachHandler_OutOfMemoryError.

OfficeFolders theme by Themocracy