রানটাইমে ম্যাভেন আর্টিক্ট সংস্করণ পান


177

আমি লক্ষ করেছি যে কোনও ম্যাভেন আর্টিক্টসের জেআর-তে, প্রজেক্ট.ভারশন বৈশিষ্ট্যটি দুটি ফাইলে অন্তর্ভুক্ত রয়েছে:

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

রানটাইমে এই সংস্করণটি পড়ার জন্য কি কোনও প্রস্তাবিত উপায় আছে?


উত্তর:


265

কোনও প্রদত্ত লাইব্রেরি / শ্রেণির সংস্করণ তথ্য পেতে আপনার মাভেন-নির্দিষ্ট ফাইল অ্যাক্সেস করার দরকার নেই।

আপনি getClass().getPackage().getImplementationVersion()একটি জাজার-ফাইলগুলিতে সঞ্চিত সংস্করণ তথ্যটি পেতে সহজেই ব্যবহার করতে পারেন MANIFEST.MFভাগ্যক্রমে মাভেন যথেষ্ট স্মার্ট, দুর্ভাগ্যক্রমে মাভেন ডিফল্টরূপে ম্যানিফেস্টে সঠিক তথ্যও লেখেন না!

পরিবর্তে এক পরিবর্তন করতে হয়েছে <archive>কনফিগারেশন উপাদান maven-jar-pluginসেটে addDefaultImplementationEntriesএবং addDefaultSpecificationEntriesকরতে trueভালো:

<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>

আদর্শভাবে এই কনফিগারেশনটি সংস্থা pomবা অন্য কোনও বেস-পমতে রাখা উচিত।

ম্যাভেন আর্কাইভ ডকুমেন্টেশনে<archive> উপাদানটির বিশদ নথিপত্র পাওয়া যাবে ।


6
দুর্ভাগ্যক্রমে প্রতিটি শ্রেণিবদ্ধ ব্যক্তি মেনিফেস্ট ফাইলটি থেকে এই সম্পত্তিগুলি লোড করে না বলে মনে হয় (টমক্যাটের সাথে ঠিক এই ক্ষেত্রে সমস্যা হচ্ছে মনে আছে)।
ডিওয়েজনার

@ অবিঠান: সত্যি? এই পদ্ধতির সাথে টমকেটের সাথে আমার কখনও সমস্যা হয়নি। এছাড়াও, আমি মনে করি যে কোনও শ্রেণিবদ্ধকারী যা ম্যানিফেস্টটিকে উপেক্ষা করে সম্ভবত এটি মেনে চলে না।
জোয়াকিম সৌর

@ জোছিমসৌর ঠিক আছে, আমি ভুল ছিলাম। বর্তমানে এটি হটস্পটে দুর্দান্ত কাজ করে বলে মনে হচ্ছে তবে ওপেনজেডিকে নির্ভরযোগ্য কাজ করে না। আমি যখন বিশদ তথ্য পেয়েছি তখন আমি পুনরায় প্রতিবেদন করব
1313

@ অ্যাভিশন আমার পক্ষে এটি প্রাসঙ্গিক (এবং আপনি কী রিপোর্ট করেছেন তা আমি দেখিনি) - আপনি কি এখনও বিশদ তথ্য পেয়েছেন?
থরবজর্ন রাভন অ্যান্ডারসন

4
দুর্ভাগ্যক্রমে প্রকল্পটি গ্রহ থেকে চালানো হয় বা "এমভিএন এক্সিকিউট: জাভা" ব্যবহার করে কাজ করে না।
জান 8

77

একটি জন্য উপরে উত্তর আপ অনুসরণ করতে, .warহস্তনির্মিত বস্তু, আমি দেখেছি আমি সমতূল্য কনফিগারেশন আবেদন করতে ছিল maven-war-pluginবদলে 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>

এই সংস্করণে তথ্য যোগ MANIFEST.MFপ্রকল্পের মধ্যে .jarঅন্তর্গত থাকে ( WEB-INF/libএর .war)


3
<অর্চিভক্লাশস> সত্য </ translation> আমার ক্ষেত্রে ত্রুটি ঘটেছে। কিন্তু সমস্যা মীমাংসিত পেয়েছিলাম stackoverflow.com/questions/14934299/...
পল Verest

10
আমি যখন এটি চেষ্টা করি তখন আমার ফলাফল সর্বদা হয় nullযদিও যুদ্ধের ফাইলগুলিতে MANIFEST.MF- এ সঠিক তথ্য থাকে।
thomas.mc.work

