<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le Touilleur Express &#187; web</title>
	<atom:link href="http://www.touilleur-express.fr/tag/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.touilleur-express.fr</link>
	<description>Blog sur Java, le métier de développeur et la vie de freelance par Nicolas Martignole</description>
	<lastBuildDate>Wed, 08 Feb 2012 11:54:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Comment tester son site sur les différentes versions d&#8217;Internet Explorer</title>
		<link>http://www.touilleur-express.fr/2011/11/03/comment-tester-son-site-sur-les-differentes-versions-dinternet-explorer/</link>
		<comments>http://www.touilleur-express.fr/2011/11/03/comment-tester-son-site-sur-les-differentes-versions-dinternet-explorer/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 08:06:08 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.touilleur-express.fr/?p=5793</guid>
		<description><![CDATA[Je ne sais pas pour vous, mais moi Windows j&#8217;ai dit bye-bye en 2008 pour prendre un Mac. Alors on peut dire ce que l&#8217;on veut d&#8217;Apple, râler très fort en disant que c&#8217;est cher, mais il y a un truc qui échappe encore au monde de Windows : ça marche. 
En même temps on a un vrai métier &#171;&#160;dans la vraie vie&#160;&#187; comme disent les gens. Or dans ma vraie vie de développeur indépendant, je code des sites Internet avec Play! Framework pour des clients. Et les sites de ...]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.touilleur-express.fr/wp-content/uploads/2011/11/tag_web.jpg" alt="" title="tag_web" width="150" height="150" class="alignleft size-full wp-image-5795" />Je ne sais pas pour vous, mais moi Windows j&#8217;ai dit bye-bye en 2008 pour prendre un Mac. Alors on peut dire ce que l&#8217;on veut d&#8217;Apple, râler très fort en disant que c&#8217;est cher, mais il y a un truc qui échappe encore au monde de Windows : ça marche. </p>
<p>En même temps on a un vrai métier &laquo;&nbsp;<em>dans la vraie vie</em>&nbsp;&raquo; comme disent les gens. Or dans ma vraie vie de développeur indépendant, je code des sites Internet avec Play! Framework pour des clients. Et les sites de mes clients doivent fonctionner sur le navigateur de Microsoft, à savoir Microsoft Internet Explorer. La question aujourd&#8217;hui, cher public, c&#8217;est comment tester facilement que le fruit de votre travail fonctionne sur IE7, IE8 et IE9 ? Et bien voici la réponse : Virtual Box et des VMs, un script intelligent et quelques heures de patience. </p>
<p>Je commence par la fin, pour montrer à la salle qu&#8217;il n&#8217;y a aucuns trucages :<br />
<a href="http://www.touilleur-express.fr/wp-content/uploads/2011/11/windows_vm_virtualbox.png"><img src="http://www.touilleur-express.fr/wp-content/uploads/2011/11/windows_vm_virtualbox-300x228.png" alt="" title="windows_vm_virtualbox" width="300" height="228" class="alignnone size-medium wp-image-5794" /></a> </p>
<p>Le site Artstechnica montre <a href="http://arst.ch/rg6">dans cet article</a> que pour la première fois, Internet Explorer est passé sous la barre des 50% des navigateurs utilisés dans le monde, en octobre 2011. Bref si IE6 est presque mort, il faut bien voir qu&#8217;IE8 est actuellement le navigateur le plus utilisé dans le monde. </p>
<p>Alors voyons comment configurer des machines virtuelles rapidement avec IE7, IE8 et IE9. Pour IE7 nous allons utiliser Windows Vista. Et pour IE8/IE9 nous prendrons Windows 7 Ultimate Edition. Ce qui suit fonctionne pour Mac OS X et pour Linux. </p>
<p><strong>Virtual Box</strong><br />
Commencez par installer <a href="http://virtualbox.org/">Virtualbox</a>, une machine virtuelle gratuite et géniale, développée par SUN Microsystems et qui appartient maintenant à Oracle. Sur Mac OS X avec un processeur Intel, ceci vous permet d&#8217;avoir un Windows fonctionnel et qui tourne parfaitement. </p>
<p><strong>Les machines virtuelles Microsoft</strong><br />
Microsoft propose des machines virtuelles pour les développeurs Webs, afin de tester leurs sites webs facilement sur les différents navigateurs <a href="http://www.microsoft.com/download/en/details.aspx?id=11575">depuis août dernier</a>. Ces images sont même patchées avec les dernières corrections de sécurité. Cependant vous ne pourrez pas activer l&#8217;image virtuelle. Ce ne sera donc pas une installation de Windows sur laquelle vous pourrez installer d&#8217;autres logiciels. Tous les 30 jours il faudra revenir à l&#8217;image de départ, mais je vais vous expliquer cela plus loin. </p>
<blockquote><p>In order to help web designers and web developers test their websites in older versions of Internet Explorer, we&#8217;ve provided the following VHD with Windows set up with the specified version of Internet Explorer. The images are patched with the latest security updates and are otherwise clean installs of the operating system with very few modifications. </p>
<p>This download page contains different VPC images, depending on what you want to test.  These images are specifically designed to run on Microsoft Virtual PC, and may or may not work in other hosting environments. </p>
<p>Due to the size of the Windows 7 and Windows Vista VHDs, it is split across several files, you&#8217;ll need to download all files for that version of the Internet Explorer and uncompress them to the same directory to unpack the VHD file. </p>
<p>The password to login to all of these images is <strong>Password1</strong> and the username will be present when you first login. </p>
<p>*Note: You may be required to activate the OS as the product key has been deactivated. This is the expected behavior. The VHDs will not pass genuine validation. Immediately after you start the Windows 7 or Windows Vista images they will request to be activated. You can cancel the request and it will login to the desktop. You can activate up to two “rearms” (type slmgr –rearm at the command prompt) which will extend the trial for another 30 days each time OR simply shutdown the VPC image and discard the changes you’ve made from undo disks to reset the image back to its initial state.  By doing either of these methods, you can technically have a base image which never expires although you will never be able to permanently save any changes on these images for longer than 90 days.
</p></blockquote>
<p>Le nom d&#8217;utilisateur sera Admin et le mot de passe par défaut est Password1. </p>
<p><strong>Je veux un script</strong><br />
Je ne sais pas pour vous, mais moi je ne me vois pas télécharger chacune des VMs et ensuite configurer pas à pas les installations. En cherchant un peu sur Github, j&#8217;ai trouvé un script développé par Greg Thornton qui marche super bien sur Mac OS X Lion. Allez voir <a href="https://github.com/xdissent/ievms">https://github.com/xdissent/ievms</a>. </p>
<p>Pour lancer le téléchargement et l&#8217;installation des VMs, pour peu que Virtual Box soit déjà installé, comptez 3 à 4 heures avec la commande suivante :<br />
<code>
<pre>
curl -s https://raw.github.com/xdissent/ievms/master/ievms.sh | bash
</pre>
<p></code></p>
<p>Voilà, vous aurez ensuite 3 VMs sur VirtualBox configurées avec IE7, IE8 et IE9.</p>
<p><strong>Oui mais le numéro de série ?</strong><br />
Pas besoin de numéro de série. Il suffit de ne pas activer la version de Windows, et de reprendre à chaque fois l&#8217;image de base sans sauvegarder sur VirtualBox. Une autre possibilité plus compliquée est expliquée <a href="http://www.microsoft.com/download/en/details.aspx?id=11575">sur le site de Microsoft</a>.</p>
<p>Au final, cela vous donne un moyen simple et rapide de tester avec IE7, IE8 et IE9 votre site Internet.</p>
<p><strong>D&#8217;autres manières de tester</strong></p>
<p>Via Twitter (@nmartignole) j&#8217;ai eu d&#8217;autres suggestions d&#8217;outils et de liens intéressants. Voici ce que j&#8217;ai reçu : </p>
<p>- <a href="http://www.browserstack.com">http://www.browserstack.com</a> est une solution dans le cloud qui permet aussi de tester un site en local sur votre machine, via une Applet Java. Vous pouvez tester le service gratuitement 60mn, sinon c&#8217;est payant. Outil proposé par @alanzirek. </p>
<p>- <a href="http://saucelabs.com/ondemand">SauceOnDemand</a> permet de tester un site via des VMs hostées dans le Cloud. Intéressant, il est possible de faire tourner des tests Selenium afin de vous notifier lorsqu&#8217;une des versions pour un navigateur donné est cassée. Merci @fcamblor du BordeauxJUG pour l&#8217;info. </p>
<p>[Update]<br />
Après plusieurs essais, la solution la plus pratique est <a href="http://www.browserstack.com/">Browserstack</a>. Cet outil vous permet de tester via votre navigateur puis des machines virtuelles, l&#8217;ensemble des navigateurs du marché. A découvrir d&#8217;urgence. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2011/11/03/comment-tester-son-site-sur-les-differentes-versions-dinternet-explorer/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Spring Faces+WebFlow+Java classique comparé à Play! Framework</title>
		<link>http://www.touilleur-express.fr/2010/05/13/spring-faceswebflowjava-classique-compare-a-play-framework/</link>
		<comments>http://www.touilleur-express.fr/2010/05/13/spring-faceswebflowjava-classique-compare-a-play-framework/#comments</comments>
		<pubDate>Thu, 13 May 2010 13:23:31 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[jsf]]></category>
		<category><![CDATA[play]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.touilleur-express.fr/?p=3716</guid>
		<description><![CDATA[
Dans cet article, je vous propose de regarder 2 approches différentes pour résoudre un même problème : construire une application web sécurisée, moderne et Ajaxisé. Je vais vous présenter les différences de conceptions sur la partie Java essentiellement. Cet article ne sera pas une introduction à l&#8217;une ou l&#8217;autre des technologies. Je souhaite vous éclairer sur quelques concepts différents dans Play! par rapport à l&#8217;approche classique.
Pour comparer 2 choses, il faut un référentiel comparable. JBoss Seam propose sur cette page plusieurs versions d&#8217;une application de réservation de chambres d&#8217;hôtels. La ...]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.touilleur-express.fr/wp-content/uploads/2010/05/springwebflow-versus-Play1.jpg"><img src="http://www.touilleur-express.fr/wp-content/uploads/2010/05/springwebflow-versus-Play1.jpg" alt="" title="springwebflow-versus-Play" width="500" height="500" class="alignnone size-full wp-image-3719" /></a><br />
Dans cet article, je vous propose de regarder 2 approches différentes pour résoudre un même problème : construire une application web sécurisée, moderne et Ajaxisé. Je vais vous présenter les différences de conceptions sur la partie Java essentiellement. Cet article ne sera pas une introduction à l&#8217;une ou l&#8217;autre des technologies. Je souhaite vous éclairer sur quelques concepts différents dans Play! par rapport à l&#8217;approche classique.</p>
<p>Pour comparer 2 choses, il faut un référentiel comparable. JBoss Seam propose <a href="http://demo.flamingo.exadel.com/booking/">sur cette page</a> plusieurs versions d&#8217;une application de réservation de chambres d&#8217;hôtels. La version originale basée sur JSF 1.2 n&#8217;est plus toute jeune mais fonctionne très bien. <a href="http://www.touilleur-express.fr/2006/12/12/jboss-seam-linteret-de-la-conversation/">J&#8217;en avais parlé sur le Touilleur Express il y a 3 ans et demie&#8230;</a> Quand je me dis que cela fait plus de 3 ans que j&#8217;ai vu cela, et qu&#8217;à l&#8217;époque je vous avais convaincu de regarder JSF par rapport à Struts, je me dis qu&#8217;il faut que je réussisse dans cet article à vous montrer la nouvelle approche, celle de 2010.</p>
<p>Nous allons prendre Spring Faces et Spring Webflow, une approche que je trouve très intéressante et qui permet de réaliser des applications Webs avec les technologies de Spring.</p>
<h2>I. Le match : télécharger, installer et lancer la démo</h2>
<p>Voyons tout d&#8217;abord comment télécharger, compiler et lancer la démonstration avec chacun des environnements. Je souhaite évaluer la rapidité de prise en main. Je souhaite que le projet soit configuré dans IDEA IntelliJ ou Eclipse pour travailler, et je vais évaluer la facilité à monter chacun des environnements. Je regarderai aussi le temps de démarrage des serveurs Webs testés.</p>
<h3>I.1) Préparation de l&#8217;espace de démo pour Spring</h3>
<p>SpringSource propose &laquo;&nbsp;<a href="http://richweb.springframework.org/swf-booking-faces/spring/intro">Spring Travel</a>&laquo;&nbsp;, une version basée sur <a href="http://www.springsource.org/faces">Spring Faces</a>, Spring WebFlow 2.0.9 et une librairie JSF avancée pour le rendu. J&#8217;ai regardé précisément le code &laquo;&nbsp;booking-faces&nbsp;&raquo; dans le répertoire projects/spring-webflow-samples pour écrire cet article. Si vous souhaitez tester par vous même :<br />
- téléchargez <a href="http://www.springsource.org/download#webflow">la version Spring WebFlow 2.0.9</a> sur le site de SpringSource<br />
- décompressez l&#8217;archive<br />
- ouvrez le répertoire projects/spring-webflow-samples/booking-faces<br />
- tapez <em>mvn eclipse:eclipse</em> pour créer un nouveau projet<br />
- ou sinon tapez <em>mvn idea:idea</em> pour créer un projet IDEA IntelliJ<br />
- ou enfin, si vous avez IDEA IntelliJ, celui-ci importe sans problème le pom.xml et vous prépare un projet configuré&#8230; Pas besoins de plugins.</p>
<p><strong>Faire tourner la démo en local</strong><br />
Pour faire fonctionner la version Spring en local, éditez le pom.xml et ajoutez Jetty dans la balise build/plugins comme ici:</p>
<pre class="brush:xml">   ...
   &lt;build&gt;
        &lt;finalName&gt;swf-booking-faces&lt;/finalName&gt;
        &lt;plugins&gt;
        	...

            &lt;plugin&gt;
                &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
                &lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;

        &lt;/plugins&gt;
    &lt;/build&gt;
    &lt;properties&gt;
        &lt;spring.version&gt;2.5.6.SEC01&lt;/spring.version&gt;
        &lt;jsf.version&gt;1.2.0.09&lt;/jsf.version&gt;
    &lt;/properties&gt;
&lt;/project&gt;</pre>
<p>Vous pourrez alors lancer la démo avec mvn jetty:run dans le répertoire de la démo de Spring.</p>
<h3>I.2) Configuration de la version Play! Framework</h3>
<p>Play! Framework se télécharge <a href="http://www.playframework.org/">sur le site de Play!</a>. Voici comment suivre mes explications pour la deuxième partie :<br />
- décompressez le zip dans un répertoire C:\Soft\play par exemple<br />
- ajoutez C:\Soft\play à votre PATH</p>
<p>Pour lancer l&#8217;application :<br />
- allez dans le répertoire C:\Soft\play\samples-and-tests\booking<br />
- tapez &laquo;&nbsp;<em>play run</em>&nbsp;&raquo; et connectez-vous sur http://localhost:9000/</p>
<p>Pour travailler avec Eclipse ou IDEA IntelliJ<br />
- allez dans le répertoire C:\Soft\play\samples-and-tests\booking<br />
- tapez <em>play eclipsify</em> pour créer un projet Eclipse<br />
- OU tapez <em>play idealize</em> pour créer un module IDEA IntelliJ<br />
c&#8217;est tout !</p>
<p><strong>I.3) Résultat du match :</strong></p>
<p>Facilité d&#8217;installation : match nul<br />
Qualité de la doc sur le site : match nul<br />
Création du projet dans IDEA IntelliJ : match nul<br />
Serveur : la démo Spring n&#8217;embarque pas de serveur, il a fallut ajouter Jetty pour tester alors que Play! Framework dispose de son propre serveur<br />
Temps de démarrage : avantage Play! qui démarre très rapidement en 2 secondes.</p>
<p><strong>Vainqueur : Play! Framework d&#8217;une courte longueur </strong></p>
<h2>II. Le modèle</h2>
<h3>II.1) Spécification fonctionnelle</h3>
<p>L&#8217;objectif de l&#8217;application est de réaliser un site de réservation d&#8217;hôtel. Pour cela, l&#8217;utilisateur peut chercher un hôtel, puis ensuite créer une réservation (Booking en Anglais).</p>
<p>L&#8217;utilisateur doit s&#8217;authentifier avant de pouvoir terminer sa réservation. Une entité User permet donc de gérer la sécurité facilement avec un moteur de persistence.</p>
<p>Nous utiliserons JPA et une base en mémoire pour les 2 versions. L&#8217;essentiel est que Play! Framework comme la version Spring, utilisent JPA. Donc les entités sont presque identiques.</p>
<h3>II.2) Une entité simple : l&#8217;Hotel</h3>
<p>Prenons tout d&#8217;abord l&#8217;entité Hotel qui représente un hôtel. Voici la version de la démo Spring Webflow/JSF :</p>
<pre class="brush:java">
package org.springframework.webflow.samples.booking;

