Logging tomcat et hibernate

Introduction

Dans une application d'un client que je reprends pour de la maintenance, j'ai un problème. Cette application est faite pour Oracle et, sur ma machine de test, je n'ai aucune envie d'installer cette base de données plutôt gourmande en ressources.

Cette application utilise l'ORM hibernate pour abstraire tous les accès à la base de données. C'est donc, normalement, un jeu d'enfant d'utiliser un au SGBD. J'ai donc décidé d'utiliser le MySQL 5.1.36 qui est installé sur ma machine. Ensuite, j'ai modifié le fichier "persistence.xml" pour qu'hibernate se connecte à une nouvelle base de données sous MySQL.

Problème

Alors que tout devrait fonctionner sans problème, en lançant l'application, je n'ai aucune table qui est créée.

Dans le logging de cette application, j'obtiens l'erreur suivante :

ERROR org.hibernate.tool.hbm2ddl.SchemaUpdate - Unsuccessful: alter table nom_de_la_table add index FKCD10932052C35B33 (clé), add constraint FKCD10932052C35B33 foreign key (clé) references preview (id)
ERROR org.hibernate.tool.hbm2ddl.SchemaUpdate - Can't create table 'nom_de_la_table' (errno: 150)

Logging

Bon, le fait d'avoir un message d'erreur ne me pose pas plus de problèmes que ça. Par contre, ce qui m'embête c'est le fait que ce message est plutôt vague. Il me faut donc avoir un logging plus détaillé.

persistence.xml

Pour ce faire, j'ai activé les logging de requêtes dans persistence.xml

 

C'est un bon début, mais je ne vois toujours pas les requêtes de création de tables qui m'intéressent...

log4j.properties

La première chose à faire est d'ajouter un fichier "log4j.properties" au bon endroit dans ce projet qui utilise "Maven" : Voici le contenu du fichier. J'y suis allé franchement en mettant les niveaux de logging à "debug" de manière à récupérer un maximum d'informations.

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
 
log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=debug, stdout
log4j.logger.org.hibernate.SQL=debug, stdout
log4j.logger.org.hibernate.type=debug, stdout
log4j.logger.org.hibernate.engine.QueryParameters=debug, stdout

Solution

En fouillant dans ce logging très détaillé, je trouve le problème suivant :

09:12:59,704 DEBUG SchemaExport:415 -
    create table NOM_DE_LA_TABLE (
        CLE integer not null,
        ...
        primary key (CLE)
    ) type=InnoDB
Cette requête n'est pas correcte. "type=InnoDB" ne fonctionne pas avec ma version de MySQL, il faudrait "Engine=InnoDB". Je dois donc, simplement, changer le dialecte SQL :
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>

Conclusion

En fait, j'avais créé moi-même le problème en utilisant le mauvais dialecte MySQL. Mais, sans un bon système de logging, je n'avais aucun moyen de m'en apercevoir. Je me dis que ça peut arriver à n'importe qui...

Java, machine à états et SCXML

Le problème

Il y a quelque temps, je devais développer un logiciel pour un client qui contenait beaucoup de boutons de commande. Pour la plupart des boutons, il y a des conditions du genre :

  • Si on clique sur "Ajouter" et qu'une édition est en cours ...
  • Si on clique sur "Enregistrer" et que c'était un ajout ...
  • Si on est en train éditer ou d'ajouter une donnée ...

Étant donné la quantité de boutons et de conditions, je me retrouvais rapidement dans un situation pénible pour gérer tous les cas de figure. De plus, je n'étais pas convaincu que le mandant arrivait à m'aider à définir toutes les conditions avant l'écriture du code. Donc, je m'attendais à une phase de tâtonnement avant de livrer la première version.

La proposition de solution

Il se trouve que, par hasard, à ce moment-là je suivais un cours sur la modélisation avec Monsieur Medard Rieder qui est très versé dans le développement d'applications embarquées. Nous avons notamment parlé de logiciels de commande d’ascenseurs. La problématique est assez comparable à la mienne. Beaucoup de boutons de commande et des conditions du genre :

  • Si l'utilisateur choisi le deuxième alors qu'il est au rez ...
  • Si un utilisateur appelle l'ascenseur ...
  • Si quelqu'un appelle ascenseur alors qu'il est au même étage ...

Pour résoudre ce problème, cela fait longtemps que les électroniciens ont résolu ce problème. Pour ce faire ils utilisent les machines à états (Finite State Machine).

