Sur la route d'Oxiane digressions diverses

LeBlog OXiane

17 juin
2011

Le Shiv HTML5 chez Adobe

Alors que Adobe peaufine sa suite CS5.5 avec de nouvelle fonctionnalités, l’une d’elles nous intéresse particulièrement et mérite peut être un peu d’explication : la gestion du shiv.

Le shiv, pour certains, c’est le second de Pat Morita dans O’Hara, Shaver de son vrai pseudonyme …

Pour nous, le shiv, c’est simplement un petit bout de code pour améliorer la rétro-compatibilité de nos sites web. En effet, les versions anciennes d’Internet Explorer ne sont pas très à l’aise avec le HTML5. Mais le plus grave, c’est qu’elles ne reconnaissent même pas les « nouveaux » éléments ! Et que le style ne peut donc pas s’appliquer (et par conséquent, on oublie également toute manipulation de DOM…).

Le shiv a une histoire courte mais déjà complexe, difficile par exemple, quand on est pas anglophone, de comprendre le passage du terme original « shim » au « shiv » … Techniquement, on apprend qu’une poignée de gars a bossé sur le problème, et qu’ils nous ont fourni une mini API simple à utiliser, un simple script à embarquer et nous pouvons designer nos pages avec les nouveaux éléments HTML5 !


Attention, ce script ne sert en aucun cas à permettre à IE de gérer les API HTML5 ! Les fonctionnalités qui manquent dans le moteur javascript ou dans le moteur de rendu CSS ne vont pas apparaitre ainsi. Il faudra pour ça utiliser un plugin javascript pour « simuler » ce qui manque.

Désormais, donc, le shiv est embarqué nativement dans les templates Dreamweaver HTML5, et c’est tant mieux, car cet outil a souvent un public de développeur « non-geek », qui n’ont pas spécialement envie de connaitre le nom du dernier contributeur de la spec non-encore finalisée d’un langage de balises ;)

Voilà encore une raison de se lancer dans le web sémantique et joli et tout rose grâce à Sjoerd Visscher !

Alain Boudard

aboudard

15 juin
2011

NoSQL vs relationnel ou NoSQL + relationnel

Commençons par clarifier les choses, le NoSQL ce n’est ni un langage, ni un standard, ni de l’anti SQL, ni de l’anti base de données, ni “Not Only SQL”.
Lancé en juin 2009, le NoSQL est un mouvement dont le but est de proposer une alternative au langage SQL et au modèle relationnel des bases traditionnels.
Le NoSQL n’a pas pour vocation de remplacer le modèle relationnel mais plutôt de compléter ses fonctionnalités ou de s’adresser à des applications différentes.

Les bases relationnelles c’est robuste, elles ont fait leur preuve alors pourquoi le NoSQL ?

Le NoSQL est issu du travail des grands acteurs d’internet (Google, Amazon, Facebook, LinkedIn, …) en écho aux nouvelles architectures que sont le cloud computing et les sites communautaires.

Sa génèse est liée au théorème de CAP formulé par Eric Brewer (UC Berkeley) en 2000 (keynote) et démontré par  Seth Gilbert et Nancy Lynch (MIT) en 2002 (white paper).
Ce théorème énonce qu’il est impossible, sur un système informatique de calcul distribué, de garantir en même temps les trois contraintes suivantes :

  • Coherence (Cohérence) : Tous les clients voient la même chose, même en présence de mises à jour.
  • Availibility (Disponibilité) : Tous les clients obtiendront une réponse à leur requête.
  • Partition Tolerance (Partitionabilité) : Les propriétés du système sont maintenues même lorsque celui-ci est partitionné.

En réponse à ce théorème les architectes en place décidèrent de sacrifier la cohérence au profit de la disponibilité et de l’évolutivité. Cette décision, motivée par des besoins croissant en terme de charge et de volumétrie, engendra  la mise au point de systèmes de bases de données non relationnels. Aucun d’entre eux ne supportant le langage SQL le terme « NoSQL » fût choisi pour les qualifier.