import java.io.Serializable;
import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * Version Spring Web Flow. La sérialisation est nécessaire pour JSF.
 */
@Entity
public class Hotel implements Serializable {
    private static final long serialVersionUID = 4011346719502656269L;
    private Long id;
    private String name;
    private String address;
    private String city;
    private String state;
    private String zip;
    private String country;
    private BigDecimal price;

    @Id
    @GeneratedValue
    public Long getId() {
	return id;
    }

    public void setId(Long id) {
	this.id = id;
    }

    public String getName() {
	return name;
    }

    public void setName(String name) {
	this.name = name;
    }

    public String getAddress() {
	return address;
    }

    public void setAddress(String address) {
	this.address = address;
    }

    public String getCity() {
	return city;
    }

    public void setCity(String city) {
	this.city = city;
    }

    public String getZip() {
	return zip;
    }

    public void setZip(String zip) {
	this.zip = zip;
    }

    public String getState() {
	return state;
    }

    public void setState(String state) {
	this.state = state;
    }

    public String getCountry() {
	return country;
    }

    public void setCountry(String country) {
	this.country = country;
    }

    @Column(precision = 6, scale = 2)
    public BigDecimal getPrice() {
	return price;
    }

    public void setPrice(BigDecimal price) {
	this.price = price;
    }

    public Booking createBooking(User user) {
	return new Booking(this, user);
    }

    @Override
    public String toString() {
	return "Hotel(" + name + "," + address + "," + city + "," + zip + ")";
    }
}</pre>
<p>Voici la version Play! Framework :</p>
<pre class="brush:java">package models;

import play.db.jpa.*;
import play.data.validation.*;
import javax.persistence.*;
import java.math.*;

/**
 * Version Play! Framework
 */
@Entity
public class Hotel extends play.db.jpa.Model {

    @Required
    @MaxSize(50)
    public String name;

    @MaxSize(100)
    public String address;

    @Required
    @MaxSize(40)
    public String city;

    @Required
    @MaxSize(6)
    @MinSize(2)
    public String state;

    @Required
    @MaxSize(6)
    @MinSize(5)
    public String zip;

    @Required
    @MaxSize(40)
    @MinSize(2)
    public String country;

    @Column(precision=6, scale=2)
    public BigDecimal price;

    public String toString() {
        return "Hotel(" + name + "," + address + "," + city + "," + zip + ")";
    }

}</pre>
<p>Les différences entre les 2 versions :<br />
- Play! Framework étend la classe &laquo;&nbsp;play.db.jpa.Model&nbsp;&raquo; qui fournit le support JPA.<br />
- Les attributs sont publics dans la version Play!, ce qui logiquement évite des getters/setters comme dans la version Spring classique. Moi depuis que l&#8217;encapsulation n&#8217;est plus à la mode en soirée, j&#8217;ai arrêté.<br />
- La syntaxe JPA est un peu plus poussée dans la version Play! Nous verrons si cela permet d&#8217;améliorer l&#8217;expérience utilisateur dans l&#8217;interface graphique ou non.</p>
<p><del datetime="2010-05-14T05:57:30+00:00">Le bean de Spring n&#8217;étend pas une classe de base contrairement à Play!, ce qui permet d&#8217;étendre éventuellement Hotel. Mais est-ce que c&#8217;est quelque chose que nous faisons pour des Entities ? Je me pose la question. Perso je décourage l&#8217;héritage avec JPA. FBI = Fausse bonne idée.</del></p>
<p>[Update] Avec Play! Framework vous pouvez étendre la classe Model afin de simplifier la gestion JPA de l&#8217;entité. Cela fait partie des bonnes pratiques comme expliqué par Nicolas Leroux dans les commentaires. Pour en savoir plus, regardez <a href="http://www.playframework.org/documentation/1.0.2.1/jpa">la doc de la partie JPA de Play!<br />
</a></p>
<p>Play! gère l&#8217;identité dans la class Model avec un attribut Id de type Long par défaut. Si vous souhaitez gérer votre propre id, vous <del datetime="2010-05-14T05:57:30+00:00">devez</del> <em>pouvez</em> par exemple étendre la class <strong>JPASupport</strong> de Play!, puis simplement définir un attribut @Id comme d&#8217;habitude avec JPA. C&#8217;est tout à fait possible.</p>
<p>On voit que dans la version Spring, il y a une méthode &laquo;&nbsp;createBooking&nbsp;&raquo; qui permet de créer au niveau de l&#8217;Hotel une réservation.</p>
<p>Il n&#8217;y a donc pas de vainqueur dans cette partie pour moi. Les 2 approches se valent je pense. Je préfère la simplicité de Play! Framework qui remet en question quelques habitudes du monde Java, comme l&#8217;encapsulation systématique.</p>
<p>Par contre je n&#8217;aime pas trop l&#8217;approche de placer les annotations JPA sur les getters/setters plutôt que sur les attributs de la classe dans la version Spring. On perd beaucoup en lisibilité.</p>
<h3>II.3) Une entité plus compliquée : Booking</h3>
<p>Une réservation est l&#8217;association d&#8217;un User, d&#8217;un Hotel, d&#8217;une date d&#8217;arrivée et de départ et de différents autres attributs. Je vais faire exprès de vous donner la version complète des 2 frameworks, afin de vous montrer les différences flagrantes entre les 2 approches.</p>
<p>La version de la démo Spring WebFlow telle qu&#8217;elle est livrée, sans trucages, sans effets spéciaux :</p>
<pre class="brush:java">package org.springframework.webflow.samples.booking;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.validation.ValidationContext;

/**
 * A Hotel Booking made by a User.
 */
@Entity
public class Booking implements Serializable {

    private static final long serialVersionUID = 1171567558348174963L;

    private Long id;
    private User user;
    private Hotel hotel;
    private Date checkinDate;
    private Date checkoutDate;
    private String creditCard;
    private String creditCardName;
    private int creditCardExpiryMonth;
    private int creditCardExpiryYear;
    private boolean smoking;
    private int beds;
    private Amenity amenities;   // Absent de la version Play!

    public Booking() {
    }

    public Booking(Hotel hotel, User user) {
        this.hotel = hotel;
        this.user = user;
        Calendar calendar = Calendar.getInstance();
        setCheckinDate(calendar.getTime());
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        setCheckoutDate(calendar.getTime());
    }

    @Transient
    public BigDecimal getTotal() {
        return hotel.getPrice().multiply(new BigDecimal(getNights()));
    }

