Java

Le logger ruby avec son bloc

Alors que je m'amusais à étendre le Logger de base de Ruby, j'ai découvert que l'on pouvait utiliser le Logger comme ci-dessous :

Logger.debug { "My object is #{self.map(&:id)}" }

Par défaut, on l'utilise en fournissant une string en paramètre comme ceci : Logger.debug("My object is #{self.map(&:id)}").

La différence entre ces deux écritures ?

La première permet d'éviter d'évaluer la chaine qui sera loggé si elle n'en a pas besoin. Contrairement à la deuxième qui sera toujours évaluée même si vous ne la loggez pas. Ainsi le temps de traitement pourrais s'en faire ressentir.

Grâce à ça, on peux facilement éviter les fameux :

Logger.debug("My object is #{self.map(&:id)}") if Logger.level == Logger::DEBUG

En effet, ce genre de code est très fréquent en Java, pour gagner un petit peu en performance sans perdre ses logs.

[...]
Published on Mer 21 oct 2009 21:08
0 commentaires

Sortir un test Junit à partir d'un test Junit d'Eclipse

Au niveau de mon travail, on m'a demandé de réaliser une sortie console de nos tests unitaires. Hélas on a jamais pris le temps de réaliser un pom.xml complet (pour projet Maven) pour ainsi avoir toutes les dépendances nécessaires.

Comme toujours on m'a demandé de réaliser cette sortie assez rapidement. J'ai donc trouvé une petite bidouille pour arriver à réaliser mon test en console en conservant complètement mon classpath défini par Eclipse.

Tout d'abord il faut récupérer la commande réaliser par Eclipse pour lancer le test. Pour cela, il suffit de mettre un point d'arrêt dans son script Junit, lancer le script en mode « Debug » et ensuite quand le point d'arrêt à stopper le processus, un clic droit sur le thread permet de consulter le menu de propriété de lancement de ce thread.

On copie entièrement la ligne de commande qui est de la forme suivante :

C:\bea\jdk142_05\bin\javaw.exe -classpath ${CLASSPATH_DE_LANCEMENT}
-Xdebug 
-Xnoagent
-Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:1859 
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner 
-version 3 
-port 1858 
-testLoaderClass Org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader
-classNames ${CLASSE_LANCER_POUR_LE_TEST}

Dans mon exemple les variables ${} sont bien sûr différente. Je les ai remplacé pour limiter un peu la place prise par la ligne de commande.

Maintenant que vous avez cette ligne de commande, il suffit de faire quelque modification dessus et vous aurez votre ligne de commande complète. Les modifications à réaliser sont les suivantes :

  • Suppression de l'option -Xdebug
  • Suppression de l'option -Xnoagent
  • Suppression de l'option -Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:1859
  • Suppression de -port 1858
  • Transformer l'exécutable de lancement pas java.exe au lieu de javaw.exe
  • Transformer la classe de lancement par junit.textui.TestRunner au lieu de org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader qui est spécifique à Eclipse.

Maintenant que vous avez réalisé tous ces petits changements vous pouvez désormais lancer la ligne de commande obtenu de la façon suivante :

C:\bea\jdk142_05\bin\java.exe 
-classpath ${CLASSPATH_DE_LANCEMENT} 
junit.textui.TestRunner 
-version 3 
-classNames ${CLASSE_LANCER_POUR_LE_TEST}

Bien sûr il y a d'autres techniques qui sont de simplement récupérer le CLASSPATH par exemple et de le mettre dans notre ligne de commande.

[...]
Published on Jeu 27 sept 2007 08:34
0 commentaires

Technique de controleurs entre Hibernate et Struts

Dans un précédent billet sur Hibernate et les mappings, je me posais la question de savoir comment séparer au maximum chaques fonctions dans une application J2EE utilisant Hibernate et Struts. Voici donc la technique que j'ai fini par adopter, après réflexion. Cette technique est ma propre technique et n'est peut-être pas la meilleure.

Contexte

Dans une application J2EE utilisant Hibernate et Struts, nous utilisons classiquement 3 composants:

  • Les mappings Hibernate
  • Les DAO (Database Access Object) pour toutes les communications à la base de donnée
  • Les actions Struts pour la gestion des requêtes HTTP de l'utilisateur

Mais voilà avec ces 3 composants, les actions struts doivent utiliser les mappings Hibernate et les DAO. les DAO eux devront utiliser les mappings. Comme indiqué dans le schéma suivant :

Graphique représentant la communication DAO, Mapping et Action Struts

Il manque donc un composant intermédiaire entre les DAO et les mappings qui sera le composant à être utilisé par les actions Struts. ce composant est appelé «Controleur».

Les controleurs

