Design patterns utilisés dans le JDK

Pour faire suite à mon précédent article sur les design patterns, j'ai trouvé intéressant, dans un souci de "culture générale", de publier un simple lien vers une liste quasi-exhaustive des différents patterns utilisé au sein-même du JDK, ainsi que leurs rôles. Bonne lecture!


Fichier(s) joint(s) :

Obtenir un graphique de dépendances Maven

Il arrive assez souvent d'avoir besoin de savoir quelle version de librairie est liée à quelle dépendance, afin par exemple de résoudre des conflits de versions... Pour ceci, il est nécessaire d'établir un arbre des dépendances du ou des projets en question. Voici trois méthodes qui devraient subvenir à tous les besoins :

La première et la plus simple tout d'abord. Maven fournit la possibilité d'afficher dans console tous les liens entres les librairies, par projets. Pour ce faire, rendez-vous à cette adresse pour configurer le POM du projet principal. Il ne reste ensuite plus qu'à lancer la ligne de commande : mvn dependency:tree pour afficher quelque chose du genre :

Ceci peut être utile pour avoir accès rapidement à certaines informations, mais il faut avouer que ce n'est pas très lisible... Qui plus est, ce bloc de dépendances est généré uniquement par projet, difficile donc de faire des croisements dans le cas des projets multi-modules (reactors).

Il est alors possible d'obtenir une version plus graphique et élégante des dépendances grâce au plugin Eclipse pour Maven m2Eclipse fournit par la société Sonatype (éditrice de Maven). La dernière version est devenue très stable et permet de combler les précédentes lacunes d'Eclipse vis-à-vis de Netbeans concernant l'intégration de Maven. Entre autres choses, il est aisé de générer des graphes du style :

Beaucoup plus intéressant! Mais là encore une fois, une limitation importante est l'impossibilité de créer un graphique inter-modules...

Note : L'update site indiqué sur le site officiel de m2eclipse pour son installation ne fonctionne que pour des version de l'IDE supérieures ou égales à Ganymede (3.5), comme l'indique le bug ouvert ici.

Pour finalement arriver à nos fins, il faut utiliser le plugin Maven "Maven Graph Plugin". Il est utilisable sous deux modes, dont "reactor", qui permettra de lancer la création de l'arbre depuis un POM parent contenant plusieurs modules :

Voici donc un panel d'outils qui vous permettra de créer des graphiques très pratiques et rapidement exploitables de vos dépendances.


Fichier(s) joint(s) :



Maven, Hibernate et Persistence provider...

Ce post a pour but d'expliquer les différentes raisons pour lesquelles, lors du lancement d'une application packagée sous forme de jar par Maven, est parfois levée l'erreur :

javax.persistence.PersistenceException: No Persistence provider for EntityManager named ...

Pour changer des mes habitudes, l'environnement de développement utilisé ici est Netbeans, mais les instructions que je vais donner sont valables également pour Eclipse.

Il y a 3 choses à vérifier pour corriger ce problème, de la plus simple à la plus compliquée :


  1. Vérifier la présence du fichier de configuration hibernate persistence.xml dans le projet, au bon endroit! Sous Netbeans, il doit se trouver à ce niveau :
    Pour le créer, il est possible d'utiliser l'assistant 'Nouveau fichier'>'Catégorie Persistence'>'Type Persitence Unit'

  2. Le contenu du fichier persistence.xml doit être de la forme :
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.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_1_0.xsd">
      <persistence-unit name="PU_NAME" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>my.class.EntityName</class>
        <class>...</class>
        <properties>
          <property name="hibernate.connection.username" value="username"/>
          <property name="hibernate.connection.driver_class" value="driver_class"/>
          <property name="hibernate.connection.password" value="password"/>
          <property name="hibernate.connection.url" value="jdbc:..."/>
          <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.TheDialect"/>
          <property name="hibernate.show_sql" value="false"/>
        </properties>
      </persistence-unit>
    </persistence>
    

  3. Si vous arrivez ici, c'est que les choses se compliquent pour vous! ;) En effet, malgré l'assurance du fait que le fichier de configuration soit placé au bon endroit, il se peut que l'erreur continue de se produire... C'est ce qui se passait dans mon cas : lorsque je lançait mon application depuis l'IDE, tout fonctionnait à merveille. Mais lorsque je voulais l'exécuter en ligne de commande depuis le jar produit par Maven, plus rien à faire... Et même si l'erreur renvoyée est toujours la même, le problème se situe en réalité du côté des dépendances que Maven n'a pas résolues. En effet, puisque nous avons déclaré dans le fichier de configuration hibernate, le provider org.hibernate.ejb.HibernatePersistence, il faut inclure de manière explicite la dépendance suivante dans le pom.xml du projet, comme indiqué ici Doc Hibernate :
    <dependency>
      <artifactId>hibernate-entitymanager</artifactId>
      <groupId>org.hibernate.jpa</groupId>
      <type>jar</type>
      <version>3</version>
    </dependency>
    
    Mais va maintenant se poser le problème de toutes les autres dépendances liées à celle-ci... Mais alors, comment cela fonctionne-t-il dans l'IDE et pas en ligne de commande? La réponse vient de la faculté assez vicieuse pratique de Netbeans à se coupler à Maven : il se peut que vous ayez défini, dans l'IDE, une librairie pointant directement sur votre repository local Maven, comme ceci par exemple :
    Ce qui a pour conséquence de permettre à l'IDE de facilement trouver les librairies dont vous avez besoin pour votre projet, mais de ne finalement pas les lui lier directement... D'où leur absence lors du build Maven... Pour régler ceci, il faut déclarer dans le pom TOUTES les dépendances nécessaires au projet! Afin que Maven puisse les récupérer tout seul comme un grand. Pour ce faire, dans Netbeans, vous pouvez sélectionner les librairies du projet et utiliser l'action "Declare as direct dependency" :
    Et le tour est joué! Le build Maven va maintenant pouvoir clairement récupérer tout le nécessaire au projet et permettre son exécution de manière indépendante en ligne de commande.

