Création d’une application de type CRUD avec JSF et JPA

Extrait du synopsis :

Cet article a pour objectif de vous présenter la tâche de création d’une application complète de type CRUD ( Create, Read, Update, Delete ) permettant d’effectuer les opérations de création, consultation, suppression et modification d’une entité et ce en utilisant le framework web JSF et le framework de persistance JPA .

L’article complet est par ici : Création d’une application de type CRUD avec JSF et JPA

JSF et Facelets

Extrait du synopsis :

Cet article a pour objectif de vous présenter la technologie de présentation Facelets ainsi que de vous guider dans les tâches de configuration et d’utilisation de cette technologie.

L’article complet est par ici : JSF et Facelets

Stratégie publicitaire agressive d’ICEfaces

ICEfaces, la boite derrière le jeu de composants JSF ICEfaces (innovant soit dit en passant) est en train de faire quelques mouvements agressifs ces derniers jours histoire de promouvoir leur produit mais aussi leur support commercial.

Dans mon cas, ça a commencé Lundi dernier (le 22) : j’ai reçu un mail de leur part comme quoi un compte en mon nom dans leur site a été crée … je me rappelle que j’avais crée un compte il y’a une année déjà pour pouvoir télécharger leur produit. ils ont utilisé la première partie de mon adresse email comme login et un mot de passe standard.

[Suite:]

Aujourd’hui, je viens de recevoir un second email comme quoi ils ont entendu que je travaillais sur un projet utilisant ICEfaces (wow ! moi même je le savais pas) et qu’ils voudraient me contacter (par téléphone) pour m’expliquer les avantages dont je disposerais si je m’abonne à leur programme de support commercial.

Je ne suis pas le seul, ça s’est sûr … et j’hésite sur comment je dois prendre cela :D je veux dire que c’est naturel qu’ils essaient de faire connaitre et adopter leurs produits … mais aussi agressivement ? me créer un compte à ma place ? Mais surtout (leur second mail) :

Hello Jawher,

I noticed that you are working on a project with ICEfaces

Edit:
En fait non, grâce à l’explication de lepack (un membre d’ICEfaces peut être ?), le fait qu’on m’ait automatiquement crée un compte dans le site d’ICEfaces est dû plutôt au fait que j’ai téléchargé la RefCard de JSF de Dzone. Or, dans la page de téléchargement, il est clairement signalé qu’en téléchargeant la chose, on serait automatiquement enrolé dans la communauté ICEfaces.

=> My bad ! J’aurais vraiment du lire plus attentivement les modalités ^^
Merci d’avoir répondu et de m’avoir rectifié !

—-

[Java] JSF 2.0 va inclure un ViewScope

Ryan Lubke a publié un (autre) billet sur son blog où il présente (encore) quelques nouveautés du futur JSF 2.0. Ce qui m’a vraiment intéressé cette fois-ci est l’introduction du view scope qui vient s’ajouter aux autrez scopes classiques (Session, Request, Application).

Basiquement, il s’agit d’un scope lié à une page, où une donnée qui y est stockée est gardé trant qu’on est sur une même vue, et est effacée dès qu’on navigue vers une autre vue.

[Suite:]

Ceux qui ont utilisé Tomahawk reconnaîtront le composant saveState qui présente une fonctionnalité simailaire.

L’introduction de ce nouveau scope est une excellente nouvelle car il serait vraiment utile (pensez aux listes alimentées depuis la base de données dans un managed bean par exemple, l’édition sur place, etc. ou on devait passer par le scope session (le marteau pour écraser la mouche)). Dommage que ça a pris 4 ou 5 ans à l’EG de JSF de s’en rendre compte :D

—-

Gestion des sessions expirées dans JSF (rebelote)

J’avais précédemment traité ce thème dans un autre billet, mais je dois avouer que la méthode que j’y avais présenté n’étatit pas vraiment solide ou fiable.

Donc, suite à quelques recherches et expérimentations, j’ai pu mettre en place un autre filtre beaucoup plus solide qui permet d’intercepter les erreurs de sessions expirées dans JSF (qui sont plus qu’abondants avec ce dernier :) ) pour afficher une page personnalisée au lieu de la mooche page d’erreur par défaut du serveur utilisé.