Le but du controleur est de faire la liaison entre le mapping Hibernate et le DAO. En effet, le mapping doit être un objet le plus léger possible et n'avoir en conséquence que des attributs et leurs getter/setter. Par contre, les DAO ne stocke rien à part la Session de connection à la base de donnée. Ainsi le controleur n'a pour seul champ privé obligatoire que le mapping. On peux aussi lui adjoindre des données complémentaires qui seront issues de contraintes annexes et ainsi augmenter les possibilités d'attribut interne à la classe. Mais des méthodes de confort pourront aussi lui être ajoutées comme la méthode classique du save() qui se chargera de sauvegarder le mapping Hibernate dans la session du DAO. Il aura ainsi plusieurs constructeurs avec différentes possibilités. Par contre, il faudra faire attention au getter/setter de attribut qui ne sont pas issue du mapping et qui peuvent dépendre du constructeur. Une bonne gestion des erreurs et à prévoir. Ce système permet ainsi l'utilisation unique du controleur dans l'actions Struts. Celui-ci n'aura qu'à construire l'objet et l'utiliser. L'action Struts n'aura plus aucun dialogue avec les mappings et DAO. Comme montré sur le schéma suivant :

Graphique représentant la communication DAO, Mapping, Action Struts et Controleur

Cas des listes de mapping Hibernates

Dans certain cas, on veux avoir une information supplémentaire à un mapping et pour cela on utiliser les controleurs. Mais cette information peux nécessité un calcul. Hors, au niveau du DAO, nous ne récupérons qu'une liste d'objet de mapping. Pour ajouter des informations, il faudrait alors itérer sur tous les éléments et leur ajouter les éléments voulus. Cette technique n'est pas optimum dans le cas d'une utilisation partielle de la liste, comme avec l'utilisation de Display Tag qui n'affichera pas toutes les lignes et créera une pagination. La technique est donc de créer un objet héritant de ArrayList et de surcharger la méthode get(int). Au moment de l'appel de cette méthode, nous ne renvoyons plus de mapping, mais notre controleur se construit à partir d'une liste d'objet mapping. Le calcul des informations supplémentaires ne se fera donc plus que sur les objets réelement demandé et non sur tous les objets de la liste initiale.

Pourquoi cette implémentation ?

Je voulais par cette méthode n'obtenir que des objets le plus léger possible. En effet, je préfére que mon programme utilise plus de petits objets que moins d'objets, mais gros. Je voulais aussi que mes actions Struts soit le plus simple possible à lire. Car sans l'utilisation de ce procédé, je me retrouvais avec des actions comprenant énormément de ligne de code. Cette technique rend le code plus simple à lire et à comprendre. Je voulais aussi effectuer les traitements non nécessaire qu'à la fin pour ainsi permettre de n'effectuer que le nécessaire et éviter ainsi le superflu.

Pour les curieux, j'ai fait mes graphiques grâce à Graphivz que je ne maitrise hélas pas trop. Vous pouvez trouver les sources des scripts de création ici

Published on Mer 07 mars 2007 14:37
0 commentaires

Hibernate et les mappings

Salut, Je fais appel au net pour une logique de conception Java et surtout une aide sur Hibernate. En effet sans système de mapping Hibernate j'aurais trouvé la solution que je veux, mais là je veux utiliser au maximum de les possibilités d'Hibernate. Voici ce que je désire faire :

J'ai des listes avec un nom. Dans chaque listes, il y a des produits. Mais pour chaque listes il peux y avoir plusieurs fois le même produit. Voici les deux solutions que j'ai au niveau SQL pur :

Tout en SQL

Cette solution se base sur le comptage du nombre de lien entre une liste et un produit.

CREATE TABLE List (
  id INT PRIMARY KEY,
  name VARCHAR,
);

CREATE TABLE Product (
  id INT PRIMARY KEY,
  name VARCHAR,
);

CREATE TABLE ListToProduct (
  id int PRIMARY KEY,
  Product_id int,
  List_id int,
);

Sur cette table pour savoir le nombre de produit A dans la liste B il faut faire en SQL pur une requête de type SELECT COUNT(*) FROM ListToProduct WHERE Product_id='A' AND List_id='B' où A et B sont les id respectif de notre produit et liste.

Au niveau d'hibernate, j'ai trouvé comment faire un mapping assez simple pour obtenir la liste des Produits d'un liste :

    <list name="listsName" table="ListToProduct" >
	<key column="product_id" />
        <index column="list_name_to_product_id" />
        <many-to-many column="list_id" class="List" />
    </list>

Au niveau du type de retour dans mon POJO, j'ai un attribut du type List<Produit>. Ca marche très bien dans un système de navigation entre mes produits et listes. Mais je me suis trouvé confronté au problème du comptage. Combien il y a de Produit A dans ma liste B. La seule solution est de faire :

  • Soit une requete SQL par ligne avec un COUNT(*)
  • Soit un parcours de ma liste pour compter le nombre d'occurrence.

Je ne pense pas qu'aucune de ces deux techniques soit très performante. De même je n'ai trouvé aucun système au sein d'hibernate pour avoir immédiatement le résultat. Comme dans une sous-requête avec un DISTINCT peut-être ?

Faire le comptage directement en base de Donnée

Normalement en SQL pur et propre il est recommandé de ne pas faire de calcul directement dans la Base de donnée. On ne doit rien stocker qui est potentiellement calculable. Dans notre cas, l'ajout du nombre de Produit dans la liste au niveau de la table de liaison permet de diminuer potentiellement le nombre de ligne d'enregistrement tout en augmentant le nombre de colonne. Théoriquement l'amélioration peux peux-être interressante si toutes nos listes ont en moyenne plus de 3 produits.

