Le Touilleur ExpressLe Touilleur ExpressLe Touilleur ExpressLe Touilleur Express
  • Accueil
  • A propos de l’auteur
  • A propos du Touilleur Express

JBoss Tohu et GateIn : construire des formulaires dynamiques

    Home Java JBoss Tohu et GateIn : construire des formulaires dynamiques

    JBoss Tohu et GateIn : construire des formulaires dynamiques

    Par Nicolas Martignole | Java | 4 commentaires | 24 février, 2010 | 0 | 4 175 affichages
         

    GateIn

    L’actualité eXo Platform

    GateIn est un moteur dont je vous ai déjà parlé l’an dernier (ici et surtout là), et qui revient sur le devant de la scène. Avec une sortie finale prévue début mars, l’année 2010 sera eXo Platform ou ne sera pas. En octobre dernier, Sacha Labourey que vous avez vu à l’anniversaire du Paris JUG, ancien directeur général de JBoss Europe a rejoint le board. C’est aussi Edwin Khodabakchian, précédemment vice-président du développement produits d’Oracle, et Bob Bickel, co-fondateur de Bluestone Software qui eux aussi s’associent à Benjamin Mestrallet.

    Il y aura très certainement encore quelques visages connus de la communauté Java dans les semaines qui viennent. Bob Bickel sur Twitter le 21 février dernier lâche un énigmatique message :

    Exo just added another key person to join the team. Another couple me weeks before we announce though.

    JBoss Tohu

    A la recherche de nouvelles idées pour tester GateIn, j’ai travaillé sur un prototype avec JBoss Tohu et GateIn CR1. En quelques mots, JBoss Tohu est un moteur de génération de questionnaires basés sur Drools. Il permet de proposer des questionnaires dont la liste est déterminée par les réponses des utilisateurs aux réponses précédentes. C’est avant tout un moteur orienté Web, qui permet de créer des interfaces de saisies avec peu de lignes de code. Capable de s’intégrer avec Seam, JSF ou Spring MVC, c’est un moteur simple qui permet de gagner du temps.

    Dans la démonstration que je vous ai préparé, vous verrez comment je génère une nouvelle version du formulaire en éditant simplement le fichier Drools de définition du questionnaire.

    En terme de performances, c’est un peu poussif. J’ai dû aussi adapter les paramètres de mémoire de GateIn car Drools+Tomcat n’aime pas spécialement le redéploiement à chaud. Mais à part cela, c’est très facile comme nous allons le voir.

    GateIn CR1

    La dernière version de GateIn supporte 15 langues, l’intégration du moteur JCR 1.12.0-Beta06, un grand nombre de corrections et d’améliorations. En terme de performances, j’ai testé la version Tomcat et il y a une amélioration sensible du temps de démarrage et des performances. Je n’ai eu qu’à relancer une version du mois d’octobre pour voir la différence.

    Rappelons que GateIn est un moteur d’applications, un socle applicatif Web. Ce n’est pas uniquement un Portail, c’est un socle technique qui permet de passer la seconde. Prenez un serveur comme Tomcat, auquel vous êtes habitué. Il vous donne un certain nombre de fonctionnalités, comme la gestion des connexions avec une base, de quoi l’administrer facilement et de gérer le clustering par exemple. GateIn est une porte d’entrée vers le Web 4.0 avec un moteur d’exécution capable certes de faire tourner une webapp, mais aussi de proposer un moteur événementiel du côté navigateur, un serveur de Google Gadget, un JCR, un système de gestion des autorisations et de l’authentification, un moteur de template basé sur Groovy, bref un nombre de fonctionnalités intéressant pour qui développe des applications de nouvelles générations.
    Ce sera un socle sur lequel il est prévu d’intégrer et de faire collaborer des applications que l’on connaît comme Alfresco, Bonita ou Nuxeo. L’une des cibles est Microsoft SharePoint. La suite logicielle de Microsoft dispose d’un moteur de recherche, d’une gestion documentaire, de forums et de la possibilité de créer des formulaires dynamiques.

    Et c’est exactement ce que je vais faire avec JBoss Tohu : créer un formulaire dynamique et capturer les réponses de l’utilisateur pour générer un PDF.

    Vidéo de l’application

    J’ai mis en ligne sur YouTube une vidéo du projet complet. Après avoir lancé GateIn, je charge une page sur laquelle j’ai déclaré en quelques lignes un formulaire. Notez que le formulaire s’adapte dynamiquement selon les réponses sélectionnées par l’utilisateur. Lorsque je clique sur « Done » une Servlet génère un fichier PDF avec iText, votre certificat de meilleur Framework Web.

    Le code de la page principale de la Portlet est très simple. J’ai simplement adapté le chargement des ressources comme jQuery à GateIn, mais pour le reste, l’essentiel du travail est effectué par JBoss Tohu. Au chargement de la page, jQuery récupère via une Servlet spéciale la liste des questions, et construit à la volée la page. A chaque fois que le visiteur rempli une valeur, une règle Drools est évaluée. Il est alors possible de déclencher l’affichage de nouvelles zones automatiquement selon les réponses données par l’utilisateur. Imaginez ce système appliqué au monde de l’assurance ou de la finance, pour générer des contrats à la volée par exemple.

    <%@ page import="java.util.List" %>
    <%@ page import="javax.portlet.Portlet" %>
    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
    <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
    
    
    <portlet:defineObjects/>
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/ui.base.css" />
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/ui.core.css" />
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/ui.theme.css" />
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/ui.datepicker.css" />
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/jquery.readonly.css" />
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/ui.core.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/ui.datepicker.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/cookie.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/sprintf.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/toxml.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/jquery.readonly.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/jquery/jquery.url.packed.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_messages.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_utility.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_ajax.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_objects.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_interface.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_html.js"></script>
    <script type="text/javascript" src="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/script/dynamicUI_main.js"></script>
    
    <link rel="stylesheet" type="text/css" media="screen, projection" href="<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/css/style.css" />
    
    
    
    <script type="text/javascript">
    $(document).ready(function() {
        setDroolsURL("<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/stateful/simple");
        setActionURL("<%=renderResponse.encodeURL(renderRequest.getContextPath())%>/action/");
      onQuestionnaireLoad("bodyContent", "simple");
    });
    </script>
    
    <div id="content">
    
    <div id="bodyContent"> <p class="preLabel">Fill-in the form and click on "Done" to generate your certificate as PDF.</p></div>
    
    </div>
    <div class="copyright">
    Copyright(c) 2010 Nicolas Martignole - GateIn and JBoss Tohu</div>
    
    

    Le nom du formulaire à appeler est spécifé dans la fonction jQuery onQuestionnaireLoad. Il serait facile de prévoir une Portlet GateIn générique et de spécifier cette valeur comme propriété de la Portlet par exemple.

    Le fichier Drools

    Le script Drools est éditable bien entendu avec les outils graphiques de Drools. Vous allez voir qu’il est simple de construire un enchaînement de questions dynamiques.

    package com.innoteria.docxang
    
    import java.util.Calendar;
    
    import org.tohu.Group;
    import org.tohu.Question;
    import org.tohu.Questionnaire;
    import org.tohu.MultipleChoiceQuestion;
    import org.tohu.MultipleChoiceQuestion.PossibleAnswer;
    import org.tohu.Note;
    
    /*
     * Defines the questionnaire and initial questions which always appear.
     * Note that this rule has no when clause so it fires once when the session is first created.
     */
    rule "static"
    dialect "mvel"
    then
    	Questionnaire questionnaire = new Questionnaire("myQuestionnaire");
    	questionnaire.setLabel("GateIn and JBoss Tohu Sample");
    	// items (inherited from Group) determines the order in which things are displayed
    	questionnaire.setItems({"name", "hello", "webFrameworkType", "otherWebFrameworkType", "description"});
     	// completionAction specifies what to do when the user completes the questionnaire (i.e. clicks the Done button).
     	// The JQuery client interprets this as uri but other clients could use it in other ways.
    	questionnaire.setCompletionAction("generatedCertificate.pdf");
    	insertLogical(questionnaire);
    
    	Question question = new Question("name");
    	question.setAnswerType(Question.TYPE_TEXT);
    	question.setPreLabel("What's your name?");
    	insertLogical(question);
    
    	MultipleChoiceQuestion multi = new MultipleChoiceQuestion("webFrameworkType");
    	multi.setAnswerType(Question.TYPE_TEXT);
    	multi.setPreLabel("What type of Web Framework do you like?");
    	multi.setPossibleAnswers({
    		new PossibleAnswer(null, "None"),
    		new PossibleAnswer("wicket", "Apache Wicket"),
    		new PossibleAnswer("tapestry", "Apache Tapestry"),
    		new PossibleAnswer("jsf", "Java Server Faces"),
    		new PossibleAnswer("seam", "Seam"),
    		new PossibleAnswer("other", "Other")
    	});
    	insertLogical(multi);
    end
    
    /*
     * If the user provides their name then we create a new note called hello.
     * If they blank out their name then the note will disappear again automatically because of truth-maintenance.
     */
    rule "hello"
    when
    	Question(id == "name", answered == true);
    then
    	Note note = new Note("hello");
    	insertLogical(note);
    end
    
    /*
     * The actual text for the hello note is in a separate rule because we need it to fire whenever the name is changed,
     * not just when we create the note (which only fires when the name is first specified).
     */
    rule "hello data"
    no-loop
    when
    	Question(id == "name", name : answer);
    	hello : Note(id == "hello");
    then
    	hello.setLabel("Hello " + name + "!");
    	update(hello);
    end
    
    /*
     * This dependent question only appears for a specific data value. i.e. webFramework type is Other.
     * It will disappear automatically via truth-maintenance.
     */
    rule "other type of web framework"
    when
    	Question(id == "webFrameworkType", answer == "other");
    then
    	Question question = new Question("otherWebFrameworkType");
    	question.setAnswerType(Question.TYPE_TEXT);
    	question.setPreLabel("Please specify wich Web Framework:");
    	insertLogical(question);
    end
    
    /*
     * This dependent question appears whenever the original question is non-null.
     * It will disappear automatically via truth-maintenance.
     */
    rule "webframework's name"
    when
    	Question(id == "webFrameworkType", answered == "true");
    then
    	Question question = new Question("description");
    	question.setAnswerType(Question.TYPE_TEXT);
    	question.setPreLabel("Can you explain why it's your favorite framework?");
    	insertLogical(question);
    end
    

    J’ai copié le fichier complet, ce qui est un peu verbeux mais qui vous permet de comprendre comment fonctionne JBoss Tohu. A partir de ces règles Drools, Tohu est capable de générer une structure XML qui représente le Questionnaire et les Questions. jQuery charge dans le navigateur les questions, et retourne à une Servlet de Tohu les réponses. Lorsque l’utilisateur soumet le formulaire, vous recevez simplement une Map clé/valeur. A vous ensuite d’en faire ce que vous voulez. J’ai adapté l’un des exemples de Tohu qui génère un fichier PDF avec iText.

    Conclusion

    L’intéret de GateIn est de mettre en place rapidement une application avancée, avec déjà de l’authentification et la gestion du cycle de vie de l’application. L’idée pour aller plus loin et vraiment « faire du GateIn » est la suivante : générer un PDF, le stocker dans le JCR et le rendre accessible via CMIS. En effet, les équipes d’eXo Platform ont annoncé la disponibilité d’un connecteur CMIS sous la forme d’un projet LGPL, xCMIS.

    Enfin ne loupez pas le blog de Jérémi Joslin, ancien responsable produit de la partie eXo Social, qui poste des billets très intéressants sur GateIn.

    Ressources
    La page JBoss Tohu
    La page GateIn.org
    Une vidéo YouTube d’exemple de JBoss Tohu

    Articles similaires:

    Default ThumbnailPrésentation de GateIn beta 2 et eXo Portal mardi 27 octobre Default ThumbnailGateIn : premiers pas Default ThumbnailComment configurer l'encoding en UTF-8 dans JBoss Default ThumbnailConstruire une application d'entreprise nouvelle génération avec AJAX en utilisant echo2, EJB et ServiceMix ESB
    gatein
    • Avatar
      zepouet 24 février 2010 at 12 h 31 min

      Excellente plus value de GateIn !

    • Avatar
      Christian 24 février 2010 at 17 h 18 min

      Intellectuellement, tout cela est séduisant.
      Mais ca fait quand même beaucoup penser à une grosse usine à gaz que l’on pourrait aisément remplacer par qq lignes de rails ou php.
      Je suis le seul à qui ça fait cet effet ?

    • Avatar
      Florent Ramière 24 février 2010 at 18 h 48 min

      @Christian
      J’ai eu la même impression que toi.
      En fait, dès que l’on dégaine un moteur de règles pour faire quoi que ce soit c’est que l’on a un besoin *réellement* non trivial.
      Dans ce cas, ce n’est pas le langage qui va permettre de t’aider au mieux pour implémenter ton besoin, mais bien le moteur de règle.
      Ensuite, comme d’habitude, c’est coton pour tester.

      Nicolas, tu aurais des pointeurs sur des use case adaptés a cet outil ?

    • Avatar
      Nicolas Martignole 24 février 2010 at 21 h 25 min

      @Florent : oui j’ai un cas d’usage en tête : générer des interfaces de saisie dynamiquement pour ensuite éditer des documents contractuels comme des Contrats ou des Devis. Le moteur de règle permet ici de gérer la combinatoire, d’extraire l’intelligence du coeur du produit. Je reconnais le côté « Usine à Gaz ». Je sors de l’habituelle application de gestion, que j’aurai habillé avec du Grails ou autre, pour aller chercher des sujets un peu plus touchy.
      En fait peu importe de savoir si cela va servir ou non. L’important est de montrer qu’en quelques heures, il a été possible de créer une application qui sort de l’habituel « Hello World », grâce à ces outils.

    Recent Posts

    • GitHub Actions : le tueur de Jenkins ?

      Avouez-le : ce titre de blog est super racoleur. J’avais aussi pensé

      15 février, 2021
    • Comment recréer du lien social dans l’Entreprise avec des outils numériques en 2021

      Nous sommes en février 2021 pendant le 3ème confinement lié à la

      10 février, 2021
    • FizzBuzz en Java et Scala (surtout Scala)

      L’exercice FizzBuzz est un petit exercice très simple, à tester par exemple

      9 février, 2021

    Recent Tweets

    • RT  @JosePaumard : Il y a tout juste un an j'ouvrais ma chaîne de cours Java en ligne (près de 80h de cours), c'était la fermeture des univer…

      3 hours ago
    •  @ShirleyAlmCh  Ça fait du bien de te lire

      4 hours ago
    • RT  @kimchy : great read from  @ldoguin  on putting customers first to the benefit of all by cloud vendors, wonderful to see it embraced by  @cl …

      13 hours ago
    •  @juliendubois   @alexismp  Interesting. However I tweet mostly in French so how accurate is this graph ?

      1 day ago
    • Et hop, voici la future liste des talks 2021 https://t.co/kQPehA8uzx avec encore quelques ajustements à faire (masq… https://t.co/mIDLEw0sML

      1 day ago

    Mots clés

    agile (18) ajax (11) Apple (11) architecture (6) barcamp (5) BarCampJavaParis (5) ddd (5) devoxx (33) esb (6) exo (6) flex (9) geek (5) google (11) grails (5) groovy (10) humeur (12) humour (7) independant (6) iphone (12) Java (77) javascript (7) jazoon (28) jboss (22) jboss seam (12) jsf (9) jug (16) Linux (11) mac (6) mule (5) parisjug (7) paris jug (22) pjug (6) play (8) playframework (6) portlet (5) recrutement (6) ria (8) Scala (21) scrum (44) spring (23) Startup (11) usi (21) usi2010 (9) web (16) xebia (7)

    Le Touilleur Express

    Contactez-moi : nicolas@touilleur-express.fr

    Suivez-moi sur Twitter : @nmartignole

    Copyright© 2008 - 2020 Nicolas Martignole | Tous droits réservés
    • A propos de l’auteur
    • A propos du Touilleur Express
    Le Touilleur Express