Category: Dev

Scala – Scalatra – Salat – MongoDB : découverte

CodeDevFrançaisTutorials

Bonjour, un petit test avec Scala (2.9.0-1) pour la partie service, Scalatra concernant le front en REST, Salat et MongoBB pour la persistance des données. J’utiliserai sbt (0.10) pour la gestion du projet et IntelliJ Idea comme IDE (What else ?).

Qu’allons nous voir ici ?

Nous allons exposer une API REST (et sa documentation associée) afin de créer des utilisateurs (identifiant, courriel, mot de passe). Cette API est extrèmement simple afin de bien comprendre ce qui se passe.
L’objectif est donc de pouvoir :
– créer un utilisateur,
– trouver un utilisateur (avec son ID ou son identifiant),
– effacer un utilisateur
– visualiser la documentation de chaque API en ligne pour chacune des méthodes
Keep reading

CentOS – Geoserver + osm2pgsql – Installation

DevFrançaisLinuxTutorials

Dans cet article nous allons voir comment mettre en place un serveur de carte.

Sur base de net install x64 de CentOS 6, installation de type “Basic server” tout par défaut.
Pour l’URL utilisez celle-là par exemple : http://mirror.centos.org/centos/6/os/x86_64
(une image virtual box est disponible ici… a venir…)

Les différentes ressources documentaires à l’origine de ce post :
http://wiki.openstreetmap.org/wiki/Osm2pgsql
http://weait.com/content/build-your-own-openstreetmap-server
http://www.surfaces.co.il/?p=880
http://ian01.geog.psu.edu/geoserver_docs/data/openstreetmap/osm.html

On commence par mettre à jour le système : Keep reading

Multi-tenant Hibernate

DevEnglish

Let’s say you have an application that needs to deal with several tenants and that each tenant requires to have its own database located where he wants.
In our example we will have the same database shcema for all tenant but it is not a problem to have several schemas.
The solution presented here loads one SessionFactory per Tenant Keep reading

Code generator with ant FMPP and FreeMarker

CodeDevEnglish

A simple code generator example with FMPP and FreeMarker with the help of ant and antelope for automation.

Content :
– Why should we do code generators ?
– How it works
– Prepare ant tasks
– Let’s try with a simple file
– Now let’s do something bigger

Why should we do code generators
Some people are…pretty anxious when I advocate the use of a code generator. Most of the time they think spending time on a code generator isn’t productive enough for their short term objectives… These kind of person spend their lives running to catch a train that goes to fast for their capacity. Actually, code generators are a perfect answer for short term project, but not the first one (and again this isn’t obvious).

Code generators are part of your company’s (or personal) normalisation, industrialisation, and process simplification.
– Developers can focus more on business than technical implementation,
– Maintenance is easier : all code base is similar
– If your company turnover is important, process are simpler to acquire

So actually you can code faster, with a better quality, the ROI is always (if code generator is correctly done) positive.

How it works
Creating a code generator project is really fast, just :
1- use a real project you want to generate and copy it somewhere,
2- identify the dynamic stuff inside this project, like :
– classnames,
– packages,
– folders,
– …
3- replace dynamic patterns with a property tag
4- generate it once and do the adjustments if needed

In order to have an idea, a code generator creating around fifty files, that creates a Flex module with BlazeDS Java endpoints takes about 4 hours of work and tuning before beiing live.

Prepare ant tasks
Download Fmpp and AntelopeTasks jars and put them inside your ANT_HOME/lib folder.
Then inside your build.xml add those 2 lines after your project definition :

<taskdef name="antelope" classname="ise.antelope.tasks.StringUtilTask" />
<taskdef name="fmpp" classname="fmpp.tools.AntTask" />

Now to use fmpp just do something like this inside a target :

<fmpp sourceRoot="${basedir}/src/MODULE/entity_and_code" 
      outputroot="${module_base_dir}/${entity_and_code}" 
      alwaysCreateDirectories="true" 
      logfile="${basedir}/logs/${entity_and_code}.log" >
  <data>antProperties()</data>