La nouvelle base de donnée serait donc identique à la précédente sauf la table ListToProduct qui serait la suivante :

CREATE TABLE ListToProduct (
  id int PRIMARY KEY,
  Product_id int,
  List_id int,
  count int,
);

Avec cette technique, au lieu de rajouter une ligne dans la table de liaison au moment de l'ajout d'un produit existant dans une liste, le compteur est incrémenté. Il ne reste donc ensuite qu'à lire la valeur dans count pour savoir le nombre exacte de Produit du type A dans la liste B. Cette technique me semble assez intéressantes. Mais voilà, je suis incapable de la mettre en place avec un mapping hibernate. J'ai testé les components, les many-to-one. Mais rien n'y fait. Il doit vraiment y avoir un truc que je n'ai pas compris et je ne sais pas quoi. C'est aussi pour ca que je fais appel à tous.

Donc si vous avez une idée sur la meilleur solution à employer et aussi comment la mettre en place avec Hibernate, je suis preneur.

Published on Mar 16 jan 2007 22:36
0 commentaires

Différence entre Netbeans et Eclipse Episode 2

Alors que j'ai encore passé une bonne soirée à installer mon environnement de développement et j'ai heureusement fini par y arriver. Maintenant je ne vais plus y toucher du tout et faire en sorte que ca soit stable. Je pense aussi avoir compris d'où vient le problème. En effet, mon projet a été créé avec une version d'eclipse plugger qui s'appele easyeclipse version 1.0.1 basé sur Eclipse 3.1. Chez moi j'ai donc voulu upgrader eclipse et passer par easyeclipse 1.2.1 qui est basé sur Eclipse 3.2. Mais voilà le changement de version est pas très apprécié par Eclipse. En conséquence, je pense que mes problèmes étaient principalement lié à cette modification d'environnement.

Ce qui m'amène au problème que je ressens avec Eclipse et son support SVN. En effet, une fois que tu as fait le premier commit de ton application avec une version d'Eclipse il ne faut pas changer. même pour d'autre version comme Lomboz ou MyEclipse. En effet, chacun d'eux a sa propre gestion des serveurs type Tomcat et ne permet d'attacher qu'un projet de leur jus au serveur. Mais par contre comme netbeans intégre de base une gestion de serveur type Tomcat, avec l'import SVN. Il est ainsi très facile de créer un projet web et de lui donner les valeurs de checkout de notre SVN. Alors qu'avec Eclipse en faisant un Checkout nous ne pouvons que créer un nouveau projet. Nous ne pouvons pas l'attacher à un projet existant :(.

Published on Jeu 21 déc 2006 09:01
0 commentaires

NetBeans et Eclipse pour du J2EE

Actuellement devant coder une application J2EE pour mon école, j'ai pris le temps de tester un peu deux gros IDE libres existant sur le marché pour développer du J2EE. Voici un très rapide comparatif que je vais faire.

Au premier abord Eclipse est de loin le meilleur, mais a de gros problèmes de plugin. Ainsi je me retrouve à ne plus pouvoir ouvrir une JSP sans faire planter eclipse, ce qui est assez gênant pour faire du J2EE.

En passant sous netbeans, j'y ai vu une intégration complète de gestion de serveur Web type TOMCAT ainsi, j'ai juste à définir mon contexte et tout est fait. Mais voilà j'ai trouvé un problème que je considère majeur dans le développement rapide d'application web, l'obligation de recréer complètement le projet à chaque déploiement. Ainsi, je suis obligé de copier mes sources, les compilés et créer un WAR pour enfin déployer l'application. Cela prend ainsi très facilement 5 min à faire et tout ça pour une application qui ne compte encore que 2 pages. Déjà que je pestais contre les 5 secondes de redémarrage de Tomcat, les 5 min seront hélas de trop pour moi. Espérons que cela sera implémenté dans les futurs version de netbeans et on aura un produit vraiment très sympa qui pourra complètement rivaliser avec Eclipse.

On voit tout de suite le problème de développement d'application J2EE, la compilation est très longue. C'est là que les langages de scripting permettent de gagner beaucoup de temps.

En tout cas après une soirée de tentative de mise en place d'un projet J2EE sur mon PC, je suis bon pour recommencer vu que je n'ai toujours pas réussi.

Published on Mer 20 déc 2006 08:27
1 comment

setOpaque true or false ?

La méthode setOpaque de la Classe Jcomponent a un comportement particulier. En effet, j'ai pris juste deux petites heures à trouver comment mettre un JLabel avec une couleur de fond. Une fois la métode setBackground(Color) utilisé, je ne constatais aucun résultat. J'ai donc quand même fini par comprendre.

En effet, la méthode setOpaque est à "false" dans le cas d'un JLabel, il n'est à true que pour les JButton. Maintenant que je le sais, je ne referais plus cette erreur.

Published on Ven 24 fév 2006 11:26
1 comment

RSS Follow me on Twitter