    @Transient
    public int getNights() {
        if (checkinDate == null || checkoutDate == null) {
            return 0;
        } else {
            return (int) (checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24;
        }
    }

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Basic
    @Temporal(TemporalType.DATE)
    public Date getCheckinDate() {
        return checkinDate;
    }

    public void setCheckinDate(Date datetime) {
        this.checkinDate = datetime;
    }

    @ManyToOne
    public Hotel getHotel() {
        return hotel;
    }

    public void setHotel(Hotel hotel) {
        this.hotel = hotel;
    }

    @ManyToOne
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Basic
    @Temporal(TemporalType.DATE)
    public Date getCheckoutDate() {
        return checkoutDate;
    }

    public void setCheckoutDate(Date checkoutDate) {
        this.checkoutDate = checkoutDate;
    }

    public String getCreditCard() {
        return creditCard;
    }

    public void setCreditCard(String creditCard) {
        this.creditCard = creditCard;
    }

    @Transient
    public String getDescription() {
        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
        return hotel == null ? null : hotel.getName() + ", " + df.format(getCheckinDate()) + " to "
                + df.format(getCheckoutDate());
    }

    public boolean isSmoking() {
        return smoking;
    }

    public void setSmoking(boolean smoking) {
        this.smoking = smoking;
    }

    public int getBeds() {
        return beds;
    }

    public void setBeds(int beds) {
        this.beds = beds;
    }

    public String getCreditCardName() {
        return creditCardName;
    }

    public void setCreditCardName(String creditCardName) {
        this.creditCardName = creditCardName;
    }

    public int getCreditCardExpiryMonth() {
        return creditCardExpiryMonth;
    }

    public void setCreditCardExpiryMonth(int creditCardExpiryMonth) {
        this.creditCardExpiryMonth = creditCardExpiryMonth;
    }

    public int getCreditCardExpiryYear() {
        return creditCardExpiryYear;
    }

    public void setCreditCardExpiryYear(int creditCardExpiryYear) {
        this.creditCardExpiryYear = creditCardExpiryYear;
    }

    @Transient
    public Amenity getAmenities() {
        return amenities;
    }

    public void setAmenities(Amenity amenities) {
        this.amenities = amenities;
    }

    public void validateEnterBookingDetails(ValidationContext context) {
        MessageContext messages = context.getMessageContext();
        if (checkinDate.before(today())) {
            messages.addMessage(new MessageBuilder().error().source("checkinDate").code(
                    "booking.checkinDate.beforeToday").build());
        } else if (checkoutDate.before(checkinDate)) {
            messages.addMessage(new MessageBuilder().error().source("checkoutDate").code(
                    "booking.checkoutDate.beforeCheckinDate").build());
        }
    }

    private Date today() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    @Override
    public String toString() {
        return "Booking(" + user + "," + hotel + ")";
    }

}</pre>
<p>Voyons la version Play! Framework de l&#8217;entité Booking maintenant :</p>
<pre class="brush:java">package models;

import play.db.jpa.*;
import play.data.validation.*;
import javax.persistence.*;
import java.util.*;
import java.text.*;
import java.math.*;

@Entity
public class Booking extends Model {

    @Required
    @ManyToOne
    public User user;

    @Required
    @ManyToOne
    public Hotel hotel;

    @Required
    @Temporal(TemporalType.DATE)
    public Date checkinDate;

    @Required
    @Temporal(TemporalType.DATE)
    public Date checkoutDate;

    @Required(message="Credit card number is required")
    @Match(value="^\\d{16}$", message="Credit card number must be numeric and 16 digits long")
    public String creditCard;

    @Required(message="Credit card name is required")
    @MinSize(value=3, message="Credit card name is required")
    @MaxSize(value=70, message="Credit card name is required")
    public String creditCardName;
    public int creditCardExpiryMonth;
    public int creditCardExpiryYear;
    public boolean smoking;
    public int beds;

    public Booking(Hotel hotel, User user) {
        this.hotel = hotel;
        this.user = user;
    }

    public BigDecimal getTotal() {
        return hotel.price.multiply( new BigDecimal( getNights() ) );
    }

    public int getNights() {
        return (int) ( checkoutDate.getTime() - checkinDate.getTime() ) / 1000 / 60 / 60 / 24;
    }

    public String getDescription() {
        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
        return hotel==null ? null : hotel.name +
            ", " + df.format( checkinDate ) +
            " to " + df.format( checkoutDate );
    }

    public String toString() {
        return "Booking(" + user + ","+ hotel + ")";
    }

}</pre>
<p>Tout d&#8217;abord il manque des choses dans la version Play! Framework, et on ne compare donc plus exactement la même chose. Notez l&#8217;absence de l&#8217;entité Amenity. Ensuite, la version Spring utilise une approche différente pour l&#8217;attribut @Id et spécifie le générateur alors que la version Play! hérite de ce que la super-classe Model propose.</p>
<p>Ce qui me dérange dans la version Spring c&#8217;est la présence de la méthode <em>validateEnterBookingDetails</em>. Celle-ci est intéressante fonctionnellement, mais dépose une dépendance vers MessageContext un peu trop forte à mon goût.</p>
<p>Regardez aussi la différence sur la validation du numéro de carte de paiement. La version Play! utilise un moteur simple similaire à Hibernate Validation, mais propriétaire à Play! Au contraire la version Spring ne précise rien, et on imagine donc que la validation des 16 digits se fera dans la vue&#8230; et pas dans le modèle.</p>
<p>Conclusion : j&#8217;ai de plus en plus de mal avec la sauce des getters/setters, surtout lorsque les entités dépasse les &laquo;&nbsp;HelloWorld&nbsp;&raquo; et que l&#8217;on commence à sortir des cas d&#8217;usages compliqués. Souvenez-vous de ce que je vous disais : pour résoudre des problèmes compliqués il faut des solutions simples&#8230;</p>
<h2>III. Le contrôleur</h2>
<p>Après avoir regardé 2 entités différentes pour le modèle, voyons maintenant la différence d&#8217;approche entre Spring WebFlow et Play! Framework. Je vais étudier le cas de l&#8217;affichage de la liste des Hôtels, lorsque l&#8217;utilisateur clique sur le bouton Search par exemple.</p>
<h3>III.1) Spring WebFlow</h3>
<p>L&#8217;approche de Spring WebFlow est la suivante : afin d&#8217;éviter d&#8217;écrire un controller classique, Spring propose de définir les chemins logiques de navigation en XML, et d&#8217;associer directement des méthodes sur des services pour récupérer la partie Model. Cette approche a l&#8217;avantage de simplifier le développement de workflow webs complexes. Je vais vous présenter le concept.</p>
<p>Pour commencer, nous définissions un flow en XML pour l&#8217;action qui affiche la liste des Hotel correspondant à un critère de recherche. Je ne vous montre que la view-state &laquo;&nbsp;reviewHotels&nbsp;&raquo; afin de ne se concentrer que sur l&#8217;exemple :</p>
<p>&laquo;&nbsp;<em>main-flow.xml</em>&nbsp;&raquo;</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"&gt;

	&lt;var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" /&gt;

	&lt;view-state id="enterSearchCriteria"&gt;
		// Effacé pour simplifier l'exemple...
	&lt;/view-state&gt;

	&lt;view-state id="reviewHotels"&gt;
		&lt;on-render&gt;
			&lt;evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" result-type="dataModel" /&gt;
		&lt;/on-render&gt;
        &lt;transition on="sort"&gt;
            &lt;set name="searchCriteria.sortBy" value="requestParameters.sortBy" /&gt;
            &lt;render fragments="hotels:searchResultsFragment" /&gt;
        &lt;/transition&gt;
		&lt;transition on="previous"&gt;
			&lt;evaluate expression="searchCriteria.previousPage()" /&gt;
			&lt;render fragments="hotels:searchResultsFragment" /&gt;
		&lt;/transition&gt;
		&lt;transition on="next"&gt;
			&lt;evaluate expression="searchCriteria.nextPage()" /&gt;
			&lt;render fragments="hotels:searchResultsFragment" /&gt;
		&lt;/transition&gt;
		&lt;transition on="select" to="reviewHotel"&gt;
			&lt;set name="flowScope.hotel" value="hotels.selectedRow" /&gt;
		&lt;/transition&gt;
		&lt;transition on="changeSearch" to="changeSearchCriteria" /&gt;
	&lt;/view-state&gt;</pre>
<p><strong>Le point fort de Spring WebFlow/JSF ici :</strong> il sera possible de ne redessiner qu&#8217;une partie de l&#8217;interface. En effet, vous avez noté le tag &lt;render fragments=&nbsp;&raquo;"/&gt; ? Grâce à ce système très pratique avec Spring WebFlow et JSF, si vous avez une partie cliente en Ajax il devient alors possible de ne redéfinir qu&#8217;une partie de l&#8217;interface.</p>
<p>Dans la démo Play! Booking, ce mécanisme est implémenté &laquo;&nbsp;à la main&nbsp;&raquo; dans la page index.html. Tout est fait avec du jQuery et le tag jsAction de Play!, qui appelle des actions du controller Play. Celui-ci retourne alors des fragments de HTML, ce qui fait que la version Play! est aussi ajaxisé. Je reconnais que c&#8217;est moins évident et facile, mais les 2 se discutent.</p>
<p>Il y a donc un BookingService avec une méthode <strong>findHotels</strong> pour rechercher la liste des hôtels, d&#8217;après le Flow XML. Il s&#8217;agit d&#8217;une interface, ce qui permet de changer l&#8217;implémentation. Dans notre cas nous n&#8217;aurons que la version JPA. Si vous avez une forte envie de faire une version <em>PasJPA</em> notez que c&#8217;est super utile&#8230;</p>
<pre class="brush:java">public interface BookingService {
   // j'ai effacé les autres méthodes ici pour ne garder que l'essentiel

    public List&lt;hotel&gt; findHotels(SearchCriteria criteria);

}</pre>
<p>Le service implémente l&#8217;interface, j&#8217;ai supprimé une bonne partie du code afin de ne vous laissez que ce qui nous intéresse. Mais croyez-moi, la version complète est assez verbeuse. Ce qui nous intéresse ici c&#8217;est uniquement la méthode <em>findHotels</em></p>
<pre class="brush:java">@Service("bookingService")
@Repository
public class JpaBookingService implements BookingService {

    private EntityManager em;

    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

   // Note : j'ai effacé du code ici pour ne garder que quelques méthodes

    @Transactional(readOnly = true)
    @SuppressWarnings("unchecked")
    public List findHotels(SearchCriteria criteria) {
        String pattern = getSearchPattern(criteria);
        return em.createQuery(
                "select h from Hotel h where lower(h.name) like " + pattern + " or lower(h.city) like " + pattern
                        + " or lower(h.zip) like " + pattern + " or lower(h.address) like " + pattern + " order by h."
                        + criteria.getSortBy()).setMaxResults(criteria.getPageSize()).setFirstResult(
                criteria.getPage() * criteria.getPageSize()).getResultList();
    }

   // Note 2 : j'ai effacé du code ici pour ne garder que quelques méthodes

   // helpers
   private String getSearchPattern(SearchCriteria criteria) {
        if (StringUtils.hasText(criteria.getSearchString())) {
            return "'%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
        } else {
            return "'%'";
        }
    }

}</pre>
<p>Le plus intéressant est donc la méthode findHotels. Elle permet d&#8217;effectuer la recherche, de retourner une List d&#8217;Hotel à la vue, que nous verrons tout à l&#8217;heure si vous êtes toujours motivé.</p>
<h3>III.2) Le contrôleur version Play! Framework</h3>
<p>L&#8217;approche de Play! est un peu plus simple mais demande un peu plus de code Java.<br />
Je précise tout de suite : j&#8217;ai modifié l&#8217;exemple afin de retirer la partie Authentification et pour ne me concentrer que sur le Use-Case de récupérer la liste des Hotel correspondant à un critère entré dans l&#8217;interface utilisateur.</p>
<pre class="brush:java">public class Hotels extends Controller {

    public static void list(String search, Integer size, Integer page) {
        List hotels = null;
        page = page != null ? page : 1;
        if(search.trim().length() == 0) {
            hotels = Hotel.all().fetch(page, size);
        } else {
            search = search.toLowerCase();
            hotels = Hotel.find("lower(name) like ? OR lower(city) like ?", "%"+search+"%", "%"+search+"%").fetch(page, size);
        }
        render(hotels, search, size, page);
    }
   ...
    // Note : code effacé pour ne conserver que la méthode list
   ...
}</pre>
<p>L&#8217;approche de Play! Framework est donc la suivante :<br />
- écrire une classe dans le répertoire &laquo;&nbsp;controllers&nbsp;&raquo; qui étend la class Controller de Play!<br />
- écrire une méthode public static avec en argument les paramètres de la vue. Play! se charge de vous récupérer ce que l&#8217;utilisateur a entré. Notez ensuite l&#8217;appel pour récupérer la liste des Hotels :</p>
<pre class="brush:java">            search = search.toLowerCase();
            hotels = Hotel.find("lower(name) like ? OR lower(city) like ?", "%"+search+"%", "%"+search+"%").fetch(page, size);</pre>