</fmpp>

Antelope in this project will be used mostly for its lowercase/upperCase/replace commands. Example :

  <property name="entity_and_code" value="${entity_and_project}_${module_code}" />
  <antelope string="${entity_and_code}" property="entity_and_code">
    <lowercase />
  </antelope>
  <antelope string="${entity_and_code}" property="ENTITY_AND_CODE">
    <uppercase />
  </antelope>

Let’s try with a simple file

You can get the files here : QQ_CG01.tar

The src folder contains this hierarchy : fr/quidquid/sample/flex/modules/MODULE_CODE
This folder contains the ModuleConstants.as file.

Inside the ModuleConstants.as file you’ll find freemarker tags :

package ${module_base_package}.flex.${module_code}
{
    public class  ModuleConstants{

        // ***********************************************
        // ******** EVENTS FOR ${module_code?upper_case}_${module_name}

        public static const EVENT_${module_code?upper_case}_TESTBUTTON_SUBMIT:String = "EVENT_${module_code?upper_case}_TESTBUTTON_SUBMIT";

        // ####_DO_NEVER_(RE)MOVE_THIS_LINE_NOR_CHANGE_IT_#### EVENTS

        // ***********************************************
        // ******** NOTIF FOR ${module_code?upper_case}_${module_name}

        public static const NOTIF_${module_code?upper_case}_I18N_GET_OK:String = "NOTIF_${module_code?upper_case}_I18N_GET_OK";

        // ####_DO_NEVER_(RE)MOVE_THIS_LINE_NOR_CHANGE_IT_#### NOTIF

    }
}

Our goal is to replace these tags and after generation rename the MODULE_CODE folder with the right name.

First step to see how it works, in the root folder open the PROJECT.properties, it contains our dynamic stuffs (quite simple on this example):

# Output folder of the code generator
output_dir = OUT

# Base package, will be suffixed with the module_code upper case 
module_base_package = fr.quidquid.sample.flex.modules
# Functionnal name
module_name = Quidquid Test
# Module unique name in the whole application
module_code = QQT01

Then let’s look at the build.xml file:

<project name="SimpleCodeGenerator" default="generate" basedir=".">

  <!-- Initialize antelope and fmpp -->
  <taskdef name="antelope" classname="ise.antelope.tasks.StringUtilTask" />
  <taskdef name="fmpp" classname="fmpp.tools.AntTask" />

  <target name="generate">

    <!-- Get properties from property file -->
    <property file="${basedir}/PROJECT.properties" />

    <!-- I need module_code to be lower case -->
    <antelope string="${module_code}" property="module_code">
      <lowercase />
    </antelope>
    
    <!-- I need module_base_package to be lower case -->
    <antelope string="${module_base_package}" property="module_base_package">
      <lowercase />
    </antelope>
    <!-- Get the path from the package ( just replaces . with / )-->
    <antelope string="${module_base_package}" property="module_base_path">
      <replace regex="\." replacement="/" />
    </antelope>

    <!-- MODULE GENERATION -->
    <fmpp sourceRoot="${basedir}/src/" 
          outputroot="${output_dir}/" 
          alwaysCreateDirectories="true" 
          logfile="${basedir}/${module_code}.log" >
      <data>antProperties()</data>
    </fmpp>

    <!-- Rename the module folder -->
    <move todir="${output_dir}/${module_base_path}/${module_code}">
      <fileset dir="${output_dir}/${module_base_path}/MODULE_CODE" />
    </move>

  </target>

</project>

You can now open a command line ant do:

[julien@mars QQ_CG01]# ant

Output should be something like:

Now you should have an OUT folder containing your fr/quidquid/sample/flex/modules/qqt01/ModuleConstants.as with all the freemarker tags replaced… Easy no ?

Some freeMarker expressions you can use:
${module_code?upper_case}
${module_code?lower_case}
${module_code?cap_first}

To change the name of a filename:
<@pp.dropOutputFile />
<@pp.changeOutputFile name=module_name?cap_first + "Mediator.as" />