[Suite:]

En gros, voici une version simplifiée du filtre :

import java.io.IOException; 
 
 
 
import javax.servlet.Filter; 
 
import javax.servlet.FilterChain; 
 
import javax.servlet.FilterConfig; 
 
import javax.servlet.ServletException; 
 
import javax.servlet.ServletRequest; 
 
import javax.servlet.ServletResponse; 
 
import javax.servlet.http.HttpServletRequest; 
 
import javax.servlet.http.HttpServletResponse; 
 
 
 
import org.slf4j.Logger; 
 
import org.slf4j.LoggerFactory; 
 
public class TimeoutFilter implements Filter { 
  private static final Logger log = LoggerFactory 
      .getLogger("webapp.timeoutFilter"); 
 
  private static final String TIMOUT_PAGE = "timeout.html"; 
  private static final String LOGIN_PAGE = "login.faces";  
 
  public void init(FilterConfig filterConfig) throws ServletException { 
  } 
 
  public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain filterChain) throws IOException, ServletException { 
    if ((request instanceof HttpServletRequest) 
        && (response instanceof HttpServletResponse)) { 
      HttpServletRequest hRequest = (HttpServletRequest) request; 
      HttpServletResponse hResponse = (HttpServletResponse) response; 
 
      if (checkResource(hRequest)) { 
        String requestPath = hRequest.getRequestURI(); 
        if (checkSession(hRequest)) { 
            String timeoutUrl = hRequest.getContextPath() + "/" 
                + TIMOUT_PAGE; 
            log.info("Session is invalid! redirecting to timeoutpage : {}", 
                    TIMOUT_PAGE); 
 
            hResponse.sendRedirect(timeoutUrl); 
            return; 
        } 
 
 
    } 
    filterChain.doFilter(request, response); 
  } 
 
  private boolean checkResource(HttpServletRequest request) { 
    String requestPath = request.getRequestURI(); 
    log.debug("reqPath={}", requestPath); 
    return !(requestPath.contains(TIMOUT_PAGE) ||  
        requestPath.contains(LOGIN_PAGE) ||  
      requestPath.equals(hRequest.getContextPath() + "/")); 
 
  } 
 
  private boolean checkSession(HttpServletRequest request) { 
    return request.getRequestedSessionId() != null 
        && !request.isRequestedSessionIdValid(); 
 
  } 
 
  public void destroy() { 
  } 
 
} 

Quelques notes:

  • J’utilise SLF4J pour le logging
  • Je commence par vérifier s’il s’agit bien d’une requête HTTP
  • Si c’est le cas, je vérifies si la ressource demandée (request.getRequestURI()) est une ressource protégée via la méthode checkResource(). En fait, c’est à vous de décider quelle ressource protéger. Dans cet exemple, je suppose que toute page exceptée celle du timeout, du login et la racine est protégée.
  • Je vérifies ensuite l’état de la session en contrôlant que l’identifiant (jsessionid) est non null, et qu’il est valide
  • Si c’est pas bon, alors je redérige vers la page de timeout (via request.sendRedirect)

Toutefois, cette implémentation n’est pas encore parfaite, car il peut arriver des cas où la session est valide sans que l’utilisateur ne soit authentifié.

Pour résoudre ceci, j’ajoute un autre test (après le premier) qui récupère un bean session (un managed bean JSF en fait, mais managé par Spring) pour vérifier qu’il n’est pas null et qu’un champ particulier est renseigné :