<p>La méthode find est une méthode statique définie dans la classe JPASupport. Elle permet d&#8217;exécuter des requêtes JPA. Vous pouvez aussi écrire une méthode dans l&#8217;entité Hotel pour éviter de placer ici du code technique par exemple. Les 2 approches se valent.</p>
<h3>III.3) Différence d&#8217;approche</h3>
<p>La version Spring WebFlow demande plus de XML, ce qui personnellement me dérange. Je trouve que la définition des flows n&#8217;est pas simple. C&#8217;est même une fausse bonne idée. Je préfère une approche fortement typée en Java, où par contre pour que la magie opère, je dois étendre des classes spécialisées de Play! Framework.</p>
<p>Côté test, il est assez simple de <a href="http://static.springsource.org/spring-webflow/docs/2.0.x/reference/htmlsingle/spring-webflow-reference.html#testing">tester Spring WebFlow</a>, mais je n&#8217;ai pas testé personnellement.</p>
<p>Je vais être méchant avec Spring WebFlow : je trouve cela bien compliqué pour résoudre un problème simple. Ici quel est l&#8217;apport du XML ? Des annotations ? Est-ce que notre vie est plus simple grâce à ce système ? Permettez-moi d&#8217;en douter.</p>
<p>C&#8217;est peut-être une révolution par rapport à l&#8217;approche Struts, mais tant qu&#8217;à faire la révolution, il ne faut pas s&#8217;arrêter à un concept basé sur un fichier XML pour définir la navigation d&#8217;une application Web.</p>
<h3>III. 4) Synthèse</h3>
<h4>Avantages de Spring Web Flow</h4>
<p>- possibilité de déclarer en quelques lignes un bout de code pour que la vue récupère le Model sans devoir définir un controller.<br />
- gestion de la navigation de l&#8217;utilisateur fine dans le site<br />
- se repose sur des Services facile à tester pour s&#8217;assurer que le Model est correct<br />
- bien meilleur que l&#8217;approche classique où les DAO dans les Services ne servent à rien<br />
- Spring MVC récupère les paramètres de la vue et les dénormalise, ce qui est très pratique.<br />
- bonne intégration de la sécurité</p>
<h4>Inconvénients de Spring Web Flow</h4>
<p>- clairement plus compliqué que Play! sur ce point<br />
- XML tu aimes ou tu n&#8217;aimes pas, mais c&#8217;est <strong>ton</strong> environnement de développement Web<br />
- gestion pas facile pour les débutants entre les view-states, les action-states, les transitions etc.<br />
- l&#8217;EntityManager à la main dans le service : pas top. Mais c&#8217;est quelque chose qui est souvent factorisé dans des classes de GenericService par exemple, avec un DAO&#8230; Bref encore 3 ou 4 classes Java en plus.</p>
<h4>Avantages de Play! Framework :</h4>
<p>- le controlleur déclare des méthodes static et public qui deviennent autant d&#8217;URL dans la vue<br />
- le framework se charge de récupérer et dénormaliser les paramètres de la vue<br />
- approche full java<br />
- les entités ont un moteur comme GORM en Grails mais plus simple. Cela permet d&#8217;avoir des finders comme méthode statique sur l&#8217;entité Hotel. C&#8217;est cependant statique et plus limité que Grails/GORM.</p>
<h4>Inconvénients de Play! Framework :</h4>
<p>- le controller de base étend une class de Play! (si la spécialisation vous dérange plutôt que la composition)<br />
- la gestion des workflows compliqué demande un effort de développement par rapport à Spring WebFlow, qui sera capable de retomber sur ses pieds.</p>
<h2>IV. La Vue</h2>
<p>Je vais maintenant évaluer plusieurs critères :<br />
- la création d&#8217;une page pour chacune des technos<br />
- la qualité de l&#8217;expérience utilisateur avec l&#8217;utilisation d&#8217;Ajax<br />
- la taille des pages webs et les temps de chargement</p>
<h3>IV.1) Créer une page avec Spring Faces</h3>
<p>Basé sur JSF, cette partie sera donc essentiellement une discussion sur JSF plutôt que sur Spring. Je parlerai un peu de la taglibs de Spring pour la partie validation du côté client, que je trouve très bien fait. Mais l&#8217;essentiel du débat porte plus sur JSF ici.</p>
<p>Dans le projet Spring Webflow, les pages sont construites à partir d&#8217;un template, avec la technologie Facelets. Très pratique, cela vous permet de construire le canevas de votre site, puis de spécialiser vos vues en écrivant peu de code.</p>
<p>Le template standard.xhtml :</p>
<pre class="brush:html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;f:view xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
	  xmlns:c="http://java.sun.com/jstl/core"
	  xmlns:sf="http://www.springframework.org/tags/faces"
	  contentType="text/html" encoding="UTF-8"&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
	&lt;title&gt;Spring Faces: Hotel Booking Sample Application&lt;/title&gt;

	&lt;sf:includeStyles/&gt;
	&lt;sf:resourceGroup&gt;
		&lt;sf:resource path="/css-framework/css/tools.css"/&gt;
		&lt;sf:resource path="/css-framework/css/typo.css"/&gt;
		&lt;sf:resource path="/css-framework/css/forms.css"/&gt;
		&lt;sf:resource path="/css-framework/css/layout-navtop-localleft.css"/&gt;
		&lt;sf:resource path="/css-framework/css/layout.css"/&gt;
	&lt;/sf:resourceGroup&gt;
	&lt;sf:resource path="/styles/booking.css"/&gt;
	&lt;ui:insert name="headIncludes"/&gt;
&lt;/head&gt;
&lt;body class="tundra spring"&gt;
&lt;div id="page"&gt;
	&lt;div id="header" class="clearfix spring"&gt;
		&lt;div id="welcome"&gt;
			&lt;div class="left"&gt;Spring Travel: A Spring Faces Reference Application&lt;/div&gt;
			&lt;div class="right"&gt;
				&lt;c:if test="${not empty currentUser.name}"&gt;
	            	Welcome, ${currentUser.name} | &lt;a href="${request.contextPath}/spring/logout"&gt;Logout&lt;/a&gt;
				&lt;/c:if&gt;
				&lt;c:if test="${empty currentUser.name}"&gt;
	            	&lt;a href="${request.contextPath}/spring/login"&gt;Login&lt;/a&gt;
				&lt;/c:if&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id="branding" class="spring"&gt;
			&lt;a href="#{request.contextPath}"&gt;&lt;img src="${request.contextPath}/resources/images/header.jpg" alt="Spring Travel"/&gt;&lt;/a&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;div id="content" class="clearfix spring"&gt;
		&lt;div id="local" class="spring"&gt;
			&lt;a href="http://www.thespringexperience.com"&gt;
				&lt;img src="${request.contextPath}/resources/images/diplomat.jpg" alt="generic hotel" /&gt;
			&lt;/a&gt;
			&lt;a href="http://www.thespringexperience.com"&gt;
				&lt;img src="${request.contextPath}/resources/images/tse.gif" alt="The Spring Experience" /&gt;
			&lt;/a&gt;
			&lt;p&gt;
			&lt;/p&gt;
		&lt;/div&gt;
		&lt;div id="main"&gt;
			&lt;ui:insert name="content"/&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;div id="footer" class="clearfix spring"&gt;
		&lt;a href="http://www.springframework.org"&gt;&lt;img src="${request.contextPath}/resources/images/powered-by-spring.png" alt="Powered by Spring" /&gt;&lt;/a&gt;
	&lt;/div&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;/f:view&gt;</pre>
<p>La page &laquo;&nbsp;reviewHotels.xhtml&nbsp;&raquo; avec 52 balises HTML+JSF permet d&#8217;afficher la liste des Hôtels :</p>
<pre class="brush:html">&lt;!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;ui:composition xmlns="http://www.w3.org/1999/xhtml"
	    		xmlns:ui="http://java.sun.com/jsf/facelets"
	  			xmlns:h="http://java.sun.com/jsf/html"
	  			xmlns:f="http://java.sun.com/jsf/core"
	  			xmlns:sf="http://www.springframework.org/tags/faces"
				template="/WEB-INF/layouts/standard.xhtml"&gt;

&lt;ui:define name="content"&gt;

&lt;h:form id="hotels"&gt;
	&lt;div class="section"&gt;
		&lt;h2&gt;Hotel Results&lt;/h2&gt;
		&lt;p&gt;
			&lt;sf:commandLink value="Change Search" action="changeSearch"/&gt;
		&lt;/p&gt;
		&lt;ui:fragment id="searchResultsFragment"&gt;
			&lt;div id="searchResults"&gt;
				&lt;h:outputText id="noHotelsText" value="No Hotels Found" rendered="#{hotels.rowCount == 0}"/&gt;
				&lt;h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="h" rendered="#{hotels.rowCount &gt; 0}"&gt;
					&lt;h:column&gt;
						&lt;f:facet name="header"&gt;
							&lt;sf:commandLink id="sortByNameLink" action="sort" value="Name" processIds="*"&gt;
								&lt;f:param name="sortBy" value="name" /&gt;
							&lt;/sf:commandLink&gt;
						&lt;/f:facet&gt;
						#{h.name}
					&lt;/h:column&gt;
					&lt;h:column&gt;
						&lt;f:facet name="header"&gt;Address&lt;/f:facet&gt;
						#{h.address}
					&lt;/h:column&gt;
					&lt;h:column&gt;
						&lt;f:facet name="header"&gt;
							&lt;sf:commandLink id="sortByCity" action="sort" value="City, State" processIds="*" &gt;
								&lt;f:param name="sortBy" value="city" /&gt;
							&lt;/sf:commandLink&gt;
						&lt;/f:facet&gt;
						#{h.city}, #{h.state}, #{h.country}
					&lt;/h:column&gt;
					&lt;h:column&gt;
						&lt;f:facet name="header"&gt;Zip&lt;/f:facet&gt;
						#{h.zip}
					&lt;/h:column&gt;
					&lt;h:column&gt;
						&lt;f:facet name="header"&gt;Action&lt;/f:facet&gt;
						&lt;sf:commandLink id="viewHotelLink" value="View Hotel" action="select"/&gt;
					&lt;/h:column&gt;
				&lt;/h:dataTable&gt;
				&lt;div class="buttonGroup"&gt;
					&lt;sf:commandLink id="previousPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page &gt; 0}"/&gt;
					&lt;sf:commandLink id="nextPageLink" value="More Results" action="next" rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/ui:fragment&gt;
	&lt;/div&gt;