En se détachant du caractère ACID des transactions, les systèmes NoSQL se sont donc dégagées de deux entraves que connaissent les bases relationnelles :

  • L’évolutivité horizontale : Le déploiement d’une base NoSQL sur de multiples machines ainsi que l’ajout d’une nouvelle machine au sein du réseau distribué sont facilités.
  • La flexibilité : Une base NoSQL peut en effet croître sans contrainte, sa structure organisationnelle n’est pas liée à un schéma relationnel difficile à modifier.

Au sujet de l’évolutivité, Adam Wiggins (Heroku) explique clairement dans ce post en quoi il est ardu de la  mettre en oeuvre sur une base relationnelle.

Ok, c’est très bien tout ça mais concrètement les bases NoSQL ça se présente comment ?

Actuellement il existe ~= 122 solutions NoSQL. Le site nosql-database.org maintient une liste à jour.
Ces différentes alternatives au SQL sont regroupés selon 6 types :

  • Associatif (clé-valeur) : Riak, Voldemort, Membase/Memcached
    Equivalent d’un gros HashMap ou Dictionary (cf Smalltalk pour les incultes :) ). Il n’y a pas de modèle de donnée et tout type de donnée peut-être associé à une clé.
  • Hiérarchique : GT.M
    Organise les données dans une structure sous forme d’arbre.
  • Orienté document : MongoDB, CouchDB, RavenDB, Lotus Notes
    Fonctionne comme le type Associatif sauf que la valeur est ici un objet structuré auto-décrit en XML ou Json. A partir d’une clé, de l’information très structurée peut donc être remontée simplement là où plusieurs jointures aurait été nécessaire dans le monde relationnel.
  • Orienté colonne : Cassandra, Hadoop/HBase, SimpleDB
    Possède un modèle de donnée similaire à celui des bases relationnelles cependant le nombre de colonne est dynamique. Pour une même table 2 enregistrements peuvent avoir un nombre de colonnes différent ce qui limitent les colonnes à NULL.
  • Orienté graphe : Neo4J, InfiniteGraph
    Utilise une structure de graphes comportant des noeuds, des arcs et des propriétés pour représenter et stocker l’information.
  • Orienté objet : GemStone/S, db4o
    Stocke les données sous formes d’objets tel qu’utilisés au sein de la programmation orientée objet. Le concept n’est pas nouveau mais ces bases sont désormais etiquettées NoSQL.

Certaines solutions misent sur la facilité de prise en main. CouchDB, par exemple, représente la donnée en JSON, fournit des services de requêtage, propose un mécanisme de réplication simple et peut être utilisée comme serveur d’application.
D’autres sont fondamentalement tournées vers la performance. HBase, Cassandra et Riak pour ne citer qu’elles.
Les bases orienté graphes, quant à elle, permettent de mettre en place des modélisations complexes inconcevables dans les bases relationnelles. Et les performances ne sont pas en reste, Neo4J est capable de lire 1000 niveaux de noeuds aux alentours d’1 ms.

Quel avenir pour le NoSQL ?

A première vue, le principal désavantage du NoSQL est sa jeunesse. Comparé aux sytèmes matures et connus que sont les bases relationnelles, il ne fait pas le poids.
Les outils de supervision ne sont pas très développés pour le moment et cela peut constituer un frein à une mise en production sur des applications critiques.
Le NoSQL a aussi une image de système à déployer uniquement sur des applications nécessitant d’être très performante et travaillant sur de gros volumes. Sorte de Rolls-Royce des bases de données que seules de grosses compagnies peuvent s’offrir.