Well just go through the manual: http://freemarker.sourceforge.net/docs/dgui_template_exp.html

.

Javascript – Afficher / cacher un élément HTML

DevFrançaisTutorials

Comment jouer à cache-cache avec des éléments HTML, avec un petit bout de code javascript complètement réutilisable ?
C’est la question du jour de nos amis d’outre-quévin qui aiment la batavia !

Prenons une page HTML (nous appellerons cette page HTML “castor” dans le reste du document) relativement simple :

<html>
<head>
  <title>Test</title>
</head>

<body>

<h3>Voici une liste FAQ passionnante</h3>
<br/>
<strong>Les multivers ont-ils un référentiel temporel commun ?</strong>
<div id="FAQ_1">
  C'est une excellente question et je vous remercie de l'avoir posée.
  Vous ne pensez tout de même pas qu'un type dans mon genre à la réponse ? 
  Appelez Stephen Hawking de ma part, il sera ravi de vous aider !
</div>
<br/>
<strong>Comment se fait-il que lors d'un décès, il existe une 
disparition de l'information ?</strong>
<div id="FAQ_2">
  Alors là, la question est celle du poids de l'information et 
  de sa place dans l'univers. Effectivement lorsque quelqu'un meurt,
  de l'information disparait ou du moins retourne à l'état de matière 
  qui en est le stade primitif.
</div>
<br/>
<strong>FAQ dinosaures :</strong>
<table align="center" border="1">
  <tr>
    <th>N°</th>
    <th>Nom</th>
    <th>Caractéristiques</th>
  </tr>
  <tr id="tableau" class="minimized">
    <td>1</td>
    <td>Allosaure</td>
    <td>
      Ancètre du tyranosaure, l'allosaure est un carnivore redoutable, 
      l'apparition  du téléphone à scellé le sort de l'Allo...
    </td>
  </tr>
  <tr>
    <td>2</td>
    <td>Ankylosaure</td>
    <td>
      Herbivore sympathique, l'ankylosaure pouvait se défendre 
      efficacement contre des prédateurs bien plus gros que lui 
      grâce à la lourde boule qui terminait sa queue.
    </td>
  </tr>
  <tr>
    <td>3</td>
    <td>Ptérosaure</td>
    <td>
      Le roi des airs, il était même capable de chanter à la perfection 
      l'air de la Reine de la nuit de la flute enchantée !
    </td>
  </tr>
</table>
</body>
</html>

Et donc à partir de ce castor (cette page HTML pour ceux qui n’ont pas tout lu) nous voulons cacher les réponses de la FAQ et ne les afficher qu’à la demande expresse… de nos amis d’outre-quévin justement…
Donc l’objectif est d’avoir une page qui cache le contenu mais pas les titres.
Nous allons utiliser 2 petites images ma foi fort sympathiques :
et

Voici les améliorations à effectuer :
– Ajout des styles min et max (dans la partie HEAD) qui cachent et affichent un élément possédant un ID :

<head>
  <title>Test</title>
  <style type="text/css">
    .min { display:none; }
    .max { display:''; }
  </style>
</head>

– Association des styles class=”min” avec les éléments que l’on souhaite cacher au lancement de la page, exemple avec le FAQ_1 :

<div id="FAQ_1" class="min">
  C'est une excellente question et je vous remercie de l'avoir posée.
  Vous ne pensez tout de même pas qu'un type dans mon genre à la réponse ? 
  Appelez Stephen Hawking de ma part, il sera ravi de vous aider !
</div>

– Ajout d’une méthode javascript pour gérer le changement de style d’un élément et d’une autre pour gérer le changement de la source de l’image (il est bien sur possible de tout mettre dans une seule méthode mais, et nous le verrons plus bas, elle aurait été peu réutilisable) :

</head>
<script type="text/javascript">
<!--
// Pour afficher ou cacher n'importe quel élément HTML possédant un ID
function afficheCache(id) {
   var elem = document.getElementById(id);
   if (elem) {
       if (elem.className != 'min') {
         elem.className = 'min';
       }
       else {
         elem.className = 'max';
       }
   }
}