আমার এটিও
মাভেন

2
<संग्रह সংরক্ষণাগার> সত্য </ translation> মনে হয় অসম্পর্কিত
কার্ল কিল্ডন

1
@ রাফায়েলসিমোনেলি আমি সরিয়েছি <archiveClasses>true</archiveClasses>- এবং এটি তখন থেকেই নির্ভরযোগ্যভাবে কাজ করে।
thomas.mc.work

28

Pom.properties থেকে সংস্করণ পাওয়ার জন্য এখানে একটি পদ্ধতি রয়েছে, এটি ম্যানিফেস্টের কাছ থেকে ফিরে আসার জন্য ফিরে আসবে

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
এটি একটি স্ট্যাটিক ইনিশিয়ালাইজার ব্লকে রাখুন।
অপটেট করুন

1
সদুপদেশ. ।। যদিও, যদি আপনি একটি সার্ভলেট (অথবা .jsp) এই ব্যবহার করছেন, সেই বিষয়ে নিশ্চিত থাকুন getServletContext () getClass () getResourceAsStream পরিবর্তে getResourceAsStream ব্যবহার করতে
Sandman থেকে

3
অ্যাপ্লিকেশনটি জার থেকে চালানো হলে এটি কেবল কাজ করে। এক্সিকিউটিভ-ম্যাভেন-প্লাগইন (যেমন নেটবিয়ান) থেকে চালিত হলে উত্সটি শূন্য।
লাইফ গ্রুইনওল্ট্ট

এই কোডটি আমার মূল শ্রেণীর ডিফল্টের অংশ হবে! ধন্যবাদ !!
ওয়েন্ডেল

আমি এটিকে উইলের উত্তরের সাথে সরাসরি এগিয়ে এবং সহজ বজায় রাখতে বিকল্পের জন্য ব্যবহার করেছি।
javydreamercsw

3

আমি এখানে দুটি প্রধান পদ্ধতির জন্য কিছুটা সময় ব্যয় করেছি এবং তারা আমার পক্ষে কাজ করে নি। আমি বিল্ডগুলির জন্য নেটবিয়ান ব্যবহার করছি, সেখানে আরও কিছু চলছে। আমার কিছু ত্রুটি এবং কিছু নির্মাণের সাথে ম্যাভেন 3 থেকে সতর্কতা ছিল, তবে আমি মনে করি সেগুলি সংশোধন করা সহজ ছিল। কোনও বিগি নেই।

আমি একটি উত্তর পেয়েছি যা DZone- এ এই নিবন্ধে প্রয়োগযোগ্য এবং সহজ প্রয়োগ দেখতে পেয়েছে:

আমার কাছে ইতিমধ্যে একটি সংস্থান / কনফিগার সাব-ফোল্ডার রয়েছে এবং আমি আমার ফাইলে নাম রেখেছি: app.properties, আমরা সেখানে যে ধরণের জিনিস রাখতে পারি তা আরও ভালভাবে প্রতিফলিত করতে (সমর্থন URL, ইত্যাদি)।

কেবলমাত্র সাবধানতাটি হ'ল নেটবিন্স একটি সতর্কতা দেয় যে আইডিই ফিল্টারিংয়ের প্রয়োজন। কোথায় / কিভাবে তা নিশ্চিত নয়। এই সময়ে এটির কোনও প্রভাব নেই। আমার যদি সেতুটি পেরোনোর ​​দরকার হয় তবে তার জন্য প্রায় কাজ আছে। ভাগ্য সুপ্রসন্ন হোক.


3

আমি maven-assembly-pluginআমার ম্যাভেন প্যাকেজিংয়ের জন্য ব্যবহার করছি । ব্যবহারের এ্যাপাচি ম্যাভেন আর্কাইভার মধ্যে জোয়াকিম সয়ার এর উত্তর এছাড়াও কাজ করতে পারে:

<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>

আর্কিভারটি ম্যভেন শেয়ারড উপাদানগুলির মধ্যে একটি , এটি একাধিক মাভেন বিল্ডিং প্লাগইনগুলি ব্যবহার করতে পারে, যা archiveভিতরে কনফিগারেশন সহ দুই বা ততোধিক প্লাগইনগুলি চালু করা হলে বিরোধ হতে পারে ।


2

এটি Eclipse এ চলার পাশাপাশি কোনও মাভেন বিল্ডে পেতে, আপনার অন্যান্য জবাবগুলিতে বর্ণিত হিসাবে addDefaultImplementationEntriesএবং addDefaultSpecificationEntriesপম এন্ট্রি যুক্ত করা উচিত , তারপরে নিম্নলিখিত কোডটি ব্যবহার করুন:

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;
}