if (hRequest.getSession(false) != null) { 
 
  final WebApplicationContext ac = WebApplicationContextUtils 
 
    .getWebApplicationContext(hRequest.getSession(false).getServletContext()); 
 
  if (ac == null) { 
 
    //redériger vers la page du timeout ... 
 
  } else { 
 
    LoginCtrl loginCtrl = (LoginCtrl) ac.getBean("loginCtrl"); 
 
    if (loginCtrl == null || !loginCtrl.isLoggedIn()) { 
 
    if (!(requestPath.contains(LOGIN_PAGE) || requestPath 
 
      .equals(hRequest.getContextPath() + "/"))) { 
 
      //redériger vers la page du timeout ...        
 
    } 
 
  } 
}

Il faut juste bien vérifer de passer false à getSession : ça m’a fait perdre quelques millions de neuronnes pour comprendre ce qui se passait car j’avais ajouté cette innoncente instruction :

 
log.debug(hRequest.getSession(true); 

erf …

Après, il est possible de peaufiner encore la chose, en ajoutant par exemple un test qui emêche un utilisateur déjà connecté de se reconnecter, i.e. d’accèder à la page de login, chose indispensable quand on bosse avec Spring par exemple, où une manipulation pareille ne recharche pas les beans en scope session …

—-

Sortie de Mojarra (JSF RI) 2.0 EDR

La première implémentation de référence du futur JSF 2.0 (Mojarra) vient de sortir en version EDR (Early Dravt Review).
Pour rappel, j’avais parlé de quelques nouveautés du futur JSF 2.0 dans ce billet.

[Suite:]

=> Annonce
=> Télécharger
=> Release Notes

Notez qu’Ed Burns (le spec Lead de JSF 2.0) a réalisé dans son blog un index de ressources parlant de JSF 2.0.
=> C’est par ici.

—-

[Java] Mojarra: Groovy pour PHPiéser le

Ryan Lubke vient d’annoncer dans son blog qu’à partir de cette nuit, les nightly build de la prochaine version de Mojarra (== Sun JSF RI) 1.2_09 inclueront une nouveauté de taille: un mode développement configurable dans web.xml via un context-param (comme celui de Wicket par exemple) qui permet d’utiliser Groovy pour ecrire les managed beans mais surtout de développer une application JSF en mode PHP-like, i.e. modifier ses classes/pages, et faire un F5 dans le navigateur pour voir le résultat … A dieu le malfamé et lourd cycle de développement inhérent à Java EE (redéploiement à chaque modification, voir même redémarrage du serveur)

[Suite:]

Pour ceux qui se plaigneront du fait qu’ils ne connaissent pas la sntaxe de groovy, la réponse est simple: il suffit d’ecrire en Java, ce qui est déjà du Groovy. D’ailleurs, il vaut mieux écrire son code Groovy en Java natif vu qu’à la fin du prototypage, et pour des performances optimales, il faudrait désactiver le mode développement et recoder les classes Groovy en Java.
=> Vous voyez où je veux parvenir: en y allant avec du Java natif, ceci reviendrait à un simple copier/coller ;)

Presque tout serait rechargeable à chaud, des managed beans jusqu’au renderers et listeners, en passant par les validators/converters et même les composants.

Autre point: il est fortement conseillé d’utiliser FAcelets comme technologie de présentation (y’en a déjà qui font du JSF avec JSP ???), car il n’y a pas de rechargement à chaud pour les TagHandlers du JSP ou encore des TLDs.

La mise en place de ceci se présente comme suit:

  1. Inclure groovy-1.5.5-all.jar dans son classpath
  2. Ajouter ceci à son web.xml:

    <context-param> 
        <param-name>com.sun.faces.developmentMode</param-name> 
        <param-value>true</param-value> 
    </context-param> 
    <filter> 
        <filter-name>GroovyFilter</filter-name> 
        <filter-class>com.sun.faces.scripting.GroovySupportFilter</filter-class> 
    </filter> 
    <filter-mapping> 
         <filter-name>GroovyFilter</filter-name> 
         <url-pattern>/*</url-pattern> 
         <dispatcher>REQUEST</dispatcher> 
         <dispatcher>FORWARD</dispatcher> 
         <dispatcher>INCLUDE</dispatcher> 
         <dispatcher>ERROR</dispatcher> 
    </filter-mapping>

    (En gros, un context-param et un filtre + son mapping)

  3. Créer un répertoire “groovy” dans WEB-INF dans lequel placer les fichiers .groovy.

Notez que lorsqu’on référence les beans Groovy dans faces-config, il faut ajouter l’extension .groovy au nom qualifié.

Notez enfin qu’il s’agit encore d’une fonctionnalité encore à son inception, et que c’est loin d’être solide/fiable.

—-

Follow

Get every new post delivered to your Inbox.