// Pour changer la source d'une image en fonction du style d'un élément HTML
function imgAfficheCache(img, id) {
   afficheCache(id)
   var elem = document.getElementById(id);
   if (elem) {
       if (elem.className != 'min') {
         img.src="moins.gif"
       }
       else {
         img.src="plus.gif"
       }
   }
}
//-->
</script>
<body>

– Ajout des images d’action qui apellent le JS pour cacher/afficher les éléments :

<img src="plus.gif" title="Afficher/Cacher" onclick="imgAfficheCache(this, 'FAQ_1')" />
<strong>Les multivers ont-ils un référentiel temporel commun ?</strong>
<div id="FAQ_1" class="min">
  C'est une excellente question et je vous remercie de l'avoir posée.
  Vous ne pensez tout de même pas qu'un type dans mon genre à la réponse ? 
  Appelez Stephen Hawking de ma part, il sera ravi de vous aider !
</div>

Bien faire attention aux id qui correspondent aux blocks que l’on souhaite cacher

Pour montrer la ré-utilisabilité du code on ajoute une petite ligne (sans image) qui permet d’afficher ou de cacher la première ligne du tableau de la FAQ_3 :

<span onclick="afficheCache('TAB_1')" >Cliquez-moi pour afficher ou cacher 
la 1ere ligne du tableau !</span>

Vous noterez qu’au lieu de passer par imgAfficheCache(), on utilise afficheCache() qui se fiche de changer une image.

Voici le code complet de la page :

<html>
<head>
  <title>Test</title>
  <style type="text/css">
    .min { display:none; }
    .max { display:''; }
  </style>
</head>
<script type="text/javascript">
<!--
// Pour afficher ou cacher n'importe quel élément HTML possédant un ID
function afficheCache(id) {
   var elem = document.getElementById(id);
   if (elem) {
       if (elem.className != 'min') {
         elem.className = 'min';
       }
       else {
         elem.className = 'max';
       }
   }
}

// Pour changer la source d'une image en fonction du style d'un élément HTML
function imgAfficheCache(img, id) {
   afficheCache(id)
   var elem = document.getElementById(id);
   if (elem) {
       if (elem.className != 'min') {
         img.src="moins.gif"
       }
       else {
         img.src="plus.gif"
       }
   }
}
//-->
</script>

<body>

<h3>Voici une liste FAQ passionnante</h3>
<br/>
<img src="plus.gif" title="Afficher/Cacher" onclick="imgAfficheCache(this, 'FAQ_1')" />
<strong>Les multivers ont-ils un référentiel temporel commun ?</strong>
<div id="FAQ_1" class="min">
  C'est une excellente question et je vous remercie de l'avoir posée.
  Vous ne pensez tout de même pas qu'un type dans mon genre à la réponse ? 
  Appelez Stephen Hawking de ma part, il sera ravi de vous aider !
</div>
<br/>
<br/>
<img src="plus.gif" title="Afficher/Cacher" onclick="imgAfficheCache(this, 'FAQ_2')" />
<strong>Comment se fait-il que lors d'un décès, il existe une 
disparition de l'information ?</strong>
<div id="FAQ_2" class="min">
  Alors là, la question est celle du poids de l'information et 
  de sa place dans l'univers. Effectivement lorsque quelqu'un meurt,
  de l'information disparait ou du moins retourne à l'état de matière 
  qui en est le stade primitif. Ce qui je l'accorde reste extrèmement
  perturbant !
