lundi 17 juin 2013

Les EJB et le classpath

Lorsqu'on créer un EJB dans un EAR, l'EJB a le même classpath que l'EAR qui le contient.
Voici un schéma représentant les classpaths :

Mais si l'EJB nécessite des dépendances qui ne sont pas dans ce classpath, comment faire alors pour fournir ces dépendances dans l'EAR et que seul l'EJB ai ces dépendance dans son classpath ?

La solution va être fournit par le plugin maven jar.
Celui-ci dispose d'une option addClasspath qui permet d'enrichir le fichier manifest du jar (MANIFEST.MF) afin d'ajouter explicitement des jars dans le classpath.
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  ...
  <configuration>
    <archive>
   <manifest>
     <addClasspath>true</addClasspath>
   </manifest>
    </archive>
  </configuration>
  ...
</plugin>
Le manifest ressemble alors à ceci :
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: ${user.name}
Build-Jdk: ${java.version}
Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar
Cette méthode n'est pas forcément très élégante. Mais puisque les dépendances sont dans l'EAR, cela dépanne avec un moindre impacte (pas de création de SharedLib en plus sous WebSphere par exemple).

lundi 3 juin 2013

Connaitre le type d'une liste genérique par introspection

En Java, il est possible de faire de l'introspection, c'est a dire de regarder à l'intérieur de l'objet.
Cela permet par exemple, de connaitre les champs privés ou public, les méthodes...

Imaginons maintenant, que vous fassiez de l'introspection sur un objet avec le code suivant :
objetInspecte = ....

// Tout les champs declarer, y compris prive
Field[] fields = objetInspecte.getClass().getDeclaredFields() ;
Class generiqueClass ;
// Valeur du champs introspecte
Object valeurDuChamps ;

for(Field field : fields) {
    // Rend le champ accessible et lecture/ecriture
    field.setAccessible(true);
                
    valeurDuChamps = field.get(objetInspecte) ;
}

Oui, mais voilà, vous avez un liste, de ce fait field.getType().getCanonicalName() renvoie java.util.List.
Très bien, maintenant vous pouvez faire un new ArrayList pour créer la liste si le champs est null.

A présent, vous souhaitez, dans cette liste ajouter un élément. Mais de quel type est cette liste ? String, Integer, un tout autre objet ?
Pour cela, Java fournit une API. Voici un exemple :
// Type pour les generique
ParameterizedType pt ;  
// Class generique
Class generiqueClass ;

// On recupere le type generique
pt = (ParameterizedType) field.getGenericType() ;
generiqueClass = (Class) pt.getActualTypeArguments()[0];

La valeur de generiqueClass ? Et bien nous découvrons, que c'est une liste de Date par exemple !
Pour créer un objet, rien de plus simple : generiqueClass.newInstance().