যদি আপনার জাভা বিল্ড "টার্গেট / ক্লাস" ব্যতীত অন্য কোথাও টার্গেট ক্লাস রাখে তবে আপনাকে সেগমেন্টটোরোমোভের মান সামঞ্জস্য করতে হতে পারে।


আপনি জানেন যে এটি ইউনিট পরীক্ষার জন্য কিনা আপনি ঠিক করতে পারেন System.getProperty("user.dir")/pom.xml। আমি দৃ sure়ভাবে নিশ্চিত যে এটি ডাব্লুটিপি-র জন্য নয় তবে অন্যান্য জিনিসের জন্যও হবে।
অ্যাডাম জেন্ট

এটি কেবলমাত্র তখনই কাজ করবে যদি আপনার প্রকল্পটি কোনও ডিরেক্টরিতে থাকে - আপনি যদি জারফাইলে ভিত্তিক কোনও প্রকল্প চালাচ্ছেন তবে আপনার সমাধান কাজ করবে না। আপনার ব্যবহার .getResource()বা প্রয়োজন .getResourceAsStream()
লুক হাচিসন

হ্যাঁ আমি ধরেই নিছিলাম যে আপনি ইতিমধ্যে জারটি পরীক্ষা করেছেন (আলা getResource)) এটি প্রথমে আপনি getResource দিয়ে পরীক্ষা করে দেখুন যদি এটি ব্যর্থ হয় তবে প্রকল্পটি এখনও কোনও জার হিসাবে তৈরি করা হয়নি যার অর্থ আপনি হয় এটি এগ্রিপস বা মাভেন থেকে চালাচ্ছেন যার অর্থ `System.getProperty (" user.dir ") / pom.xml । একমাত্র সমস্যা হ'ল এই পম ফাইলটি সত্যিকারের কার্যকর পম নয় (তবে এটি কিছু বৈশিষ্ট্য প্রসারিত হবে না) তবে আপনি যে গ্রহগ্রহের পথে পাচ্ছেন সেটিও নয়।
অ্যাডাম জেন্ট

1

আমার বসন্ত বুট অ্যাপ্লিকেশনটিতে, গ্রহণযোগ্য উত্তর থেকে সমাধানটি আমি সম্প্রতি আমার জেডি কে সংস্করণ 12-এ আপডেট না করা পর্যন্ত কাজ করেছে other অন্যান্য সমস্ত উত্তরও চেষ্টা করে দেখেছি এবং এটি কাজ করতে পারে না।

এই মুহুর্তে, আমি টীকাটির ঠিক পরে, আমার বসন্ত বুট অ্যাপ্লিকেশনটির প্রথম শ্রেণিতে নীচের লাইনটি যুক্ত করেছি @SpringBootApplication

@PropertySources({ 
        @PropertySource("/META-INF/maven/com.my.group/my-artefact/pom.properties")
})

পরে আমি যে কোনও শ্রেণিতে আমি এর মানটি ব্যবহার করতে চাই এবং তার appVersionজন্য আমার কাছে প্রকল্পের সংস্করণটি পেতে চাইলে বৈশিষ্ট্য ফাইল থেকে মান পেতে নীচেরটি ব্যবহার করি :

@Value("${version}")
private String appVersion;

আশা করি যে কাউকে সাহায্য করবে।


একাধিক পম ফাইল দিয়ে কীভাবে এটি করবেন? আমি একাধিক পোম ফাইল থেকে সংস্করণ লোড করতে চাই।
এইচএম

0

একটি সাধারণ সমাধান যা ম্যাভেন সামঞ্জস্যপূর্ণ এবং যে কোনও (তৃতীয় পক্ষেরও) শ্রেণীর জন্য কাজ করে:

    private static Optional<String> getVersionFromManifest(Class<?> clazz) {
        try {
            File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
            if (file.isFile()) {
                JarFile jarFile = new JarFile(file);
                Manifest manifest = jarFile.getManifest();
                Attributes attributes = manifest.getMainAttributes();
                final String version = attributes.getValue("Bundle-Version");
                return Optional.of(version);
            }
        } catch (Exception e) {
            // ignore
        }
        return Optional.empty();
    }

-1

ম্যাভেন প্রজেক্টের সাথে যুদ্ধের ফাইলে EJB এর জন্য জাভা 8 ভেরিয়েন্ট। 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!");
            }
        });
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.