XML Wizard & Scripts

Dans beaucoup de framework J2EE, il y a souvent des classes JAVA qui doivent être référencés dans des fichiers XML. Spring, Struts2.x sont des examples de frameworks qui nécéssitent le référencement de classe JAVA dans leur fichiers XML de configuration (spring-config.xml, struts-config.xml).

Avec Akrogen il est possible d'écrire un XML component qui génère la classe JAVA et un XML component qui met à jour le fichier de configuration XML. Dans ce cas-ci, un XML Wizard avec un script qui fait référence à ces deux XML components prend son interêt.

Cette section s'appuie sur un exemple concret basé sur le framework Struts2.x. Nous allons écrire :

  • un XML Component Action qui permet de générer une classe Action Struts 2.x.
  • un XML Component XMLStrutsAction qui permet de mettre à jour le fichier de config struts.xml avec le nom d'une action et de sa classe associée.
  • un XML Wizard Struts qui fait référence à ces deux XML components. Le script utilisé dans ce XML Wizard permettra de synchroniser le contrôle XUL actionClassName du XML component Action avec le contrôle XUL actionClassName du XML component Struts.xml.

Les scripts utilisés dans un XML Wizard utilisent des objets Javascripts :

  • wizard qui permettent de gérer le Wizard à l'aide d'un script.
  • wizardpage qui permettent de gérer un Wizard page à l'aide d'un script. Ces objets sont obtenus à l'aide de la méthode getPageById de l'objet wizard.
  • document qui permettent de gérer les contrôles XUL d'un wizard page. Ces objets sont obtenus à l'aide de la méthode getDocument de l'objet wizardpage.
  • window qui permettent d'utiliser les dialogues alert ou confirm

Cette section ne détaille pas l'écriture des XML components, mais uniquement celui du XML Wizard Struts 2.x.

XML Component Action

Ce XML component permet de générer une classe JAVA Action de Struts 2.x. A partir du Wizard page suivant :

Le fichier JAVA suivant se génère :

package com.youcompany.youwebapp.actions;

import com.opensymphony.xwork2.ActionSupport;

public class MyAction extends ActionSupport {

        public void execute() {
                // DO something
        }
}  

Pour cela, créer le XML component Action.akgncpt.xml dans votre catalogue dans le répertoire Components/Struts2.x :

<?xml version="1.0" encoding="UTF-8"?>
<component>
  <input>
    <page title="Struts2.x Action Class" >
                <description>Generate Struts2.x Action Class.</description>                     
        <box flex="1" id="" orient="vertical" 
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >             
          <script type="text/javascript" >
          
                  function updateOutputFileNameWithJavaClass() {
                          var actionClassName = document.getElementById('actionClassName').value;
                          actionClassName = actionClassName.replace(' ','_');                                   
                          document.getElementById('outputFileName').value = actionClassName + '.java';
                  }  
                  
                  function updateOutputBaseDirWithPackage() {
                          var srcBaseDir = 'src';
                          var actionPackageName = document.getElementById('actionPackageName').value;
                          actionPackageName = actionPackageName.replace('.','/');                                       
                          document.getElementById('outputBaseDir').value = srcBaseDir + '/' + actionPackageName;
                  }                                                     
                  
          </script>                                                  
          <hbox>
            <label value="actionClassName: " />
            <textbox id="actionClassName" flex="1" onkeyup="javascript:updateOutputFileNameWithJavaClass();" />
          </hbox>
          <hbox>
            <label value="actionPackageName: " />
            <textbox id="actionPackageName" flex="1" onkeyup="javascript:updateOutputBaseDirWithPackage();" />
          </hbox>          
          <hbox>
            <label value="outputBaseDir:" />
            <textbox id="outputBaseDir" flex="1" />
            <button type="folder" target="outputBaseDir" label="Browse..." />
          </hbox>
          <hbox>
            <label value="outputFileName:" />
            <textbox id="outputFileName" flex="1" />
          </hbox>       
          <hbox>
            <button type="preview" label="Preview..." />
          </hbox>                       
        </box>                  
    </page>
  </input>
  <output>
    <file>
      <template uri="/ftl/Struts2.x/Action.ftl" /> 
    </file>
  </output>
</component>

Créer le template Freemarker Action.ftl dans le répertoire Templates/ftl/Struts2.x/ :

package ${actionPackageName};

import com.opensymphony.xwork2.ActionSupport;

public class ${actionClassName} extends ActionSupport {

        public void execute() {
                // DO something
        }
}  

XML Component XMLStrutsAction

Ce XML component permet de mettre à jour le fichier struts.xml après l'avoir sélectionné) en référançant la classe Action dans celui-ci. A partir du Wizard page suivant :

Il permet de d'ajouter le fragment XML :

    <action name="myaction" 
            class="com.youcompany.youwebapp.MyAction">
    </action>

dans le fichier source XML de configuration struts.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

  <package name="example"  extends="struts-default">
    <action name="Hello" class="example.Hello">
      <result type="json" />
    </action>

    <action name="Main" class="com.opensymphony.xwork2.ActionSupport">
      <result>org.apache.struts.gwt.Main/Main.jsp</result>
    </action>
     
  </package>

</struts>  