Malgré cela, le NoSQL reste une technologie attrayante. D’une part elle apporte de l’agilité  au niveau du  développement et de la maintenance. D’autre part, elle remet au goût du jour des solutions qui avaient été éclipsées par l’avènement des bases relationnelles.
Il ne s’agit pas non plus de tout basculer vers le NoSQL mais plutôt de s’orienter vers des solutions hybrides en couplant une base relationnelle avec une base NoSQL. Comprendre comment est manipulée la donnée au sein du SI redevient l’enjeu primordial et implique de se pencher sur de nouveaux paradigmes tel l’Eventual Consistency.
Certaines entreprises ont franchi le pas « The Guardian » (post, slides) ou Twitter (slides) et leur retour d’expérience est très intéressant.

Jusqu’à quel point le challenger NoSQL pourra inquiéter le règne du  champion Relationnel, là est la question :)

Références :
http://www.julianbrowne.com/article/viewer/brewers-cap-theorem
http://www.slideshare.net/thobe/nosqleu-graph-databases-and-neo4j
http://highscalability.com/neo4j-graph-database-kicks-buttox
http://nosql.mypopescu.com/
http://www.slideshare.net/ksankar/nosql-4559402

Gaetan Le Brun

Gaëtan Le Brun

5 juin
2011

Rencontre PAUG – un événement microformat

Un événement de la communauté Android : la réunion du PAUG, Paris Android User Guide.
C’est l’occasion de passer rapidement sur un des éléments qui enrichissent depuis quelques temps les pages HTML, sans être du HTML5 à part entière.

Je parle donc ici des microformats
Ce sont principalement des données, que l’on déclare via l’attribut « class », qui n’est certes pas qu’un identifiant CSS (on trouve encore tellement de sites dont la seule destinée des classes se borne à « class=’titrebleu’ … » ou quelque chose de ce genre.

L’idée de ces données est de les fournir à des agents externes. Agent externe ?
Google par exemple, ou plus simplement le navigateur, le user agent comme on dit.
Les types les plus communs à ce jour sont les spécifications suivantes :
hCard, hCalendar, hReview et XFN et … hatom

Toutes ces spécifications peuvent être sans risque insérées dans votre contenu existant, sur une page Contact, nous aurons simplement à enrichir les balises de l’adresse de la société avec les bons attributs.

Le meilleur exemple ?
La réunion du PAUG de ce lundi 6 juin 2011.

Comment tester l’utilisation de ces données ?
Aller installer Operator pour Firefox ou encore Microformats pour Chrome. Vous verrez simplement sur votre barre d’outils ou sur le bouton droit, des raccourcis permettant d’ajouter un contact à un carnet d’adresses, un événement à un calendrier … etc. Du coup je vais voir si la page Meetup de notre réunion contient des choses intéressantes ! Hé bien oui, en partie, j’ai possibilité de lire le contact PAUG, mais il n’y a pas d’objet event ! Voilà qui est un peu dommage.

Voici un exemple de vEvent :


Rencontre PAUG Juin 2011 – Réalité augmentée


6 Juin 2011
-

6 Juin 2011
où :

37 Quai de Grenelle, Paris, France, ECE – Salle P445 au 2e étage

Le code :

Rencontre PAUG Juin 2011 - Réalité augmentée

6 Juin 2011- 6 Juin 2011 où : 37 Quai de Grenelle, Paris, France, ECE - Salle P445 au 2e étage

Ces données ne font techniquement courir aucun risque à vos pages, et vont certainement prendre de l’importance pour les moteurs de recherche, alors pas de raison de ne pas jouer avec !
Un article sur l’excellent blog des docteurs !

Alain Boudard

aboudard

5 juin
2011

JPA dans un Servlet

On trouve de nombreux tutoriels pour débuter avec JPA. La question s’est posée récemment de l’utilisation de JPA dans un contexte Web simple, ce que l’on peut résumer par « Comment utiliser JPA dans un Servlet ? ». Là, plusieurs petits problèmes surviennent et le web est étonnement avare en explications claires et « bouts de code prêts à l’emploi ». Voici donc comment faire.

Exemple autonome

Tout d’abord, commençons par refaire un exemple simple avec une application autonome.

Pour cela, il nous faut :

  • Créer un projet Java standard dans son IDE préféré (j’utilise Eclipse)
  • Configurer son classpath pour utiliser JPA (j’ajoute la librairie JBoss 5.1 Runtime)
  • Créer une entité persistante (une simple classe annotée)
    package com.oxiane;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity
    public class EntitePersistente {
    
      @Id @GeneratedValue
      private Long id;
    
      private String valeur;
    
      //accesseurs
      ...
    }
  • Créer un fichier persistence.xml dans le répertoire src/META-INF
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0"
      xmlns="http://java.sun.com/xml/ns/persistence"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <persistence-unit name="TestUnit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
          <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
          <property name="hibernate.connection.username" value="root" />
          <property name="hibernate.connection.password" value="" />
          <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test" />
          <property name="hibernate.hbm2ddl.auto" value="update" />
          <property name="hibernate.show_sql" value="true" />
        </properties>
      </persistence-unit>
    </persistence>
  • Et une classe avec un « main » pour utiliser tout ça :
    package com.oxiane;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    public class TestJPA {
      public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestUnit");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
          tx.begin();
          EntitePersistente entite = new EntitePersistente();
          entite.setValeur(""+System.currentTimeMillis());
          em.persist(entite);
          tx.commit();
          System.out.println("Entité persistée, id:"+entite.getId());
        } catch (Exception e) {
          e.printStackTrace();
          System.out.println("Oops ! petit problème");
          tx.rollback();
        } finally {
          em.close();
          emf.close();
        }
      }
    }
  • Il ne reste plus qu’à démarrer son MySql et à exécuter pour obtenir une trace dans la console du genre :
    Hibernate: insert into EntitePersistente (valeur) values (?)
    Entité persistée, id:1