</div>
<br/>
<br/>
<img src="plus.gif" title="Afficher/Cacher" onclick="imgAfficheCache(this, 'FAQ_3')" />
<strong>FAQ dinosaures :</strong>
<table align="center" id="FAQ_3" border="1" class="min">
  <tr>
    <th>N°</th>
    <th>Nom</th>
    <th>Caractéristiques</th>
  </tr>
  <tr id="TAB_1" class="min">
    <td>1</td>
    <td>Allosaure</td>
    <td>
      Ancètre du tyranosaure, l'allosaure est un carnivore redoutable, 
      l'apparition  du téléphone à scellé le sort de l'Allo...
    </td>
  </tr>
  <tr>
    <td>2</td>
    <td>Ankylosaure</td>
    <td>
      Herbivore sympathique, l'ankylosaure pouvait se défendre 
      efficacement contre des prédateurs bien plus gros que lui 
      grâce à la lourde boule qui terminait sa queue.
    </td>
  </tr>
  <tr>
    <td>3</td>
    <td>Ptérosaure</td>
    <td>
      Le roi des airs, il était même capable de chanter à la perfection 
      l'air de la Reine de la nuit de la flute enchantée !
    </td>
  </tr>
</table>
<br/>
<br/>
<br/>
<br/>
<span onclick="afficheCache('TAB_1')" >Cliquez-moi pour afficher ou cacher la 1ere ligne du tableau !</span>

</body>
</html>

Bonne journée !

CastorHelper

CodeDevFrançais

Dans la série code à garder sous la main : Une classe pour travailler Castor

package com.ledruide.utils.xml;

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.xml.sax.InputSource;

public class CastorHelper {

    private CastorHelper() {}

    private static final String ENCODING = "UTF-16";

    /**
     * Permet de creer un fichier contenant le XML genere
     * 
     * @param monObjet la classe contenant les donnees a 'castoriser'
     * @param mappingFile le fichier XML de mapping pour savoir quoi faire avec l'Objet
     * @throws Exception si une erreur survient.
     */
    public static String saveXMLFile( Object monObjet , String mappingFile ) throws Exception {
        try {

            StringWriter content = new StringWriter();
            // First look into the classpath
            InputStream is = CastorHelper.class.getResourceAsStream( mappingFile );
            // If the input stream is not OK I look into the filesystem
            if ( is == null ) {
                is = new FileInputStream( mappingFile );
            }
            // Chargement du mapping
            Mapping mapping = new Mapping();
            mapping.loadMapping( new InputSource( is ) );
            // Marshal l'object -> La transformation de Java en XML !
            final Marshaller marshaller = new Marshaller( content );
            marshaller.setValidation( false );
            marshaller.setMapping( mapping );
            marshaller.setEncoding( ENCODING );
            marshaller.marshal( monObjet );

            return content.toString();
        }
        catch ( Exception e ) {
            throw e;
        }
    }

    /**
     * Permet de lire un fichier XML contenant les donnees
     * 
     * @param aClasse la classe d'implémentation des donnees a 'decastoriser'
     * @throws Exception si une erreur survient.
     */
    public static void loadXMLFile( Object monObjet , String mappingFile , String xml ) throws Exception {
        try {
            // First llok into the classpath
            InputStream is = CastorHelper.class.getResourceAsStream( mappingFile );
            // If the input stream is not OK I look into the filesystem
            if ( is == null ) {
                is = new FileInputStream( mappingFile );
            }

            // Chargement du mapping
            Mapping mapping = new Mapping();
            mapping.loadMapping( new InputSource( is ) );
            // UnMarshal l'object -> La transformation XML vers Java !
            Unmarshaller unmarshaller = new Unmarshaller( monObjet );
            unmarshaller.setWhitespacePreserve( true );
            unmarshaller.setMapping( mapping );
            monObjet = unmarshaller.unmarshal( new FileReader( xml ) );
        }
        catch ( Exception e ) {
            throw e;
        }
    }

    /**
     * @param result
     * @return
     * @throws IOException
     * @throws MarshalException
     * @throws ValidationException
     */
    public static String dynamicXmlFromObject( Object object ) throws Exception {
        StringWriter content = new StringWriter();
        final Marshaller marshaller = new Marshaller( content );
        marshaller.setValidation( false );
        marshaller.setEncoding( ENCODING );
        marshaller.setSuppressXSIType(true);
        marshaller.marshal( object );

        return content.toString();
    }

}