188 votes

Obtenir la version de l'artefact Maven au moment de l'exécution

J'ai remarqué que dans le JAR d'un artefact Maven, l'attribut project.version est inclus dans deux fichiers :

META-INF/maven/${groupId}/${artifactId}/pom.properties
META-INF/maven/${groupId}/${artifactId}/pom.xml

Existe-t-il un moyen recommandé de lire cette version au moment de l'exécution ?

0 votes

279voto

Joachim Sauer Points 133411

Vous ne devriez pas avoir besoin d'accéder aux fichiers spécifiques à Maven pour obtenir les informations de version d'une bibliothèque/classe donnée.

Vous pouvez simplement utiliser getClass().getPackage().getImplementationVersion() pour obtenir les informations de version stockées dans un fichier .jar. MANIFEST.MF . Heureusement, Maven est assez intelligent Malheureusement, Maven n'écrit pas les informations correctes dans le manifeste par défaut !

Au lieu de cela, il faut modifier le <archive> de l'élément de configuration de l maven-jar-plugin pour fixer addDefaultImplementationEntries y addDefaultSpecificationEntries a true comme ceci :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>                   
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
</plugin>

Idéalement, cette configuration devrait être placée dans la société pom ou une autre base-pom.

Une documentation détaillée de la <archive> se trouve dans l'élément Documentation sur les archives Maven .

6 votes

Malheureusement, tous les chargeurs de classes ne semblent pas charger ces propriétés à partir du fichier manifeste (je me souviens avoir eu des problèmes avec Tomcat dans ce cas précis).

0 votes

@avithan : vraiment ? Je n'ai jamais eu de problème avec Tomcat avec cette approche. De plus, je pense qu'un classloader qui ignore le manifeste n'est probablement pas conforme.

0 votes

@JoachimSauer ok, j'avais tort. Actuellement, il semble que cela fonctionne très bien sur HotSpot mais ne fonctionne pas de manière fiable sur OpenJDK. Je ferai un rapport lorsque j'aurai des informations détaillées

79voto

Rob Points 402

Pour faire suite à la réponse ci-dessus, pour un .war je me suis aperçu que je devais appliquer la configuration équivalente à maven-war-plugin plutôt que maven-jar-plugin :

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1</version>
    <configuration>
        <archive>                   
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
</plugin>

Cela a ajouté l'information sur la version à MANIFEST.MF dans le cadre du projet .jar (inclus dans WEB-INF/lib de la .war )

3 votes

<archiveClasses>true</archiveClasses> a provoqué une erreur dans mon cas. Mais le problème a été résolu stackoverflow.com/questions/14934299/

12 votes

Lorsque j'essaie de le faire, mon résultat est toujours null bien que le fichier MANIFEST.MF des fichiers de guerre contienne les informations correctes.

0 votes

J'ai également dû l'ajouter à maven-assembly-plugin

29voto

mysomic Points 638

Voici une méthode pour obtenir la version à partir du pom.properties, en revenant à l'obtenir à partir du manifest.

public synchronized String getVersion() {
    String version = null;

    // try to load from maven properties first
    try {
        Properties p = new Properties();
        InputStream is = getClass().getResourceAsStream("/META-INF/maven/com.my.group/my-artefact/pom.properties");
        if (is != null) {
            p.load(is);
            version = p.getProperty("version", "");
        }
    } catch (Exception e) {
        // ignore
    }

    // fallback to using Java API
    if (version == null) {
        Package aPackage = getClass().getPackage();
        if (aPackage != null) {
            version = aPackage.getImplementationVersion();
            if (version == null) {
                version = aPackage.getSpecificationVersion();
            }
        }
    }

    if (version == null) {
        // we could not compute the version so use a blank
        version = "";
    }

    return version;
}

2 votes

Mettez ça dans un bloc d'initialisation statique.

1 votes

Un bon conseil. Cependant, si vous l'utilisez dans une servlet (ou un .jsp), assurez-vous d'utiliser getServletContext().getResourceAsStream au lieu de getClass().getResourceAsStream.

4 votes

Cela ne fonctionne que lorsque l'application est exécutée à partir du jar. Si elle est exécutée à partir de exec-maven-plugin (par exemple Netbeans), la ressource est nulle.

7voto

千木郷 Points 305

J'utilise maven-assembly-plugin pour mon packaging maven. L'utilisation de Apache Maven Archiver en La réponse de Joachim Sauer pourrait également fonctionner :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution .../>
    </executions>
</plugin>

Parce que Archiever est l'un des composants partagés maven il pourrait être utilisé par plusieurs plugins de construction maven, ce qui pourrait également entraîner des conflits si deux ou plusieurs plugins sont introduits, notamment archive configuration à l'intérieur.

4voto

darefilz Points 413

Si vous utilisez Spring Boot, vous pouvez utiliser la fonction BuildProperties classe.

Prenez l'extrait suivant de notre classe de configuration OpenAPI comme exemple :

@Configuration
@RequiredArgsConstructor // <- lombok
public class OpenApi {

    private final BuildProperties buildProperties; // <- you can also autowire it

    @Bean
    public OpenAPI yourBeautifulAPI() {
        return new OpenAPI().info(new Info()
            .title(buildProperties.getName())
            .description("The description")
            .version(buildProperties.getVersion())
            .license(new License().name("Your company")));
    }
}

0 votes

C'est exactement le cas d'utilisation qui m'a poussé à chercher des solutions pour exécuter les détails de Maven, comme c'est pratique ! Peut-être que cela devrait faire l'objet d'une autre question, mais c'est quand même pratique. Merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X