On trouve facilement des infos pour faire la même chose dans un EJB

Dans ce cas, c’est même plus simple.

  • On passe par une DataSource, ce qui modifie le fichier persistence.xml :
  • <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0"
      xmlns="http://java.sun.com/xml/ns/persistence"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <persistence-unit name="TestUnit">
        <jta-data-source>jdbc/TestDS</jta-data-source>
        <properties>
          <property name="hibernate.hbm2ddl.auto" value="update" />
          <property name="hibernate.show_sql" value="true" />
        </properties>
      </persistence-unit>
    </persistence>
  • Le code est beaucoup plus simple puisqu’on se fait injecter l’EntityManager et que la transaction est gérée par le conteneur :
  • package com.oxiane;
    
    import javax.ejb.Remote;
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    @Stateless(mappedName="ejb/Test")
    @Remote(JPAServiceRemote.class)
    public class JPAServiceBean implements JPAServiceRemote, JPAServiceLocal {
    
      @PersistenceContext
      private EntityManager em;
    
      public JPAServiceBean() {
      }
    
      public Long test() {
          EntitePersistente entite = new EntitePersistente();
        entite.setValeur("" + System.currentTimeMillis());
        em.persist(entite);
        return entite.getId();
      }
    }

Que se passe-t-il maintenant si on veut faire la même chose dans un servlet ?

Là c’est moins simple et moins clair.
Tout d’abord, l’injection avec @PersistenceContexte n’est plus permise. Cela conduirait à partager l’EntityManager en cas de requêtes simultanées. A la place, il faut utiliser l’annotation @PersistenceUnit pour injecter l’EntityManagerFactory qui lui est partageable et « Thread-Safe ».

  • Injection du PersistenceUnit :
    @PersistenceUnit
    private EntityManagerFactory emf;
  • Il est donc à nouveau nécessaire de créer explicitement un EntityManager à partir de la factory :
    // !!! ne fonctionne pas !!!
    protected void doGet(HttpServletRequest request,
          HttpServletResponse response) throws ServletException, IOException {
    
        PrintWriter out = response.getWriter();
        EntityManager em = emf.createEntityManager();
        EntitePersistente entite = new EntitePersistente();
        entite.setValeur("" + System.currentTimeMillis());
        em.persist(entite);
        out.write("Entité persistée, id:" + entite.getId());
      }