La morale de cette histoire est de toujours vérifier, lors de développements d'applications vouées à être utilisées aussi bien depuis un IDE que de manière autonomes (via un jar construit par Maven), que l'IDE n'a pas été un peu trop "zélé" dans son rôle de "facilitateur" dans la mise en place du projet...


Fichier(s) joint(s) :



Eclipse over the rainbow... Java up high...

Toujours plus haut dans les nuages avec Eclipse! Pourquoi se contenter de gérer les sources des projets sur des serveurs distants partagés, alors qu'il est désormais possible de se passer d'IDE? C'est en gros le message que vient de faire passer la fondation Eclipse en annonçant la naissance d'un nouveau projet dans son écosystème : Orion.

Mais il ne faut pas s'y tromper : le but ici n'est pas de porter l'IDE dans un navigateur, mais bien de présenter un tout nouveau paradigme dans le monde du développement. La tendance actuelle étant de tout orienter vers les navigateurs web (est-ce bien raisonnable au fond?), la fondation Eclipse ne pouvait manquer cette occasion pour repenser ses outils et envisager le navigateur comme une toute nouvelle plateforme de développement.

Orion a donc pour vocation de fournir un outil léger par l'intermédiaire d'une expérience web. Son état encore embryonnaire à ce jour ne permet pour le moment que l'écriture de code Javascript, mais le but est de fournir d'ici quelques mois un panel plus complet notamment par l'ajout du versionage des fichiers (grâce à une intégration avec Git) et du debug (à l'aide de Firebug). Son interface est entièrement codée en Javascript et communique avec des librairies Java/Osgi par l'intermédiaire de REST.

Le code d'Orion est d'ores-et-déjà testable et téléchargeable ici. Même s'il est pour l'instant très limité, il faut admettre que l'idée peut paraître intéressante et qu'il faudra donc garder un oeil attentif sur son évolution.

Comme précisé plus haut, ce projet s'inscrit dans la volonté future d'Oracle de déporter les utilisations actuelles de Java en général, comme l'illustre les liens ce-dessous. A ce titre, Java EE 6 et plus tard (2012 environ) Java EE 7 vont proposer toujours plus d'outils pour déployer les applications vers le web. Plusieurs sociétés se positionnent déjà en tant que prestataires PaaS, en particulier VMware qui a récemment annoncé un partenariat pour promouvoir ce concept au travers du projet VMforce.

Sources

Java in the cloud


Fichier(s) joint(s) :



[Swing] Limiter la saisie dans une combobox editable

Plus compliqué qu'il n'y parait!

Le composant qui permet de saisir du texte dans ce type de combobox est un simple JTextField, mais il est impossible de paramétrer son nombre de caractères maximal aussi simplement qu'avec un JTextField classique.

Le text field est accessible grâce au code suivant :

JTextField tf = (JTextField)(combo.getEditor().getEditorComponent());

La solution consiste donc à modifier l'objet Document associé au champ (ici la limite sera fixée à 32 caractères) :

tf.setDocument(new JTextFieldLimit(32));

class JTextFieldLimit extends PlainDocument {
    private int limit;
    JTextFieldLimit(int limit) {
        super();
        this.limit = limit;
    }
    @Override
    public void insertString(int offset, String str, AttributeSet attr) {
        try {
            if (str == null)
                return;
            if ((getLength() + str.length()) <= limit) {
                super.insertString(offset, str, attr);
             }
        } catch (BadLocationException e) {}
    }
}

Un problème persiste cependant : à chaque fois que l'utilisateur essaiera de taper plus de 32 caractères, une erreur sera levée dans la console :

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: bad position: 33
        at javax.swing.text.JTextComponent.moveCaretPosition(JTextComponent.java:1523)
        at org.jdesktop.swingx.autocomplete.AbstractAutoCompleteAdaptor.markText(AbstractAutoCompleteAdaptor.java:116)
        at org.jdesktop.swingx.autocomplete.AutoCompleteDocument.insertString(AutoCompleteDocument.java:161)
        at javax.swing.text.JTextComponent.replaceSelection(JTextComponent.java:1358)
...

Cette erreur est volontairement levée par le composant java afin de maximiser la rétro-compatibilité, comme justifié dans ce bug : Oracle bug database (4903033). Il faut donc s'en contenter ou arriver à encapsuler suffisamment le composant pour récupérer l'erreur.


Fichier(s) joint(s) :