dimanche 21 octobre 2012

Créer des propriétés dynamiquement au sein d'un pom Maven

Pour compléter mon dernier post, voici comment résoudre le problème de version identique dans un manifest.

Il existe un plugin maven qui est une véritable boite à outils. Ce plugin vous aidera de très nombreuses fois, une fois que vous l'aurez découvert.
Ce plugin répond au doux nom de build-helper-maven-plugin et est disponible sur Codehaus.
Il contient un goal très intéressant qui permet de créer une variable dynamiquement en lui appliquant une expression régulière (ou rationnelle).
Voici dans notre cas, l'utilisation que nous pourrions en faire :
<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>build-helper-maven-plugin</artifactId>
 <version>1.7</version>
 <executions>
  <execution>
   <id>create-property-versionNonSnapshot</id>
   <goals>
    <goal>regex-property</goal>
   </goals>
   <configuration>            
    <name>project.versionNonSnapshot</name>
    <value>${project.version}</value>
    <!-- http://jira.codehaus.org/browse/MBUILDHELPER-34 -->
    <regex>(.*)-(SNAPSHOT)</regex>
    <replacement>$1</replacement>
    <failIfNoMatch>false</failIfNoMatch>
   </configuration>
  </execution>
 </executions>
</plugin>
Une variable project.versionNonSnapshot va être crée a partir de la valeur de project.version.
Ne sera gardé que la première partie soit la version sans snapshot.

A présent, si on reprend le code du prost précédent :
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                        <manifestEntries>
                            <Specification-Version>${project.versionNonSnapshot}</Specification-Version>
                        </manifestEntries>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
On obtient :
Specification-Version : 1.0.0
Implementation-Version : 1.0.0-SNAPSHOT

Je vous invite à découvrir ce plugin, véritable couteau suisse du développeur maven.

mardi 16 octobre 2012

Personnaliser le manifest d'un jar ou d'un war

Si vous créez un jar utiltaire à destination d'équipe utilisatrice, vous voudrez certainement que la commande de lancement du jar se résume à :
java -jar monjar.jar

Pour ce faire, il est possible avec maven, lors de la phase de package, d'ajouter des informations dans le manifest du jar.
Avec l'entrée Main-Class: com.maventest.App, une classe peut-être lancée automatiquement.

Pour cela, il est nécessaire d'ajouter dans le pom :
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.maventest.App</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

Ce principe peut être reprit aussi pour un war.

Ce qui est intéressant, c'est d'ajouter dans le manifest, l'entrée Specification-Version et Implementation-Version.
Cela permet de connaitre la version logique d'un service par exemple, et la version réel.
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
Ce qui donne :
Specification-Version : 1.0.0-SNAPSHOT
Implementation-Version : 1.0.0-SNAPSHOT
Inconvénient, la même version est répétée deux fois.
Dans le prochain post, j'expliquerais comment résoudre ce problème.

jeudi 11 octobre 2012

Rechercher un champs dans un des formulaires de la page

Il y a peu, on m'a demander d'aider quelqu'un a faire un code JavaScript pour rechercher un champs dans un formulaire.
Il fallait aussi que le code puisse renvoyer le formulaire si le nom cherché était le nom d'un formulaire.

Voici un exemple :
// Recherche par le nom donc l'element chercher est un input
function rechercherDansFormulaire(nomChamp) {                
    // Fonction qui affiche le nom de tous les formulaires
    // et de tous les les éléments d'un document HTML
    // Boucle tous les formulaire
    for (var i = 0; i < document.forms.length; i++) {
        // S'il s'agit d'un formulaire
        if (nomChamp == document.forms[i].name) {
            return document.forms[i] ;
        }
        
        // Boucle tous les éléments du formulaire i
        for (var l = 0; l < document.forms[i].elements.length; l++) {
            if (nomChamp == document.forms[i].elements[l].name) {
                return document.forms[i].elements[l] ;
            }
        }
    }

    return null ;
}

mercredi 3 octobre 2012

Personnaliser le filtre d'un JFileChooser

Afin de pouvoir personnaliser les filtres dans un JFileChooser, il est nécessaire de créer une classe héritant dans FileFilter.
Cette classe va retourner une description qui sera affichée dans la boite de dialogue en bas et surtout la méthode accept() qui va indiquer au JFileChooser s'il faut prendre en compte (et donc afficher dans la boite de dialogue) le fichier.
import java.io.File;

import javax.swing.filechooser.FileFilter;


public class FileExtension extends FileFilter {
 private String extension ;
 
 private String description ;
 
 public FileExtension(final String extension, final String description)
 {
  if (extension != null)
  {
   this.extension = extension.toLowerCase() ;
  }
  
  this.description = description ;
 }
 
 @Override
 public boolean accept(File f) {
  return (testFile(f.getAbsolutePath()) || f.isDirectory()) ;
 }

 @Override
 public String getDescription() {
  return description ;
 }

 private boolean testFile(final String fileName)
 {
  return ((extension != null) && (!"".equals(extension)) &&
    fileName.toLowerCase().endsWith(extension)) ;
 }
}
Ensuite, cette objet doit être ajouter à la liste des filtres du JFileChooser :
//Create a file chooser
fc = new JFileChooser() ;

// Delete previous filter (by default *.*)
fc.resetChoosableFileFilters();
fc.addChoosableFileFilter(new FileExtension("*.exe", "Executable file"));

lundi 1 octobre 2012

Les subtilités des versions JBoss

Voici un retour d'expérience sur une migration JBoss 3.5 vers 4.3.
Je n'avais encore jamais participé à aucune migration de ce type.
Nous avions fait des tests de chaque module et tout semblait correct. Pas de modification spécifique en vue.
Erreur !

Lors du test d'intégration, nous avons donc mis plusieurs WAR dans la même instance JBoss.
Ces modules utilisaient les mêmes librairies mais les embarquaient chacune dans leur WAR.
En effet, ces librairies contenaient des singletons propre à chaque application.

Phénomène étrange, les WAR semblaient partager le même classloader.

En effet, il n'est possible d'indiquer à JBoss, de ne pas partager le même classloader (java2ParentDelegation = false) que pour les EAR, dans sa configuration générale.
Pourtant, en JBoss 3.5 cela fonctionnait, alors que se passe-t-il ?

Du côté du fichier jboss-web.xml qui embarqué dans chaque WAR permet de configurer le comportement JBoss, tout semblait correct :
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">

<jboss-web>
 <class-loading>
  <loader-repository>
   nom_war:loader=nom.war
   <loader-repository-config>
    java2ParentDelegation=false
   </loader-repository-config>
  </loader-repository>
 </class-loading>

</jboss-web>
Après, une plongée dans la documentation de JBoss, un commentaire me met la puce à l'oreille.
Ce commentaire indique une particularité de JBoss 4.2.x à 5.0.0.

Le format que fichier à changé, pour ces versions, il faut :
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">

<jboss-web>

   <!-- Fonctionne uniquement avec JBoss de 4.2.x a 5.0.0 -->
   <loader-repository> 
      nom_war:archive=nom.war
   <loader-repository-config>
    java2ParentDelegation=false
   </loader-repository-config>
   </loader-repository> 

</jboss-web>
Attention, à partir de la version 6, on revient comme en 3.5 !