Bien qu’il n’y ait pas d’erreur à l’exécution, cela ne fonctionne pas. En effet, on ne bénéficie plus de la gestion de transaction du conteneur. Il faut à nouveau gérer explicitement la transaction.
Ici deux approches sont possibles que l’on peut résumer par « JTA ou pas ? »

L’approche non-JTA

Elle signifie que l’on va gérer les transactions directement avec l’EntityManager (comme dans l’exemple autonome initial).

  • Dans ce cas, le fichier persistence.xml doit indiquer explicitement ce mode de gestion :
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0"
      xmlns="http://java.sun.com/xml/ns/persistence"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <persistence-unit name="TestUnit" transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>jdbc/TestDS</non-jta-data-source>
        <properties>
          <property name="hibernate.hbm2ddl.auto" value="update" />
          <property name="hibernate.show_sql" value="true" />
        </properties>
      </persistence-unit>
    </persistence>
  • Le code du Servlet devient alors :
    @PersistenceUnit
    private EntityManagerFactory emf;
    
    //gestion des transactions non JTA
    protected void doGet(HttpServletRequest request,
          HttpServletResponse response) throws ServletException, IOException {
    
        PrintWriter out = response.getWriter();
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        EntitePersistente entite = new EntitePersistente();
        entite.setValeur("" + System.currentTimeMillis());
        em.persist(entite);
        tx.commit();
        out.write("Entité persistée, id:" + entite.getId());
        em.close();
    }

L’approche JTA

L’autre approche consiste à utiliser des transactions JTA. Dans ce cas, le fichier de persistence.xml est le même que dans le cas des EJB mais il faut maintenant gérer explicitement une transaction JTA.
Le plus simple est de se faire injecter la UserTransaction avec l’annotation @Resource, en plus de la factory.

  • Injection de la UserTransaction
    @Resource
    private UserTransaction tx;
    
    @PersistenceUnit
    private EntityManagerFactory emf;
  • Remarque : il peut paraître surprenant d’avoir un tel attribut dans le Servlet. Il faut juste comprendre que le UserTransaction n’est pas un objet représentant la transaction mais une interface, Thread-Safe, de manipulation des transactions. Elle peut donc être partagée sans problème.

  • Le code devient alors :
    protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    
      PrintWriter out = response.getWriter();
      EntityManager em = null;
      try {
        tx.begin();
        em = emf.createEntityManager();
        EntitePersistente entite = new EntitePersistente();
        entite.setValeur("" + System.currentTimeMillis());
        em.persist(entite);
        tx.commit();
        out.write("Entité persistée, id:" + entite.getId());
      } catch (Exception e) {
        try {
          tx.rollback();
        } catch (Exception e1) {
          e1.printStackTrace();
        }
        out.write("Oops ! petit problème");
      }
      finally {
        if (em != null) {
          em.close();
        }
      }
    }

Notez au passage une subtilité un peu déroutante : dans le cas des transactions JTA, l’EntityManager doit être créé après le début de la transaction pour qu’il soit géré par celle-ci.
Si on ne respecte pas cette contrainte, on retombe dans la situation précédente où il ne se produit pas d’erreur mais rien n’est enregistré.

Jean-Francois Lefevre

jflefevre

2 juin
2011

Développeurs graphistes chefs de projet assistantes

Une humble contribution à la compréhension du microcosme de l’informaticien !

L’article original duquel l’image est tirée, et à laquelle je n’ai rajouté que les lignes « assistantes » est ici.

 

Alain Boudard

aboudard