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

SvnMapper

By , 01/12/2010

Il y a quelques mois, j’ai découvert un outil très intéressant pour les développeurs qui travaillent avec Subversion : SvnMapper.

Il affiche l’historique d’un projet subversion sous la forme d’un graphique où il est possible de déplacer les branches, de voir les commits, de s’interface avec TortoiseSvn pour visualiser les différence sur un commit, etc.

Avec toutes ses fonctionnalités plus ou moins avancées, je pense que SvnMapper permet un audit approfondi de la gestion de contrôle en soulignant les tags, les branches et surtout les merges. Qui n’a jamais oublié de faire un merge pour reporter des corrections d’une version à une autre ?

Remarque : pour afficher l’historique d’un projet, il faut donner l’adresse de sa branche principale : le trunk.

m2eclipse : SCM extra inexistant

By , 29/11/2010

En utilisant la nouvelle version du plugin Eclipse m2eclipse, je me suis rendu compte que l’extension SCM n’existait plus. Ou bien n’est pas encore développée dans la version actuelle (0.12). Voici comment faire pour créer manuellement tous les projets Eclipse correspondants aux sous-module d’un projet multimodule :

  1. Récupérer le projet père du SCM (Check out simple)
  2. Importer les projets maven existant : File -> Import… -> Existing Maven projects
  3. Sélectionner les modules qui vont faire l’objet d’un projet dans Eclipse

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.

JadClipse

By , 11/10/2010

Il est souvent très utile de naviguer dans les classes java provenant des librairies tierces pour comprendre leur fonctionnement. Hélas, les sources des librairies ne sont pas toujours publiées ou disponibles dans la bonne version. Il y a quelque années, j’utilisais Jad pour dé-compiler ces classes. Je viens de découvrir qu’il existe un plugin d’intégration Eclipse pour Jad : jadClipse.

Comme il s’agit d’un plugin d’intégration, vous devez installer au préalable Jad sur votre système. C’est un petit exécutable que vous pouvez déposer n’importe où. Puis il faut installer le plugin dans votre IDE : l’URL d’update est http://jadclipse.sf.net/update. Après l’installation, il faut uniquement configurer le plugin pour qu’il sache retrouver l’exécutable Jad : dans le menu “Windows -> Préférence…” le panneau de configuration se trouve dans le menu “Java -> Decompiler -> Jad”

Traitements longs et batchs sur un serveur d’application Java

By , 09/10/2010

La question posée dans ce article est de savoir s’il est opportun d’utiliser JavaJ2EE et donc un serveur d’application pour des traitements longs. Je pense notamment à des traitements batch ou à des traitements lourds provoqués par une demande d’un utilisateur sur une page web. Pour répondre à cette question il faut comprendre le fonctionnement d’un serveur d’application.

Principe de fonctionnement

Lorsqu’un serveur d’application reçoit à une demande cliente (HTTP, RMI, etc.), il utilise une thread pour y répondre puis la libère à la fin du traitement. Vous pouvez vérifier ce comportement avec une requête HTTP ou bien un MBean. Pour visualiser les threads dans les log il faut paramétrer le PatternLayout Log4J avec %t. Lorsque toutes les threads sont occupées, le serveur ne peut plus répondre aux demandes clientes.

Pour information, sur un serveur d’application, le nombre de thread est limité mais configurable. Par exemple, le nombre maximum de threads sur JBoss est de 100 par défaut.

Traitements longs

Dans un serveur d’application, certaines ressources ont une durée de vie ou d’activité limitée. Par exemple, une transaction sur une base de données ne peut pas excéder 5 minutes par défaut sur une serveur JBoss sous peine de provoquer l’exception suivante :

Transaction is not active: tx=TransactionImple < ac, BasicAction: -3f57f10b:911:49fb4a4b:3e status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: -3f57f10b:911:49fb4a4b:3e status: ActionStatus.ABORT_ONLY >)