Rational Rose

Pour ce cours de modélisation, nous avons utilisé Rational Rose. Concernant les machines à états, ce logiciel permet de les modéliser en UML grâce au diagramme d'états-transitions. Ensuite, le code source peut être généré dans différents langages de programmation.

Le but est atteint, mais à quel prix ? Rational Rose est un excellent produit, ce que je viens de présenter n'est qu'une infime partie de la partie émergée de l'iceberg. Le revers de la médaille  c'est que les licences sont coûteuses et donc largement disproportionnées pour résoudre mon problème de base.

Produit plus réaliste pour mes besoins

Ce que j'aimerais c'est rational rose, mais en moins cher. Je m'attends donc à devoir faire des compromis, mais voici les points importants

  • Représentation graphique de la machine à états (idéalement UML)
  • Passage automatique de la version graphique au code source (Java dans mon cas)
  • Bon marché

Editeurs UML

D'abord, je me suis concentré sur les produits concurrents à Rose, mais open source. Tout ce que j'ai vu était nettement inférieur à ma référence, mais également beaucoup moins onéreux.

Il y a d'abord  les logiciels de schématique UML que j'utilise régulièrement : Violet et UMLet Ils sont très simples et permettent de modéliser rapidement. Par contre le passage du modèle au code se faire manuellement.

ArgoUML permet de générer du code, mais d'après mes souvenirs, seulement pour le diagramme de classe.

Je n'avais pas tellement confiance en BOUML car l'auteur venait de se fâcher avec un administrateur de Wikipedia et qu'il voulait laisser tombé le projet.

SCXML

Ensuite, j'ai cherché un éditeur de machine à états et je suis tombé rapidement sur SCXML.

  • Fondation Apache
  • Normalisation W3C
  • Editeur graphique scxmlgui.

Par contre la symbolique n'est pas l'UML, mais bon le rapport qualité/prix m'a eu l'air suffisant pour l'étudier attentivement...

LumisComparator

LumisComparator est un utilitaire pour UltraSoft AG qui permet de comparer les données de deux bases de données du programme Lumis.

Page principale de LumisComparator

  • Le programme ouvre la même table dans les deux bases de données à comparer.
  • Ensuite, il fait un "merge" des clés primaires pour que chaque table ait les mêmes lignes.
  • Et enfin, il colorie les données différentes

Ce petit utilitaire a été écrit en Delphi. Il a nécessité une quinzaine d'heures de développement. En plus de ce qui est décrit plus haut, il est capable d'extraire certaines données plus complexes (comme un fichier compressé dans un champ blob) et de demander à WinMerge de les différencier.

SCC

SCC est l'abréviation de SubCortex Client et SubCortex est le dépôt SubVersion qui contient le code source du projet Cortex.

Pour la gestion des versions, j'ai dû mettre en oeuvre un serveur SubVersion pour la société UltraSoft AG. Le choix de SubVersion était dicté par le mandant, car il possède déjà plusieurs serveurs de ce type pour d'autres projets.

Le projet Cortex est assez complexe. Il s'agit en réalité d'une vingtaine de projets et sous-projets qui constituent un framework permettant de construire rapidement des applications Web.

Pour gérer les dépendances entre les différentes versions des sous-projets, l'outil Maven a été utilisé. La combinaison Maven/SubVersion donne de très bons résultats. Le seul problème est qu'avec autant de projets, il est difficile pour les développeurs de gérer les bonnes versions. Il faut systématiquement ouvrir le pom.xml de tous les projets et gérer les dépendances à la ligne de commande. Mon client m'a donc demandé de réaliser un outil pour simplifier ces opérations...

Le programme SCC est développé en Java/Swing. Il utilise la librairie "snvkit" pour dialoguer avec le serveur SubVersion et une poignée de routines récursives pour les lectures sur le disque et l'affichage sous forme d'arbre.

La partie gauche de l'application présente tous les projets du dépôt et la partie droite affiche les différents outils.

SCC : page principale

Par exemple, un code de couleur montre les dépendances entre les différentes versions de sous-projets
SCC : Dépendances

Ou alors, la partie droite permet de visualiser le fichier "pom.xml"
SCC : pom.xml

Une fois le projet choisi dans l'arbre. Un simple click permet de télécharger l'ensemble des sources du projet et de tous les sous-projets avec lesquels il y a des dépendances.