&lt;/h:form&gt;
&lt;/ui:define&gt;
&lt;/ui:composition&gt;</pre>
<p>Ce que j&#8217;apprécie à titre personnel avec JSF :<br />
- possibilité d&#8217;écrire du code de mise en forme sans avoir besoin de faire trop de CSS<br />
- moteur de construction de page assez proche d&#8217;une vue client lourd<br />
- possibilité d&#8217;écrire avec la syntaxe JSF et d&#8217;avoir un rendu riche sans se prendre la tête avec du Javascript ou des feuilles de style.<br />
&lt;HUMOUR&gt;De toutes les façons, je suis pas développeur Web. Donc mort aux CSS&#8230;&lt;/HUMOUR&gt;</p>
<p>Ce qui me fait un peu tiquer, c&#8217;est que l&#8217;on dit au développeur Java : tu n&#8217;auras pas besoin d&#8217;apprendre à faire une mise en page compliquée en HTML et CSS&#8230;</p>
<p>Mais bon, vous vous foutez pas un peu de nous là ?</p>
<p>La page demande 52 balises. Et ce dataTable pourrait très bien être un simple TABLE en HTML avec une CSS non ? Ce qui d&#8217;ailleurs est le cas au final non ?</p>
<h3>IV.2) Créer une page avec Play! Framework</h3>
<p>Attention cela pique les yeux. Comme JSF ou Wicket, vous pouvez utiliser un éditeur HTML pour construire votre page. En effet, le format des pages de Play! Framework est très original <strong>puisque c&#8217;est du HTML</strong> ni plus, ni moins. Il y a cependant l&#8217;utilisation de Groovy qui risque de faire peur à quelques uns. Je note cela comme un inconvénient par rapport à JSF.</p>
<p>La version livrée avec Play! utilise jQuery et Ajax à fond. Il y a en fait une page principale, puis un ensemble de fonction Javascript pour ne charger rapidement que ce qui change dans un DIV au format HTML. C&#8217;est radicalement différent, et peut-être moins facile d&#8217;abord pour des gens n&#8217;ayant jamais fait de Web. Je vous montre donc plutôt ici ma version &laquo;&nbsp;<em>gars qui a fait du Java et du Web et qui découvre Play</em>&nbsp;&raquo;</p>
<p>Play! Framework dispose aussi d&#8217;un moteur de template. Je vais donc vous montrer 2 fichiers. Le fichier main.html est un template de base que j&#8217;utilise pour le site :</p>
<pre class="brush:html">&lt;!DOCTYPE html&gt;

&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;#{get 'title' /}&lt;/title&gt;
        &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;
        &lt;link rel="stylesheet" type="text/css" media="screen" href="@{'/public/stylesheets/main.css'}"&gt;
        #{get 'moreStyles' /}
        &lt;link rel="shortcut icon" type="image/png" href="@{'/public/images/favicon.png'}"&gt;
        &lt;script src="@{'/public/javascripts/jquery-1.3.2.min.js'}" type="text/javascript" charset="utf-8"&gt;&lt;/script&gt;
        &lt;script src="@{'/public/javascripts/sessvars.js'}" type="text/javascript" charset="utf-8"&gt;&lt;/script&gt;
        #{get 'moreScripts' /}
    &lt;/head&gt;
    &lt;body&gt;

        &lt;div id="header"&gt;
            &lt;h1&gt;play framework booking demo&lt;/h1&gt;
            #{if user?.id}
                &lt;div id="options"&gt;
                    Connected as ${user.username}
                    |
                    &lt;a href="@{Hotels.index()}"&gt;Search&lt;/a&gt;
                    |
                    &lt;a href="@{Hotels.settings()}"&gt;Settings&lt;/a&gt;
                    |
                    &lt;a href="@{Application.logout()}"&gt;Logout&lt;/a&gt;
                &lt;/div&gt;
            #{/if}
        &lt;/div&gt;

        &lt;div id="content"&gt;
            #{if flash.error}
                &lt;p class="fError"&gt;
                    &lt;strong&gt;${flash.error}&lt;/strong&gt;
                &lt;/p&gt;
            #{/if}
            #{if flash.success}
                &lt;p class="fSuccess"&gt;
                    &lt;strong&gt;${flash.success}&lt;/strong&gt;
                &lt;/p&gt;
            #{/if}

            #{doLayout /}

        &lt;/div&gt;

        &lt;div id="footer"&gt;
            Created with &lt;a href="http://www.playframework.org"&gt;play framework&lt;/a&gt; and really inspirated from the booking sample application provided by &lt;a href="http://seamframework.org/"&gt;seam framework&lt;/a&gt;
        &lt;/div&gt;

    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Voici la page qui affiche la liste des Hotels. Le fichier s&#8217;appelle &laquo;&nbsp;list.html&nbsp;&raquo; comme le nom de la méthode <em>list</em> du Controller Hotels que nous avons vu plus haut. Il est bien entendu possible de déclarer un nom différent et de configurer une autre route avec Play! Framework.</p>
<p>Le fichier est assez simple : il reçoit un objet List&lt;Hotel&gt;, il itère en Groovy avec un tag spécifique à Play et il affiche le résultat dans un tableau HTML :</p>
<pre class="brush:html">
#{extends 'main.html' /}
#{set title:'Search result'/}

#{if hotels}
&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;th&gt;Name&lt;/th&gt;
        &lt;th&gt;Address&lt;/th&gt;
        &lt;th&gt;City, State&lt;/th&gt;
        &lt;th width="8%"&gt;Zip&lt;/th&gt;
        &lt;th width="13%"&gt;Action&lt;/th&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
    #{list hotels, as:'hotel'}
    &lt;tr&gt;
        &lt;td&gt;${hotel.name}&lt;/td&gt;
        &lt;td&gt;${hotel.address}&lt;/td&gt;
        &lt;td&gt;${hotel.city}, ${hotel.state}, ${hotel.country}&lt;/td&gt;
        &lt;td&gt;${hotel.zip}&lt;/td&gt;
        &lt;td&gt;
            &lt;a href="@{show(hotel.id)}"&gt;View Hotel&lt;/a&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    #{/list}
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
    &lt;a id="nextPage" href="${page+1}"&gt;More results&lt;/a&gt;
&lt;/p&gt;
#{/if}

#{else}
&lt;p&gt;
    No more results
