Obtenir la version d'artefact de Maven à l'exécution

j'ai remarqué que dans un bocal D'artéfact Maven, le projet.l'attribut version est inclus dans deux fichiers:

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

y a-t-il une façon recommandée de lire cette version à l'exécution?

149
demandé sur bluish 2010-04-26 15:20:49

7 réponses

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 sont stockées dans une .jar fichiers MANIFEST.MF . heureusement Maven est assez intelligent malheureusement Maven n'écrit pas les informations correctes au manifeste aussi bien par défaut!

à la place, il faut modifier le <archive> élément de configuration du maven-jar-plugin pour mettre addDefaultImplementationEntries et addDefaultSpecificationEntries à 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 mise dans la société pom ou une autre base-pom.

la documentation détaillée de l'élément <archive> se trouve dans la Maven Archive documentation .

227
répondu Joachim Sauer 2014-02-08 22:51:59

pour donner suite à la réponse ci-dessus, pour un artefact .war , j'ai trouvé 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>

ceci a ajouté les informations de version à MANIFEST.MF dans le projet .jar (inclus dans WEB-INF/lib du .war )

66
répondu Rob 2018-02-21 13:46:43

Voici une méthode pour obtenir la version à partir de la pom.propriétés, retombant à l'obtention à partir du Manifeste

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;
} 
24
répondu mysomic 2014-06-30 20:03:28

j'ai passé du temps sur les deux principales approches ici et ils n'ont pas fonctionné pour moi. J'utilise Netbeans pour les constructions, peut-être qu'il y en a d'autres là-bas. J'ai eu quelques erreurs et avertissements de Maven 3 avec quelques constructions, mais je pense que ceux-ci étaient faciles à corriger. Pas trop grave.

j'ai trouvé une réponse qui semble maintenable et simple à mettre en œuvre dans cet article sur DZone:

j'ai déjà un sous-dossier resources/config, et j'ai nommé mon fichier: app.propriétés, pour mieux refléter le genre de choses que nous pouvons y conserver (comme une URL de soutien, etc.).

la seule réserve est que Netbeans donne un avertissement que L'IDE doit être filtré. Vous ne savez pas où/comment. Il n'a pas d'effet à ce point. Il y a peut-être un travail pour ça si je dois traverser ce pont. Le meilleur de chance.

3
répondu will 2014-07-25 14:23:41

pour obtenir cette exécution dans Eclipse, ainsi que dans une construction Maven, vous devez ajouter les entrées addDefaultImplementationEntries et addDefaultSpecificationEntries pom comme décrit dans d'autres réponses, puis utiliser le code suivant:

public synchronized static final String getVersion() {
    // Try to get version number from pom.xml (available in Eclipse)
    try {
        String className = getClass().getName();
        String classfileName = "/" + className.replace('.', '/') + ".class";
        URL classfileResource = getClass().getResource(classfileName);
        if (classfileResource != null) {
            Path absolutePackagePath = Paths.get(classfileResource.toURI())
                    .getParent();
            int packagePathSegments = className.length()
                    - className.replace(".", "").length();
            // Remove package segments from path, plus two more levels
            // for "target/classes", which is the standard location for
            // classes in Eclipse.
            Path path = absolutePackagePath;
            for (int i = 0, segmentsToRemove = packagePathSegments + 2;
                    i < segmentsToRemove; i++) {
                path = path.getParent();
            }
            Path pom = path.resolve("pom.xml");
            try (InputStream is = Files.newInputStream(pom)) {
                Document doc = DocumentBuilderFactory.newInstance()
                        .newDocumentBuilder().parse(is);
                doc.getDocumentElement().normalize();
                String version = (String) XPathFactory.newInstance()
                        .newXPath().compile("/project/version")
                        .evaluate(doc, XPathConstants.STRING);
                if (version != null) {
                    version = version.trim();
                    if (!version.isEmpty()) {
                        return version;
                    }
                }
            }
        }
    } catch (Exception e) {
        // Ignore
    }

    // Try to get version number from maven properties in jar's META-INF
    try (InputStream is = getClass()
        .getResourceAsStream("/META-INF/maven/" + MAVEN_PACKAGE + "/"
                + MAVEN_ARTIFACT + "/pom.properties")) {
        if (is != null) {
            Properties p = new Properties();
            p.load(is);
            String version = p.getProperty("version", "").trim();
            if (!version.isEmpty()) {
                return version;
            }
        }
    } catch (Exception e) {
        // Ignore
    }

    // Fallback to using Java API to get version from MANIFEST.MF
    String version = null;
    Package pkg = getClass().getPackage();
    if (pkg != null) {
        version = pkg.getImplementationVersion();
        if (version == null) {
            version = pkg.getSpecificationVersion();
        }
    }
    version = version == null ? "" : version.trim();
    return version.isEmpty() ? "unknown" : version;
}

si votre Java build place des classes cibles ailleurs que" target/classes", vous devrez peut-être ajuster la valeur de segmentsToRemove.

1
répondu Luke Hutchison 2016-07-05 01:05:33

j'utilise maven-assembly-plugin pour mon emballage maven. L'utilisation de Apache Maven Archiver dans 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>

comme archiever est l'un des maven shared components , il pourrait être utilisé par plusieurs plugins maven building, qui pourraient également avoir des conflits si deux ou plusieurs plugins introduits, y compris la configuration archive à l'intérieur.

1
répondu 千木郷 2017-05-23 11:33:17

variante Java 8 pour EJB dans le fichier war avec le projet maven. Testé sur EAP 7.0.

@Log4j // lombok annotation
@Startup
@Singleton
public class ApplicationLogic {

    public static final String DEVELOPMENT_APPLICATION_NAME = "application";

    public static final String DEVELOPMENT_GROUP_NAME = "com.group";

    private static final String POM_PROPERTIES_LOCATION = "/META-INF/maven/" + DEVELOPMENT_GROUP_NAME + "/" + DEVELOPMENT_APPLICATION_NAME + "/pom.properties";

    // In case no pom.properties file was generated or wrong location is configured, no pom.properties loading is done; otherwise VERSION will be assigned later
    public static String VERSION = "No pom.properties file present in folder " + POM_PROPERTIES_LOCATION;

    private static final String VERSION_ERROR = "Version could not be determinated";

    {    
        Optional.ofNullable(getClass().getResourceAsStream(POM_PROPERTIES_LOCATION)).ifPresent(p -> {

            Properties properties = new Properties();

            try {

                properties.load(p);

                VERSION = properties.getProperty("version", VERSION_ERROR);

            } catch (Exception e) {

                VERSION = VERSION_ERROR;

                log.fatal("Unexpected error occured during loading process of pom.properties file in META-INF folder!");
            }
        });
    }
}
0
répondu Fabi Yo 2018-03-09 09:34:13