La seule solution est de découper son traitement en plusieurs traitements plus petit ou de modifier le timeout. Dans ce dernier cas, il faut faire attention car un timeout top grand peut avoir des effets néfastes sur les performances de l’application. Voici comment gérer les démarcations de transaction pour découper un traitement long en plusieurs petits traitements :

Client (sans transaction) -> EJB (transaction supportée : TransactionAttributeType.SUPPORTS) -> EJBs (nouvelle transaction pour chaque appel EJB : TransactionAttributeType.REQUIRED ou TransactionAttributeType.REQUIRES_NEW)

Dissociation entre le web et les traitements lourds

Après avoir vu le principe de fonctionnement d’un serveur d’application et comment développer un traitement long sans provoquer d’exception de timeout, il ne faut pas oublier qu’une application web peut être utilisée par un grand nombre d’utilisateurs. Si les requêtes HTTP provoquent des traitements longs cela peut rapidement provoquer une indisponibilité du serveur.

Une des solutions possibles est d’utiliser deux serveurs d’applications différents : un serveur d’application pour les traitements lourds et un pour l’IHM. Les échanges entre ces deux serveurs doivent se faire en asynchrone pour ne pas pénaliser la partie web de l’application. Ainsi une augmentation du nombre d’utilisateur n’impactera pas votre application, à moins de mal configurer le serveur s’occupant de l’IHM.

Au final, tout n’est qu’une question de paramétrage des serveurs. Il ne faut pas oublier qu’avec un serveur d’application le clustering est toujours possible, et dans ce cas, le nombre de threads disponibles pour traiter les demandes augment lui aussi.

Vous pouvez utiliser le serveur d’application pour exécuter seulement des batchs. il faut alors vous assurer que le nombre de threads disponibles sur le serveur soit assez grand et que vos traitements successifs n’engendrent pas de problèmes de mémoire ou de réservation de ressources, car votre serveur ne sera pas réinitialisé au début de chaque traitement.

Cas du conteneur embarqué

Si vous préférez avoir une JVM par traitement et donc une architecture plus proche d’un batch classique, des conteneurs embarqués sont désormais disponibles et ils fonctionnent très bien. J’ai déjà testé openEJB et JBossEmbedded, glassfish, etc. je n’ai jamais remarqué de problème sur leur utilisation. De plus, dans ce cas, comme il y a une JVM non partagée par traitement, les problèmes de disponibilités lié à l’utilisation de thread n’existe plus. J’ajouterai que l’utilisation d’un conteneur embarqué est très simple, voici un exemple avec openEJB :

Créer un project maven avec l’archetype quickstart et ajouter openEJB dans les dépendances. Voici l’allure du fichier POM :

    <dependencies>
        <dependency>
            <groupId>org.apache.openejb</groupId>
            <artifactId>openejb-core</artifactId>
            <version>3.1.2</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.apache.activemq</groupId>
                        <artifactId>activeio-core</artifactId>
                    </exclusion>
                </exclusions>
        </dependency>
    </dependencies>

L’exclusion d’activeMq est nécessaire car l’artefact n’existe pas sur le repository maven. L’étape suivante est de rajouter deux fichiers de configuration : jndi.properties avec la ligne

java.naming.factory.initial = org.apache.openejb.client.LocalInitialContextFactory

et un fichier “vide” META-INF/ejb-jar.xml qui ne contient que la ligne :

<ejb-jar/>

Ce fichier XML vide indique au conteneur de rechercher les EJBs présents dans le classpath. Le serveur embarqué se démarre et déploie les  services EJB tout seul et vous n’avez plus qu’a les appeler :

    public class App {
       public static void main( String[] args ) {
          try {
             Context context = new InitialContext();
             HelloWorldService helloWorldService =
                (HelloWorldService) context.lookup("HelloWorldServiceHandlerLocal");
             System.out.println(helloWorldService.sayHello("Smith"));
          } catch (NamingException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
          }
    }
}

Pour plus de précisions, voici l’URL où vous pouvez retrouver mon exemple : https://subversion.assembla.com/svn/everythingiswrong/tutorial-embedded-openejb/