Comme ceci :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

  <package name="example"  extends="struts-default">
    <action name="Hello" class="example.Hello">
      <result type="json" />
    </action>

    <action name="Main" class="com.opensymphony.xwork2.ActionSupport">
      <result>org.apache.struts.gwt.Main/Main.jsp</result>
    </action>
    <action name="myaction" 
            class="com.youcompany.youwebapp.MyAction">
    </action>
    
  </package>

</struts>  

Pour cela, créer le XML component XMLStrutsAction.akgncpt.xml dans votre catalogue dans le répertoire Components/Struts2.x :

<?xml version="1.0" encoding="UTF-8"?>
<component dynamic="true" >
  <models>
        <model key="struts" type="xml" />
  </models>
  <input>
    <page title="Action struts.xml" >
        <description>Add Action into struts.xml</description>
        <box flex="1" id="" orient="vertical"
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">      
                        <script type="text/javascript" >
                
                        function updateClassNameWithJavaClass() {
                                var actionClassName = document.getElementById('actionClassName').value;
                                var index = actionClassName.lastIndexOf('.');                                   
                                if (index != -1) {
                                        actionClassName = actionClassName.substring(index + 1, actionClassName.length());
                                }
                                actionClassName = actionClassName.toLowerCase();
                                document.getElementById('actionName').value = actionClassName;
                        }                                
                        </script>
                <hbox>
                  <label value="Action class name :" />
                  <textbox id="actionClassName" 
                                   onkeyup="javascript:updateClassNameWithJavaClass();"
                                   flex="1" />
                  <button type="classText" target="actionClassName" label="Browse..." />
                </hbox>              
                <hbox>
                        <label value="Action name :" />
                        <textbox id="actionName" flex="1" />
                </hbox>
                <hbox>
                        <label value="Result type :" />
                        <menulist id="resultType" editable="true" >
                                          <menupopup>
                                            <menuitem label="json"/>
                                          </menupopup>
                                        </menulist>
                </hbox>           
                <hbox>
                <button type="preview" label="Preview..." />
                </hbox>             
        </box>                  
    </page>
  </input>
  <output>
    <file key="struts" >
        <insert path="/struts/package/action[last()]" position="after" >
                <template uri="/ftl/Struts2.x/XMLStrutsAction.ftl" />
        </insert>
    </file>
  </output>
</component>  

Créer le template Freemarker XMLStrutsAction.ftl dans le répertoire Templates/ftl/Struts2.x/ :

<action name="${actionName}" 
        class="${actionClassName}">
  <#if resultType != '' >
  <result type="${resultType}" />
  </#if>
</action> 

XML Wizard Struts

Voic le XML Wizard qui permet d'enchaîner les deux XML Components :

<?xml version="1.0" encoding="UTF-8"?>
<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul " >
        <wizardpage uri="Struts2.x/Action.akgncpt.xml" />
        <wizardpage uri="Struts2.x/XMLStrutsAction.akgncpt.xml" />
</wizard>  

Créer le XML Wizard Struts.akgnwzd.xml dans votre catalogue dans le répertoire Wizards/Struts2.x. Après avoir rafraîchit votre catalogue, celui doit apparaître dans la vue Catalogue.

Sélectionner le fichier struts.xml (en tant que modèle) puis double cliquer dessus. Le premier wizard page affiché est celui du XML Component Action et le deuxième celui de XML Component XMLStrutsAction.

A cette étape, le contrôle XUL actionClassName doit être saisi dans les deux XML components.

Il est posible à l'aide d'un script de saisir une fois le contrôle XUL actionClassName du premier wizard page qui met à jour celui du deuxième wizard page.

Voici le XML Wizard qui permet de gérer la synchronisation entre les deux contrôles XUL :

<?xml version="1.0" encoding="UTF-8"?>
<wizard 
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul " >
        <script type="text/javascript" >
          function synchronyseActionClassName() {
                  
            /***********************************************************/
            /* 1. Get XUL control actionClassName of Action wizardpage */ 
            /***********************************************************/
            
            // Get current wizard page (it's Action)
            var /* wizardpage */ page0 = wizard.getPageById('page0');                   
            // Get XUL Document of wizardpage Action
            var document0 = page0.getDocument();
            var actionClassName0 = document0.getElementById('actionClassName');
            
            /***********************************************************/
            /* 2. Get XUL control actionClassName of XMLStrutsAction wizardpage */ 
            /***********************************************************/
            
            // Get wizardpage  XMLStrutsAction
            var /* wizardpage */ page1 = wizard.getPageById('page1');                   
            // Get XUL Document of wizardpage XMLStrutsAction
            var document1 = page1.getDocument();
            var actionClassName1 = document1.getElementById('actionClassName');                 
            
            /***********************************************************/
            /* 3. Set value actionClassName  */ 
            /***********************************************************/
            actionClassName1.value = actionClassName0.value;
            
          }
        </script>
        <wizardpage pageid="page0" 
                    uri="Struts2.x/Action.akgncpt.xml"
                    onpageadvanced="javascript:synchronyseActionClassName();" />
        <wizardpage pageid="page1" uri="Struts2.x/XMLStrutsAction.akgncpt.xml" />
</wizard>  

Le script est lancé sur l'évenement onpageadvanced du premier wizard page qui est déclenché lorsque le bouton Next du Wizard Eclipse est cliqué.