&lt;/p&gt;
#{/else}</pre>
<p>La version Play! est très dépouillée. L&#8217;inconvénient : il sera nécessaire dans les 2 cas (JSF comme Play!) d&#8217;apprendre la technologie de rendu et les tags pour travailler efficacement. Mais Play! n&#8217;est pas orienté composant comme JSF. Il n&#8217;y a pas d&#8217;utilisation de l&#8217;Expression Language, ici c&#8217;est Groovy. Ce moteur Groovy est un poil plus lent que <a href="http://www.playframework.org/modules/japid">Japid</a>, un autre moteur Java qui est disponible pour Play!</p>
<p>Regardez aussi <a href="http://www.playframework.org/modules">la liste des modules de Play! Framework</a>. Il y a du lourd comme le support de Scala, le moteur NoSQL MongoDB, Guice, GWT ou le module Search avec Lucene (comme Hibernate Search en plus simple).</p>
<p>Un inconvénient de Play! pour les personnes qui n&#8217;ont jamais fait de Web : la mise en page et la partie CSS. Lorsque je monte un projet avec Play! Framework, j&#8217;utilise par exemple <a href="http://960.gs/">CSS 960 grid system</a>. Je connais ces systèmes car j&#8217;ai un gros background Web. Pour le CSS, pour sélectionner des couleurs qui ne font pas vomir l&#8217;utilisateur, j&#8217;ai pleins d&#8217;outils comme <a href="http://kuler.adobe.com/">Kuler</a> d&#8217;Adobe pour préparer des styles&#8230; Donc pour moi qui suit très Web : je peux faire un truc joli avec Play! Framework. Je pourrai styliser mes tableaux sans soucis. Je pense que ce qui est bien avec JSF, c&#8217;est que cela vous aide à monter vos pages facilement, à construire vos formulaires ou vos tableaux sans devoir devenir une bête en HTML/CSS. Mais c&#8217;est un peu dommage, lorsque l&#8217;on voit le potentiel d&#8217;HTML 5 pour les années qui viennent.</p>
<h3>IV.3) Expérience utilisateur</h3>
<p>J&#8217;ai lancé les 2 applications et j&#8217;ai effectué une comparaison en tant qu&#8217;utilisateur. Je donne l&#8217;avantage à la version Spring Faces. Je trouve que la librairie de Spring de validation du côté client est très sympa.</p>
<p>En terme de rapidité, la version Play! Framework est vraiment plus réactive. Si je clique comme un dingue avec un script Selenium, la version Spring WebFlow est à la peine alors que la version Play! se tourne les pouces sans s&#8217;essoufler.</p>
<h3>IV.5) Taille des pages Webs</h3>
<p>La page d&#8217;affichage de la liste des Hôtels sur Spring WebFlow (cliquez sur l&#8217;image pour l&#8217;afficher en grand) :<br />
<a href="http://www.touilleur-express.fr/wp-content/page_spring_webflow_result.jpg"><img class="alignnone size-medium wp-image-3739" title="page_spring_webflow_result" src="http://www.touilleur-express.fr/wp-content/page_spring_webflow_result-300x236.jpg" alt="" width="300" height="236" /></a></p>
<p>La version Play! Framework :<br />
<a href="http://www.touilleur-express.fr/wp-content/page_hotels_play.jpg"><img class="alignnone size-medium wp-image-3740" title="page_hotels_play" src="http://www.touilleur-express.fr/wp-content/page_hotels_play-300x261.jpg" alt="" width="300" height="261" /></a></p>
<p>Mes tests avec YSlow en effectuant 10 chargements de la page puis en prenant la moyenne :</p>
<p><strong>Moyenne des temps de chargement de la page liste des Hotels pour 10 hotels:</strong><br />
- Play! Framework en mode Dev ou Prod : 0,234 secondes<br />
- Spring WebFlow avec Jetty : 1.286 secondes<br />
- Spring WebFlow avec Tomcat 6.0.20 : 1.092 secondes</p>
<p>Le mode Prod de Play! ne prend qu&#8217;un peu plus de temps à démarrer, mais je n&#8217;ai pas constaté de différence une fois le serveur lancé.</p>
<p><strong>Volume de la partie HTML sans CSS/Images et temps de chargement :</strong><br />
Si je ne regarde que la partie HTML sans prendre en compte le temps de chargement des images, je teste réellement que la partie serveur.</p>
<p>Play! Framework : chargement de 3.1 kb en un temps moyen de 14ms<br />
Tomcat+Spring : chargement de 14kb en un temps moyen de 52 ms</p>
<p>Donc pour un affichage similaire, vous voyez le souci ? <strong>la version Spring Faces de cette démonstration est 5 fois plus lourde et demande 4 à 5 fois plus de temps</strong>. Je ne dis pas qu&#8217;en général c&#8217;est le cas, mais pour notre exemple oui c&#8217;est le cas. Et nous sommes sur le même cahier des charges : afficher dans un tableau une liste d&#8217;Hôtel.</p>
<h2>V. Conclusion</h2>
<p>Si vous avez pris le temps de lire cet énorme article jusqu&#8217;au bout, merci. Revenez voir le code des deux version en détail. Téléchargez chacune des versions et donnez vos propres arguments techniques en faveur de l&#8217;un ou de l&#8217;autre.</p>
<p>J&#8217;ai envie de taper du poing sur la table : <strong>il est temps de revoir le développement Web en Java</strong>.<br />
Le développement Web demande des compétences. Si vous ne les avez pas, ne prenez pas une techno pour couvrir vos lacunes. Apprenez à faire du Web. Désolé, le XML ne m&#8217;excite pas. Play! est plus facile à apprendre que toute la stack Spring que je vous ai présenté. Car elle est plus simple et tout aussi puissante.</p>
<p>Pour construire une application Web compliquée ou d&#8217;entreprise, est-ce que dans 5 ans nous ferrons toujours du JSF ? ou est-ce que nous ferrons du HTML+CSS+jQuery ? Je pose la question. Evidemment, Play! Framework doit encore faire ses preuves et on peut me retourner l&#8217;argument. Mais c&#8217;est plus simple, plus réaliste et plus facile à maintenir.</p>
<p>Le point faible de Play! par rapport à un framework comme Spring Faces+Spring WebFlow+JSF c&#8217;est qu&#8217;il faut plus d&#8217;efforts pour construire ses composants dans la partie vue. D&#8217;un autre côté, lorsque vous avez un framework aussi puissant que JSF, vous avez envie de prendre des tableaux avancés, des richTables, ou des composants plus puissants. Cela entraîne parfois le risque de prendre des composants qui font trop par rapport à un tableau simple. D&#8217;ailleurs, si vous ne preniez pas ces composants, quel intérêt à utiliser une librairie JSF ? Je pose la question.</p>
<p>Un risque est donc d&#8217;utiliser des composants riches trop facilement dans une application Web avec JSF. Vous vous retrouvez avec un tableau avec des colonnes triables, alors que vous n&#8217;en n&#8217;avez pas besoin. Et votre page pèse 15-20kb au lieu de peser 2-5kb, et demande de la mémoire et du CPU du côté serveur.</p>
<p>Le site &laquo;&nbsp;<a href="http://www.express-board.fr/">eXpress-Board</a>&nbsp;&raquo; tourne sur la même machine que le blog &laquo;&nbsp;Le Touilleur Express&nbsp;&raquo; avec 3 parts chez Gandi, soit 768Mo. Le process Java tourne avec 128 Mo de mémoire, et prend entre 5 et 16% de l&#8217;utilisation de la machine, bien loin de MySQL qui est très sollicité par WordPress pour le Blog.</p>
<p>Je vais me faire taper par les maîtres Javas qui ne vont pas être d&#8217;accord. Mais c&#8217;est la première fois où j&#8217;en ai rien à faire, car je suis sûr de mes arguments.</p>
<p>Allez SuperTroll, sort du bois, je t&#8217;attends.</p>
<p>On va bien s&#8217;amuser&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2010/05/13/spring-faceswebflowjava-classique-compare-a-play-framework/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>Java et les frameworks Webs : une longue histoire compliquée</title>
		<link>http://www.touilleur-express.fr/2010/05/01/java-et-les-frameworks-webs-une-longue-histoire-compliquee/</link>
		<comments>http://www.touilleur-express.fr/2010/05/01/java-et-les-frameworks-webs-une-longue-histoire-compliquee/#comments</comments>
		<pubDate>Sat, 01 May 2010 21:45:38 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.touilleur-express.fr/?p=3648</guid>
		<description><![CDATA[&#160;
Imaginons que vous êtes votre framework Web Java favori&#8230; Disons que vous habitez dans une maison, qui représente votre framework Web Java.
Fermez les yeux&#8230; visualisez une petite usine qui fume avec 345 tuyaux, plusieurs portes d&#8217;entrées, des grillages à certains endroits, une pelouse fatiguée, un panneau &#171;&#160;Attention, Chien Dangereux (et Con)&#171;&#160;, des panneaux solaires qui ne sont pas raccordés, un autocollant &#171;&#160;Java 7 Rulez&#160;&#187; et des empilements de briques&#8230; Il y a souvent des coupures, des problèmes d&#8217;allocations de ressources, des débordements de pile. Lorsque vous voulez fermer les volets, ...]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<div id="attachment_5445" class="wp-caption alignleft" style="width: 250px"><a href="http://www.touilleur-express.fr/wp-content/uploads/2010/05/complexity.jpg"><img class="size-full wp-image-5445" title="complexity" src="http://www.touilleur-express.fr/wp-content/uploads/2010/05/complexity.jpg" alt="" width="240" height="240" /></a><p class="wp-caption-text">Crédit photo michael.heiss Licence Commons Creatives 2.0</p></div>
<p>Imaginons que vous êtes votre framework Web Java favori&#8230; Disons que vous habitez dans une maison, qui représente votre framework Web Java.</p>
<p>Fermez les yeux&#8230; visualisez une petite usine qui fume avec 345 tuyaux, plusieurs portes d&#8217;entrées, des grillages à certains endroits, une pelouse fatiguée, un panneau &laquo;&nbsp;<em>Attention, Chien Dangereux (et Con)</em>&laquo;&nbsp;, des panneaux solaires qui ne sont pas raccordés, un autocollant &laquo;&nbsp;<em>Java 7 Rulez</em>&nbsp;&raquo; et des empilements de briques&#8230; Il y a souvent des coupures, des problèmes d&#8217;allocations de ressources, des débordements de pile. Lorsque vous voulez fermer les volets, vous devez relancer le groupe électrogène. Pour ajouter une chambre supplémentaire, vous avez fait poser une extension sur le toit&#8230;</p>
<p>Un jour, un gars vient sonner chez vous. Vous ouvrez la porte et il vous dit : &laquo;&nbsp;<em>Bonjour, moi je m&#8217;appelle PHP, j&#8217;ai l&#8217;air moins sérieux que toi, mais je fais tourner de gros sites Webs</em>&laquo;&nbsp;. Et toi, tu le regardes comme un hippie Baba-Cool bien gentil, mais au final tu lui lances un &laquo;&nbsp;<em>t&#8217;es incapable de monter en charge</em>&laquo;&nbsp;.<br />
Vlam, tu refermes la porte.</p>
<p>Le lendemain, un autre gars vient te voir et te tape sur l&#8217;épaule : &laquo;&nbsp;<em>Bonjour, moi c&#8217;est Ruby on Rails. Je t&#8217;éclate en productivité et en plus mes développeurs s&#8217;amusent</em>&laquo;&nbsp;. Là tu lui ris très fort au nez et tu lui dis : &laquo;&nbsp;<em>Ouais mais Ruby c&#8217;est pas comme le Latin ? Une langue morte ?</em>&laquo;&nbsp;. Vlam, et tu lâches le chien pour voir s&#8217;il a vraiment des soucis de montée en charge.</p>
<p>Le surlendemain, un mec qui semble avoir fumé un arbre sonne à ta porte. Il porte un teeshirt &laquo;&nbsp;NE TIREZ PAS : JE TOURNE SUR LA JVM&nbsp;&raquo;.<br />
C&#8217;est Mr Grails.<br />
Fier comme un pape : &laquo;&nbsp;<em>Salut, moi c&#8217;est Grails. Je suis enfin là pour t&#8217;apporter de la productivité, je suis en Groovy et je tourne sur la JVM&#8230; Gentil&#8230; pas tirer&#8230;</em>&laquo;&nbsp;. Et toi de répondre : &laquo;&nbsp;<em>Grails c&#8217;est pas si performant en production, il faut apprendre Groovy, et en plus tu portes un teeshirt moche</em>&laquo;&nbsp;. Le gars a juste le temps de reculer lorsque tu refermes la porte.</p>
<p>Quelques jours plus tard, un gars en costard-cravate, look banal, sonne à ta porte&#8230; &laquo;&nbsp;<em>Salut, moi c&#8217;est JSF2. Je suis un standard, j&#8217;ai plusieurs implémentations possibles, je suis là pour tuer Struts2. Comme je suis un standard, je suis bon pour toi et pour ton CV. Par contre pour avoir des composants intéressants il faudra que tu prennes RichFaces/IceFaces ou autre. Et pour ce qui est du REST, on prendra mon pote JAX-RS&#8230; et pour la mise en prod on prendra le serveur Trucmuche de 80mo&#8230; et blablablabla&#8230;</em>&laquo;&nbsp;.<br />
Bon là c&#8217;est facile, le bonhomme se taille en 4 tout seul. Refermons la porte poliment et retournons à TéléFoot.</p>
<p>&nbsp;</p>
<div id="attachment_5447" class="wp-caption alignleft" style="width: 250px"><a href="http://www.touilleur-express.fr/wp-content/uploads/2010/05/factory.jpg"><img class="size-full wp-image-5447" title="factory" src="http://www.touilleur-express.fr/wp-content/uploads/2010/05/factory.jpg" alt="" width="240" height="160" /></a><p class="wp-caption-text">Licence Commons Creatives, crédit photo Kenichi Nobusue</p></div>
<p><a href="http://www.flickr.com/photos/antman-87/"><br />
</a><strong>Quelques idées sérieuses</strong><br />
Le développement Web fait-il partie du génome des développeurs Java ?<br />
Autant PHP me semble fortement lié à une culture Web, autant Java n&#8217;est pas forcément associé au Web. Lors des présentations de Play! Framework, Nicolas Leroux et Guillaume Bort demandaient à la salle du Paris JUG :<br />
<strong>Qui est développeur Web ?</strong><br />
Quelques mains timides se lèvent sur les quelques 450 personnes présentes. Guillaume demande ensuite qui a déjà fait des JSPs ou des Servlets. Et là, presque tout le monde lève sa main&#8230; Donc si nous comprenons bien ce qui se passe, vous n&#8217;êtes pas développeur Web, mais pourtant vous faîtes des JSPs, des Servlets et du Struts&#8230;<br />
Ce qui est dommage si nous continuons sur cette idée, c&#8217;est que du coup, vous n&#8217;avez pas forcément de connaissances en HTML, en CSS, en JavaScript. Si je vous dis que le protocole HTTP est sans état, cela vous semble-t-il alors normal de voir des frameworks massivement avec état, comme le principe même de JSF par exemple ?</p>
<p>Le Web est un vaste espace documentaire. Chaque ressource doit disposer d&#8217;une adresse unique, d&#8217;une URI. Les répertoires virtuels d&#8217;un site doivent être autant de conteneur, pour classer et ranger vos objets, par catégorie. Le protocole Web dispose depuis 15 ans des verbes d&#8217;action pour manipuler les documents : GET,POST,DELETE et PUT essentiellement. Saviez-vous que JSF 1.x ne faisait que des POSTs pour échanger des données avec le serveur ? Qui imagine avoir des URLs bookmarkable avec ce type de framework ?</p>
<p>Chaque URL affichée par votre navigateur représente finalement une vue. Les premiers frameworks du monde Java, Struts 1.x pour n&#8217;en citer qu&#8217;un, ont été construit par dessus l&#8217;API des Servlets. Intéressant, lorsque l&#8217;on pense qu&#8217;une Servlet ajoute la notion de session du côté du serveur, concept qui va rendre la vie des développeurs Javas un peu plus compliqué que prévu. Tout d&#8217;un coup, un navigateur qui n&#8217;est pas connecté au serveur Web en permanence, demande au serveur de maintenir une session. Le concept magique de session, qui permet d&#8217;acheter des oiseaux dans un magasin, devient la référence pour les développeurs Webs. Cette démonstration a eu l&#8217;effet d&#8217;un lampadaire sur les moustiques : tout le monde a plongé dans le monde formidable de la session. J&#8217;y reviens plus loin dans quelques lignes.</p>
<p>Le jour où Gavin King a annoncé Seam, il explique entre autre avec fierté que son framework gère le bouton &laquo;&nbsp;Back&nbsp;&raquo; du navigateur&#8230; Chose qui me semble normal, et que nous savions gérer en 1997 avec du Perl, et un peu d&#8217;huile de coude.</p>
<p>La session dans les frameworks Webs Java est un objet assez mal compris. L&#8217;implémentation de certains frameworks Webs, que j&#8217;appelle &laquo;&nbsp;avec session&nbsp;&raquo; comme Tapestry, Struts ou Wicket, utilisent un Cookie pour identifier la session du navigateur avec une session en mémoire sur le serveur. Ce ticket permet de stocker sur le serveur des objets volumineux. Je vois alors le framework Web comme une sorte de Mont de Piété. Vous déposez vos valeurs, on vous donne un ticket. Lorsque vous revenez, vous récupérez alors vos valeurs, votre session contre ce ticket. Ce mécanisme est nécessaire car il n&#8217;est pas souhaitable de sérialiser vos données et de les passer au client. Le souci : cela entraîne une consommation de mémoire du côté serveur car le développeur Java aura tendance à mettre en session tout et n&#8217;importe quoi.</p>
<p>Il y a eu une tentative de faire travailler le navigateur Web, et de lui donner alors toutes les données de session. L&#8217;avantage ? Les Serveurs sans état peuvent alors être monté en cluster, et le navigateur passe les données de session de page en page. Cela fonctionne avec de la réécriture d&#8217;URL lorsque vous faîtes des GET ou en postant les données dans des champs cachés si vous faîtes du POST. Cela marche très bien, c&#8217;est le principe d&#8217;eBay. Il y a cependant quelques limitations, comme la taille des URIs par exemple. Vous ne vous êtes pas demandé quel serait la taille maximale d&#8217;une URI ?<br />
Avant tout, la RFC 2616 (Hypertext Transfer Protocol — HTTP/1.1) précise dans la section 3.2.1 qu&#8217;il n&#8217;y a pas de limite sur la taille d&#8217;une URI. En théorie, il serait donc possible de passer des données de session énorme. Dans les faits, c&#8217;est faux.<a href="http://support.microsoft.com/kb/208427"> Internet Explorer ne dépasse pas 2083 caractères</a>, Firefox pousse jusqu&#8217;à 65565 caractères. Mais les serveurs Webs comme Apache limitent à 4000 caractères par défaut, comme parfois les proxy qui se chargent de faire de la redirection ou du load-balancing.</p>
<p>En général, les frameworks Webs évitent d&#8217;avoir une notion de session qui coûte de la mémoire côté serveur lorsque celle-ci n&#8217;est pas indispensable. Les frameworks Javas ont proposé très tôt ce concept de Session. Pour monter plus de Sessions, il faudra souvent avoir plus de mémoire. Personne n&#8217;aura expliqué au développeur Web Java comment calculer la taille de sa session.</p>
<p>Il y eu ensuite le souci de la durée de vie des Sessions. Soit aucune session, proche des EJB stateless, soit avec une session, on pense aux EJBs statefull. Mais ce concept métier ne fonctionnait pas bien avec le Web. Lorsque les premières architectures Webs pour la partie vue ont commencé à discuter avec des architectures métiers écrites sur la base des EJB 2.x, ce fut assez amusant. Pour que le monde du Web puisse afficher des données sur plusieurs écrans successifs, il fallait les stocker dans le &laquo;&nbsp;Web Tiers&nbsp;&raquo;. Nous avons utilisé des DTO, représentant des données venues de la partie métier. Puis quelqu&#8217;un a dit un jour que la séparation entre le Web tiers et l&#8217;EJB Tiers était une grosse bêtise inventée par des vendeurs de machines. Et nous avons tué cette idée aussi rapidement qu&#8217;elle s&#8217;était diffusée. Je rigole pas trop fort car je connais encore beaucoup de systèmes en production avec un tiers Web, et un tiers EJB. Il y a un firewall entre le monde extérieur et le Web tiers. Puis un deuxième firewall entre le web tiers et l&#8217;ejb tiers. Bien entendu, 4 machines pour le tout, afin de faire du load-balancing&#8230; J&#8217;imagine le sourire du commercial qui a vendu les machines à l&#8217;époque.</p>
<p>Seam a introduit le concept de conversation. <a href="http://www.touilleur-express.fr/2006/12/12/jboss-seam-linteret-de-la-conversation/" target="new2">En décembre 2006</a> j&#8217;en parlais avec passion. Cela a été repris dans CDI, dans JEE6. Et le concept de conversation Flash est aussi maintenant partie intégrante de Grails ou de Play! Framework par exemple. Preuve qu&#8217;il est possible de gérer de manière fine la durée des sessions.</p>
<p>Tout ceci pour dire que je crois que les frameworks Javas et le monde Web ne se sont pas vraiment compris. Nous avons souvent une complexité culturelle avec Java, qui n&#8217;est pas nécessaire lorsque l&#8217;on fait du Web (idée de Guillaume Bort, auteur de Play! Framework). Les développeurs Javas que je connais, même les meilleurs, n&#8217;ont pas nécessairement la culture Web. Avoir une culture Web pour moi, c&#8217;est connaître le protocole HTTP, HTML, CSS, REST et les possibilités des architectures sans états. Ce n&#8217;est pas imposer une vision middleware, qui ne fonctionne pas avec le Web. C&#8217;est certainement une chose sur laquelle nous devons encore travailler, nous qui sommes développeur Java. Le jour où SUN Microsystems, IBM et HP ont décidé que pour vendre de la machine, il fallait de la complexité, nous aurions dû faire attention. Pourquoi les autres langages comme PHP, Python, Perl ou C# ont-ils des frameworks Webs digne de ce nom ? Parce qu&#8217;ils n&#8217;ont pas cherché à en faire une longue histoire compliquée. Parce qu&#8217;ils ont respecté HTTP pour ce qu&#8217;il était, sans essayer une danse du ventre pour séduire les développeurs, pour finalement les planter quelques mois plus tard. Que celui qui n&#8217;a jamais entendu un AdminSys râler à propos de Tomcat et des serveurs d&#8217;applications lève la main&#8230;</p>
<p>J&#8217;écris cela car je pense que le Web et Java ont encore des efforts pour se comprendre. Je ne suis pas extasié devant GWT, inventé pour masquer la complexité de JavaScript. Je ne suis pas impressionné par Apache Wicket qui permet de coder &laquo;&nbsp;à la Swing&nbsp;&raquo; dans un monde massivement orienté objet une application Web, qui n&#8217;a que faire de l&#8217;orienté objet. Je ne suis pas impressionné par JSF 2 qui a rattrapé le retard, mais qui dispose de plusieurs implémentations, qui demande le support d&#8217;une librairie externe pour faire de l&#8217;AJAX, et qui demande des librairies pour faire de l&#8217;orienté composant&#8230;</p>
<p>Je suis impressionné par contre par la créativité des développeurs Javas, qui cherchent parfois à faire du client lourd dans un navigateur, en appelant cela &laquo;&nbsp;un client léger&nbsp;&raquo;. Bon sang, une application Web n&#8217;a rien à voir avec la vision à papa, avec des fenêtres et des boutons qui font pouet-pouet&#8230; Prenez dans ce cas une techno comme Flex par exemple, pour faire un client déporté</p>
<p>Je pense qu&#8217;il est temps de faire simple. Les vraies architectures Webs c&#8217;est pour maintenant. Allez lire <a href="http://iam.guillaume.bort.fr/">sur le blog de Guillaume Bort</a> pourquoi Play! Framework n&#8217;est pas basé sur l&#8217;API Servlet. C&#8217;est très intéressant.</p>
<p>Merci de penser que Java et les frameworks Webs c&#8217;est simple.</p>
<p><em><br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2010/05/01/java-et-les-frameworks-webs-une-longue-histoire-compliquee/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>Compte-rendu de la présentation de Wicket et du Web Sémantique</title>
		<link>http://www.touilleur-express.fr/2009/03/11/compte-rendu-de-la-presentation-de-wicket-et-du-web-semantique/</link>
		<comments>http://www.touilleur-express.fr/2009/03/11/compte-rendu-de-la-presentation-de-wicket-et-du-web-semantique/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 19:50:40 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wicket]]></category>

		<guid isPermaLink="false">http://www.touilleur-express.fr/?p=866</guid>
		<description><![CDATA[Atterrissage en douceur hier soir sur la planète Wicket, avec aux commandes les 2 fondateurs de Zénika : Carl Azoury et Nicolas André, anciens de Sysdeo et maintenant aux commandes de Zénika. Le format choisi était ambitieux : réaliser en une heure une application CRUD de gestion de contacts. Quelques sueurs froides au départ, mais pour la suite franchement c&#8217;était vraiment bien piloté. De mémoire de Jugeur, les derniers codeurs en direct étaient Jean-François Hélie et Christian Blavier d&#8217;OCTO Technologies en juin dernier, lors de la soirée TDD et Spring. ...]]></description>
			<content:encoded><![CDATA[<p>Atterrissage en douceur hier soir sur la planète Wicket, avec aux commandes les 2 fondateurs de Zénika : Carl Azoury et Nicolas André, anciens de Sysdeo et maintenant aux commandes de Zénika. Le format choisi était ambitieux : réaliser en une heure une application CRUD de gestion de contacts. Quelques sueurs froides au départ, mais pour la suite franchement c&#8217;était vraiment bien piloté. De mémoire de Jugeur, les derniers codeurs en direct étaient Jean-François Hélie et Christian Blavier d&#8217;OCTO Technologies en juin dernier, lors de <a href="http://www.touilleur-express.fr/2008/06/11/compte-rendu-de-la-soiree-spring-pjug/">la soirée TDD</a> et Spring. Je trouve qu&#8217;ils ont vraiment bien assuré sur le contenu et sur la forme.</p>
<p>Avant cela, Antonio rappelle l&#8217;importance des sponsors, le Paris JUG a besoin de l&#8217;aide et du support de sponsors afin de continuer à pouvoir accueillir tout le monde. Concernant l&#8217;offre Java BlackBelt évoquée le mois dernier, vous pouvez contacter l&#8217;équipe en vous abonnant à la liste de diffusion du Paris JUG <a href="http://www.parisjug.org">directement sur le site</a>. Enfin chacun est venu avec son attestation d&#8217;inscription. Les places sont limitées pour des raisons de sécurité. Hier soir je pense que la salle était pleine avec ses 180 places.</p>
<p>La présentation Wicket elle-même était sympa, je pense que mes voisins seront en mesure de couvrir en détail la soirée. Allez voir <a href="http://thecodersbreakfast.net/">Olivier</a> (de Zenika) je pense que son blog ne manquera pas de vous expliquer le contenu de la soirée.</p>
<p>Carl a annoncé que le 29 avril prochain se tiendra une nouvelle soirée sur le thème de Wicket organisée comme <a href="http://www.touilleur-express.fr/2009/01/22/presentation-de-lean-chez-zenika/">la présentation de Lean</a>. Le présentateur sera l&#8217;un des co-auteur de Wicket, je crois qu&#8217;il s&#8217;agit de Jonathan Locke. A suivre donc. Encore une fois bravo à Zénika qui après Ross Mason, <a href="http://www.touilleur-express.fr/2008/10/04/quelques-photos-de-la-soiree-terracotta/">Ari Zilka</a> et la présentation sur Lean, prépare un événement sympathique.</p>
<p>Enfin pour terminer, Nicolas André et Carl Azoury ont montré qu&#8217;en 163 lignes de codes et 12 classes, il était possible de réaliser une application Web Ajaxisée avec le support du Drag-and-drop. Zenika propose un concours sur leur blog à ceux qui souhaitent coder la même application avec une autre technologie que Wicket. Le cahier des charges est assez précis, retrouvez l&#8217;article complet <a href="http://blog.zenika.com/index.php?post/2009/03/10/Concours-D%C3%A9velopper-une-application-web-en-Wicket3">sur le blog de Zenika</a>.</p>
<p>Après un buffer où j&#8217;ai croisé pas mal de monde, la deuxième partie de la soirée était une présentation du Web Sémantique par Alexandre Bertails d&#8217;Atos Origin Open Source Center. La présentation était très claire, alors que le sujet est assez compliqué à expliquer. Les notions de Triplet, d&#8217;URI, de Graphe ont peut-être fait peur à quelques-uns d&#8217;entre nous. Ce que j&#8217;ai retenu, c&#8217;est que l&#8217;objet du Web Sémantique est de séparer les Données des Applications qui les gèrent. Ainsi, à terme on imagine un moyen complet pour décrire de l&#8217;information. Cela ouvre la porte à la création d&#8217;applications capable de s&#8217;approprier l&#8217;information et d&#8217;y apporter de la valeur.<br />
Alexandre prend l&#8217;exemple de la construction d&#8217;une phrase : SUJET &#8211; VERBE &#8211; COMPLEMENT pour expliquer la notion de Triplet. Par exemple :</p>
<pre>
Le Touilleur est un blog
</pre>
<p>Chacun des éléments du Triplet sont donc le sujet, le verbe et le complément. Le tout est décrit avec 3 URI différentes pour chacun des tuples. Bien entendu différents formats comme RDF ou OWL permettent de formaliser en langage informatique ces prédicats. Je discute un moment avec <a href="http://blog.improve-technologies.com/">Sébastien Letélié</a>, directeur technique d&#8217;Improve Santé. La formalisation du dossier médical avec le Web Sémantique permet de s&#8217;assurer que le format pour exprimer finalement nos données est ensuite utilisé au mieux. Il travaille je crois sur un projet avec le SAMU afin de proposer à terme un système médicalisé basé sur une ontologie médical, où les médecins décrivent et mettent au point ces concepts.</p>
<p>Alexandre présente un site que vous pouvez vous aussi tester si les concepts de Web Sémantique vous semblent un peu compliqué. Le site dbpedia.org est une extraction du contenu de Wikipedia, enregistré avec le format du web sémantique.<br />
Vous pouvez ainsi entrer des requêtes simples en utilisant par exemple <a href="http://dbpedia.openlinksw.com:8890/isparql/">OpenLink iSPARQL</a>. Un exemple de requête logique:</p>
<pre>
Barack Obama | est né | à un endroit
Un endroit | a | pour nom ?
</pre>
<p>Regardez par exemple <a href="http://dbpedia.org/page/Java_Development_Kit">la page sur Java</a> de dbpedia avec les différents attributs (les tuplets). On constate que le contenu exprime avec des URI le type de contenu. La page web elle-même vous présente de l&#8217;information, mais démarque aussi le contenu avec des annotations afin de vous dire : &laquo;&nbsp;ici c&#8217;est le titre&nbsp;&raquo; &laquo;&nbsp;là c&#8217;est une image&nbsp;&raquo; &laquo;&nbsp;ici il s&#8217;agit d&#8217;un commentaire&nbsp;&raquo;, ce qui permet alors à votre navigateur d&#8217;en déduire ce que vous voyez.</p>
<p>Je sens que je rame.</p>
<p>Imaginez le Touilleur Express : chaque article est balisé (de manière invisible pour vous). Lorsque je place une date dans un de mes articles, je précise qu&#8217;il s&#8217;agit d&#8217;un rendez-vous. Firefox qui affiche la page peut alors vous proposer par exemple de sauver ce rendez-vous dans votre agenda. C&#8217;est ce que l&#8217;on appelle les <a href="http://fr.wikipedia.org/wiki/Microformat">microformats</a>, sans doute l&#8217;avenir du contenu intelligent sur Internet. <a href="http://microformats.org/">Le site officiel</a> sur les microformats nous informe qu&#8217;un certain nombre de format, spécifié avec RFC, sont dans les cartons. Tout ceci est encore assez jeune, Alexandre explique que les derniers travaux datent de l&#8217;an passé.</p>
<p>En conclusion, car j&#8217;ai du mal à vous retranscrire ici cette très bonne présentation, je pense que le Web sémantique est un concept qui sera mature d&#8217;ici quelques mois, voire quelques années. Avec la puissance des réseaux et ce besoin de libérer les données des applications, nous pourrons alors avoir une nouvelle forme de navigation sur Internet, un nouveau moyen d&#8217;échanger l&#8217;information.</p>
<p>Le mois prochain la prochaine présentation du Paris JUG sera sur Scrum, par Eric Mignot et moi-même. Nous travaillons avec Eric sur un format et un contenu qui sera spécialement formaté pour le Paris JUG, avec pour moi l&#8217;envie de vous proposer une présentation aux petits oignons.</p>
<p>Au mois prochain !</p>
<p>Références :<br />
<a href="http://www.itaware.eu/2009/03/10/jug-wicket-et-web-semantique/">Blog de Sébastien Letélié</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2009/03/11/compte-rendu-de-la-presentation-de-wicket-et-du-web-semantique/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Quelques sites indispensables pour vos développements Webs</title>
		<link>http://www.touilleur-express.fr/2008/06/17/quelques-sites-indispensables-pour-vos-developpements-webs/</link>
		<comments>http://www.touilleur-express.fr/2008/06/17/quelques-sites-indispensables-pour-vos-developpements-webs/#comments</comments>
		<pubDate>Tue, 17 Jun 2008 06:05:01 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Dev Web]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.touilleur-express.fr/?p=194</guid>
		<description><![CDATA[Ce matin un post qui n&#8217;a rien à voir avec Java, ni Apple&#8230; pour une fois !
J&#8217;ai en réserve un bon nombre d&#8217;adresse que j&#8217;utilise lorsque je dois valider un site, créer rapidement un logo ou trouver une mise en page CSS sympathique. Je n&#8217;ai pas tout repris ici mais voici déjà quelques uns de mes liens.
BrowserShots est un site qui vous permet de tester votre site internet avec différents navigateurs. Pour cela le site visite votre page et effectue une capture d&#8217;écran, que vous pouvez ensuite télécharger. Le Touilleur ...]]></description>
			<content:encoded><![CDATA[<p>Ce matin un post qui n&#8217;a rien à voir avec Java, ni Apple&#8230; pour une fois !</p>
<p>J&#8217;ai en réserve un bon nombre d&#8217;adresse que j&#8217;utilise lorsque je dois valider un site, créer rapidement un logo ou trouver une mise en page CSS sympathique. Je n&#8217;ai pas tout repris ici mais voici déjà quelques uns de mes liens.</p>
<p><a href="http://browsershots.org/">BrowserShots</a> est un site qui vous permet de tester votre site internet avec différents navigateurs. Pour cela le site visite votre page et effectue une capture d&#8217;écran, que vous pouvez ensuite télécharger. Le Touilleur Express par exemple ne marche pas très bien avec certaines versions d&#8217;Opéra. Pratique et rapide.<br />
<a href="http://browsershots.org/">http://browsershots.org/<br />
</a></p>
<p>L&#8217;adresse de courrier électronique poubelle, vous connaissez ? Disons que vous avez besoin de vous inscrire afin de recevoir un email d&#8217;un site marchand un peu douteux, le site <a href="http://spambox.us/">SpamBox</a> propose de créer un email valable une heure seulement. Cependant avant de m&#8217;en servir, je vérifierai bien si ce site lui-même n&#8217;en profite pas pour récupérer votre vraie adresse email pour la revendre&#8230; On est jamais trop prudent.</p>
<p>Le logo en flamme, le logo en flamme ! Si vous cherchez quelques tutoriaux afin de créer votre logo en flamme, allez jeter un oeil sur <a href="http://www.designvitality.com/blog/2007/09/photoshop-text-effect-tutorial/">le blog de DesignVitality</a>. J&#8217;aime particulièrement les designs Web 2.0.</p>
<p>Le site <a href="http://www.dafont.com/fr/">DaFont</a> offre une très grande collection de polices pour réaliser des applications webs, des sites et des logos. Il y a des polices très originales qui permettent de réaliser la patte d&#8217;un site en quelques instants.</p>
<p>Le site qu&#8217;il faut avoir dans ses bookmarks car il contient finalement un peu prêt tout ce dont j&#8217;ai besoin lorsque je crée un habillage : <a href="http://webdevelopersfieldguide.com/">http://webdevelopersfieldguide.com/.</a> Par exemple <a href="http://colourmod.com/">une roue colométrique</a> pour l&#8217;équilibre des couleurs. Ou un système comme <a href="http://www.degraeve.com/color-palette/index.php">DeGraeve.com</a> qui se base sur une image pour vous proposer une carte de couleurs.</p>
<p>Pour suivre l&#8217;actualité autour d&#8217;Ajax et des librairies comme <a href="http://www.prototypejs.org/">Prototype</a> ou <a href="http://script.aculo.us/">Script.aculo.us</a>, je vous avais déjà parlé <a href="http://ajaxian.com/">d&#8217;Ajaxian.com.</a> Le site propose souvent des articles assez pointus sur Ajax et Javascript.</p>
<p>En ce moment nous corrigeons des problèmes de Closures en Javascript. Je cherchais sur le net un outil que j&#8217;avais testé il y a 2 ans pour identifier des closures&#8230; Je tappe quelques mots et je tombe&#8230; sur mon blog&#8230; Ca fait bizarre de se répondre à soi-même&#8230; Si vous voulez briller en société et expliqué à un client ou à un consultant ce qu&#8217;est une Closure, je vous redonne <a href="http://blog.morrisjohns.com/javascript_closures_for_dummies">cette page</a> très bien faite, avant de vous proposer à mon tour une explication en français dans le texte prochainement. Oui on ne  le dit pas assez, mais un certain nombre de librairies Ajax peuvent causer des problèmes de mémoire du côté du navigateur.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2008/06/17/quelques-sites-indispensables-pour-vos-developpements-webs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joomla, un gestionnaire de contenu pour votre site</title>
		<link>http://www.touilleur-express.fr/2008/01/13/joomla-un-gestionnaire-de-contenu-pour-votre-site/</link>
		<comments>http://www.touilleur-express.fr/2008/01/13/joomla-un-gestionnaire-de-contenu-pour-votre-site/#comments</comments>
		<pubDate>Sun, 13 Jan 2008 18:17:48 +0000</pubDate>
		<dc:creator>Nicolas Martignole</dc:creator>
				<category><![CDATA[Dev Web]]></category>
		<category><![CDATA[crm]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.touillleur-express.fr/?p=14</guid>
		<description><![CDATA[Joomla est un système de gestion de contenu pour votre site web. Il est gratuit, simple et destiné à vous faciliter la vie. Basé sur PHP, Joomla permet de construire des sites Internets complexes (forum, système de vote, mailing&#8230;) sans taper une ligne de PHP ou d&#8217;HTML. Pour ma part, j&#8217;ai commencé à travailler avec la nouvelle version 1.5 RC4.
Vous avez besoin d&#8217;un serveur avec une base de données MySQL et le support PHP. Ensuite concernant le look, les templates permettent d&#8217;habiller d&#8217;un seul clic votre site. Et vous pouvez ...]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.joomla.fr/">Joomla</a> est un système de gestion de contenu pour votre site web. Il est gratuit, simple et destiné à vous faciliter la vie. Basé sur PHP, Joomla permet de construire des sites Internets complexes (forum, système de vote, mailing&#8230;) sans taper une ligne de PHP ou d&#8217;HTML. Pour ma part, j&#8217;ai commencé à travailler avec la nouvelle version 1.5 RC4.</p>
<p>Vous avez besoin d&#8217;un serveur avec une base de données MySQL et le support PHP. Ensuite concernant le look, les templates permettent d&#8217;habiller d&#8217;un seul clic votre site. Et vous pouvez changer ensuite à tout moment d&#8217;habillage sans une ligne de code. Sous Mac, aucuns problèmes pour installer Apache+MySQL grâce à <a href="http://www.framasoft.net/article3719.html">MAMP</a> (Mac, Apache, MySQL et PHP). Sous Windows vous pouvez télécharger <a href="http://www.apachefriends.org/fr/xampp.html">XAMPP</a>. Comptez  quelques heures pour maîtriser Joomla si vous avez déjà une expérience avec Internet. Sinon tout au plus une semaine je pense.</p>
<p><strong>Concernant la compatibilité avec la version 1.0</strong> vous pouvez activer le plugin <strong>System &#8211; Legacy</strong> afin de pouvoir utiliser un template 1.0 avec la version 1.5 de Joomla. Cela dit, les templates sont en fait une simple page PHP et quelques CSS.</p>
<p>Si vous utilisez Joomla et que vous chercher des templates gratuits, je vous conseille les sites suivants:</p>
<ul>
<li><a href="http://templates.joomlafacile.com/">http://templates.joomlafacile.com/</a></li>
<li><a href="http://www.siteground.com/joomla-hosting/joomla-templates.htm">http://www.siteGround.com</a></li>
<li><a href="http://www.joomlashack.com/">http://www.joomlashack.com/</a></li>
<li><a href="http://www.joomladesigns.co.uk/">http://www.joomladesigns.co.uk/</a></li>
</ul>
<p>Pour le Touilleur, je suis hébergé sur le site JRoller. Il a l&#8217;avantage d&#8217;être gratuit et bien référencé. Mais je pense qu&#8217;à terme je prendrai un hébergement dédié afin de pouvoir d&#8217;une part mon blog, et d&#8217;autre part un site plus classique pour le boulot. Voili voilà</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touilleur-express.fr/2008/01/13/joomla-un-gestionnaire-de-contenu-pour-votre-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