Conclusion

Pour conclure cet article, je dirais qu’utiliser un serveur d’application pour ses batchs ou traitements longs est très intéressant car cela vous permet de disposer de la stack Java J2EE. Cela peut  éventuellement vous permettre de mutualiser du code entre traitement batch et IHM, si vous avez une application qui nécessite les deux. Si l’utilisation d’un “vrai” serveur d’application vous fait peur, il est toujours possible d’utiliser un conteneur embarqué pour bénéficier, là aussi, de la stack logiciel fournie par Java J2EE.

Les traitements longs sur les serveurs d’applications J2EE ne sont donc qu’une question de paramétrage. Ils ne sont pas à proscrire, surtout si vous utilisez un conteneur embarqué.

Pour ceux qui ne sont toujours pas convaincus, voici 4 articles intéressants sur les batchs J2EE et le multithreading dans un serveur J2EE :

Eclipse IDE : Materialize Maven Projects

By , 06/10/2010

J’utilise le plugin Eclipse m2eclipse pour développer mes applications avec Maven. Lors que l’on travaille sur des projets complexes avec plusieurs sous modules, il faut absolument dissocier les modules en projets Eclipse dissociés pour que les classpaths soient bien respectés. C’est pour cela que je me suis souvent demandé comment transformer un projet Maven multi-modules en plusieurs petits projets Maven dans Eclipse. Jusqu’à maintenant, je me suis débrouillé en utilisant la fonctionnalité “Check out as Maven projet…” (extention SVN du plugin m2eclipse), mais cela implique qu’il faille utiliser un projet enregistré sur un serveur de gestion de configuration. Voici comment faire dans le cas sans gestion de configuration :

Créer son projet multi-module

Avec le wizard de création de projet : File -> New -> Project…, créer un nouveau projet Maven puis cocher la case “Create simple project (skip archetype selection)” puis remplir le formulaire suivant :

création basic d'un projet maven de type pom

Le fichier pom.xml doit être généré de la sorte :

<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>com.mycompany.app</groupId>
  <version>0.0.1-SNAPSHOT</version>
  <artifactId>app-root</artifactId>
  <packaging>pom</packaging>
</project>

Pour construire un ou plusieurs sous module, il faut ouvrir le pom.xml avec l’éditeur pour de fichier POM et cliquer sur l’icone “New module project”. Cette fonctionnalité existe aussi à partir du menu contextuel de la vue “Project explorer”. Voici ce que nous avons pour l’instant :

Matérialiser ses projets Maven

Pour cela il faut importer le sous module comme un nouveau projet : File -> Import... Sélectionner ensuite “Materialize Maven Project”, enfin sélectionner le projet que nous avons créer ci dessus dans la boite de dialogue suivante. Voici le résultat dans eclipse :

Après cette opération vous avez bien tous les sous modules sous la forme de projet Eclipse dissociés.

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.

Seam : Exporter une dataTable à l’interieure d’une subview

By , 30/09/2010

Lorsqu’un développeur utilise Seam, il a à sa disposition tout un panel de composant pour l’aider à développer. Par exemple le composant dataTable Exporter permet d’exporter un tableau JSF (h:dataTable, rih:dataTable, etc.) sous la forme d’un fichier Excel. Voici la syntaxe directement récupérée de la documentation de référence de Seam :

<h:form id="theForm">
    <h:dataTable id="theDataTable" value="#{personList.personList}"
        var="person">
         ...
    </h:dataTable>
</h:form>
...
<h:commandLink
    value="Export"
    action="#{excelExporter.export('theForm:theDataTable')}" />

Lorsque la table se trouve dans une sous vue (<f:subview/>) ou tout autre composant qui joue un rôle de conteneur de nom (NamingContainer), il faut que le paramètre de la méthode d’export soit sous la forme idNamingContainer1:idNamingContainer2:…:…:idDataTable. De cette manière, la table est identifiée de façon unique dans la RootView.

OfficeFolders theme by Themocracy