1

In ProjectA, I have a MethodA in ClassA, and ProjectA jar is added in different projects as a Maven dependency, and different projects are calling MethodA.

Requirement is

Whenever MethodA of ClassA is called by any other project, we would require to log the called project artifact id and version, considering ProjectA dependency is added in these projects pom.xml.

NOTE

Below works only on self project (ProjectA), creation of property file and turning on maven resource filtering

 Create a property file

 src/main/resources/project.properties
 with the below content

version=${project.version}
artifactId=${project.artifactId}
Now turn on maven resource filtering

<resource>
 <directory>src/main/resources</directory>
 <filtering>true</filtering>
</resource>

MethodA

public class ClassA {
    final static Logger logger = Logger.getLogger(ClassA.class);

    public void MethodA{
        final Properties properties = new Properties();
        properties.load(this.getClassLoader().getResourceAsStream("project.properties"));
        logger.info(properties.getProperty("version"));
        logger.info(properties.getProperty("artifactId"));
          } 
}

When called MethodA in Project B, I get the below output in logger

   version=${project.version}
   artifactId=${project.artifactId}    which is incorrect.

Expected output:

version = 1.0.0
artifactId = ProjectB

Is there any better way to log the calling project artifact id? If MethodA is called by ProjectC, we want to get ProjectC artifactid and version.

Requirement: We have 30+ projects calling MethodA from ProjectA, so we should not make any changes in the calling projects.

Bustaq
  • 159
  • 8
Rag
  • 23
  • 5
  • 3
    This might be an x-y problem. What exact information do you need and why? – Thorbjørn Ravn Andersen Jul 09 '21 at 18:49
  • Welcome to SO. Please first be advised to learn what an [MCVE](https://stackoverflow.com/help/mcve) is and why it is the right way to ask questions here. Furthermore, if you post code snippets, at least make sure they compile and run correctly. Nobody wants to fix your faulty code first, before actually addressing the problem as such. Thank you. – kriegaex Jul 10 '21 at 01:33
  • After our many comments under my answer, let us return to the core question asked by @ThorbjørnRavnAndersen: **Why** do you think you need that information at runtime? Why is the name of the calling class + method not enough? You could match them to Maven artifacts later. If you have the Maven coordinates, what are you going to do with them other than print them? What is the purpose of logging that information? I am pretty sure, you can achieve your real goal in other ways than the ones I suggested, even though those are viable under certain circumstances. – kriegaex Jul 12 '21 at 01:53
  • Thorbjorn and @kriegaex As you can see "Requirement" section in actual post description, we need to track the projects who are calling the projectA > class A functions. We are planning to get the called projects artifact and group name. – Bustaq Jul 13 '21 at 06:01
  • Why - to monitor the function calls . After logging those info's to central place, I would need to work on putting them to a graph after doing some manipulation. Thankyou for ur help . I am taking all ur suggestion and will keep updated with the solution working for me.Need some time. Don't be harsh. :) – Bustaq Jul 13 '21 at 06:15
  • @kriegaex it took some time for me to find the efficient solution to the gievn scenario. I added the solution below. thanks. – Rag Aug 08 '21 at 10:09

2 Answers2

2

Solution A: Maven resource filtering

Your POM snippet should replace the variables correctly, if you put it in the right POM section:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

You can inspect the result in the target/classes folder. After I fixed your faulty pseudo code by adding an empty argument list () to your method name and replaced the nonsensical this.getClassLoader() by getClass().getClassLoader(), the code even compiles and does something meaningful. Do you ever test before you post something to a public platform like StackOverflow?

import java.io.IOException;
import java.util.Properties;

public class ClassA {
  public void methodA() throws IOException {
    final Properties properties = new Properties();
    properties.load(getClass().getClassLoader().getResourceAsStream("project.properties"));
    System.out.println(properties.getProperty("version"));
    System.out.println(properties.getProperty("artifactId"));
  }

  public static void main(String[] args) throws IOException {
    new ClassA().methodA();
  }
}

Console log when running from IntelliJ IDEA after mvn compile (because we need Maven to process the resources and copy them to target/classes):

1.9.8-SNAPSHOT
util

Or whatever your module name and version are.

If you see the variable names instead, either your classpath does not point to the JAR but to the source directory somehow, or you have multiple modules with a project.properties file and in one of them forgot resource filtering. Whichever file is found first on the class path, will be loaded. So in a multi-module project, you better use different file names, otherwise it is more or less a lottery which one if found first.

The next problem would then be for your aspect or other module to know which resource file to load, so that better be linked to class or package names somehow in order for the other module to be able to guess the resource file from the package name. You do need clean package name separation between modules then. I really wonder if it is worth the trouble.

Solution B: Templating Maven Plugin + package-info.java + custom annotation

Another idea would be to use resource filtering or a plugin like org.codehaus.mojo:templating-maven-plugin for replacing the versions directly into package annotation values in a package-info.java file and then simply fetch the values during runtime from the package info. I made a quick & dirty local test with that plugin, and it works nicely. I recommend to keep it simple for now and just fix your resource filtering problem. If you need the more generic solution I just described, please let me know.

Project structure

Update: I extracted the quick solution I hacked into one of my projects into a new Maven multi-module project in order to show you a clean solution as follows:

Say, we have a parent POM with 3 sub-modules:

  • annotation - contains an annotation to be used on packages in package-info.java files. Can easily be modified to also be applicable to classes.
  • library - example library to be accessed by an application module
  • application - example application

You can find the full project on GitHub: https://github.com/kriegaex/SO_Maven_ArtifactInfoRuntime_68321439

The project's directory layout is as follows:

$ tree
.
├── annotation
│   ├── pom.xml
│   └── src
│       └── main
│           └── java
│               └── de
│                   └── scrum_master
│                       └── stackoverflow
│                           └── q68321439
│                               └── annotation
│                                   └── MavenModuleInfo.java
├── application
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── de
│       │   │       └── scrum_master
│       │   │           └── stackoverflow
│       │   │               └── q68321439
│       │   │                   └── application
│       │   │                       └── Application.java
│       │   └── java-templates
│       │       └── de
│       │           └── scrum_master
│       │               └── stackoverflow
│       │                   └── q68321439
│       │                       └── application
│       │                           └── package-info.java
│       └── test
│           └── java
│               └── de
│                   └── scrum_master
│                       └── stackoverflow
│                           └── q68321439
│                               └── application
│                                   └── ModuleInfoTest.java
├── library
│   ├── pom.xml
│   └── src
│       └── main
│           ├── java
│           │   └── de
│           │       └── scrum_master
│           │           └── stackoverflow
│           │               └── q68321439
│           │                   └── library
│           │                       └── LibraryClass.java
│           └── java-templates
│               └── de
│                   └── scrum_master
│                       └── stackoverflow
│                           └── q68321439
│                               └── library
│                                   └── package-info.java
└── pom.xml

Please note the src/java-templates directories in both the library and the application modules, containing package-info.java files. The directory name is the default for Templating Maven Plugin, making plugin configuration less verbose.

Parent POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
  <artifactId>maven-artifact-info-runtime</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>

  <modules>
    <module>annotation</module>
    <module>library</module>
    <module>application</module>
  </modules>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>templating-maven-plugin</artifactId>
          <version>1.0.0</version>
          <executions>
            <execution>
              <id>filter-src</id>
              <goals>
                <goal>filter-sources</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

</project>

Module annotation

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
    <artifactId>maven-artifact-info-runtime</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>annotation</artifactId>

</project>
package de.scrum_master.stackoverflow.q68321439.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface MavenModuleInfo {
  String groupId();
  String artifactId();
  String version();
}

Module library

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
    <artifactId>maven-artifact-info-runtime</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>library</artifactId>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>templating-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
      <artifactId>annotation</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>

</project>
package de.scrum_master.stackoverflow.q68321439.library;

public class LibraryClass {}

Please note that the following file needs to be located in library/src/main/java-templates/de/scrum_master/stackoverflow/q68321439/library/package-info.java. Here you can see how we use Maven properties to be replaced by their corresponding values during the build process by Templating Maven Plugin:

/**
 * This is the package description (...)
 */
@MavenModuleInfo(groupId = "${project.groupId}", artifactId = "${project.artifactId}", version = "${project.version}")
package de.scrum_master.stackoverflow.q68321439.library;

import de.scrum_master.stackoverflow.q68321439.annotation.MavenModuleInfo;

Module application

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
    <artifactId>maven-artifact-info-runtime</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>application</artifactId>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>templating-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
      <artifactId>annotation</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
      <artifactId>library</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>de.scrum-master.stackoverflow.q68321439</groupId>
      <artifactId>library</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>
package de.scrum_master.stackoverflow.q68321439.application;

public class Application {
  public static void main(String[] args) {}
}

Please note that the following file needs to be located in application/src/main/java-templates/de/scrum_master/stackoverflow/q68321439/application/package-info.java. Here you can see how we use Maven properties to be replaced by their corresponding values during the build process by Templating Maven Plugin:

/**
 * This is the package description (...)
 */
@MavenModuleInfo(groupId = "${project.groupId}", artifactId = "${project.artifactId}", version = "${project.version}")
package de.scrum_master.stackoverflow.q68321439.application;

import de.scrum_master.stackoverflow.q68321439.annotation.MavenModuleInfo;
package de.scrum_master.stackoverflow.q68321439.application;

import de.scrum_master.stackoverflow.q68321439.annotation.MavenModuleInfo;
import de.scrum_master.stackoverflow.q68321439.library.LibraryClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class ModuleInfoTest {
  @Test
  public void test() {
    String groupId = "de.scrum-master.stackoverflow.q68321439";

    MavenModuleInfo libMavenInfo = logAndGetMavenModuleInfo("Library Maven info", LibraryClass.class.getPackage());
    assertEquals(groupId, libMavenInfo.groupId());
    assertEquals("library", libMavenInfo.artifactId());

    MavenModuleInfo appMavenInfo = logAndGetMavenModuleInfo("Application Maven info", Application.class.getPackage());
    assertEquals(groupId, appMavenInfo.groupId());
    assertEquals("application", appMavenInfo.artifactId());
  }

  private MavenModuleInfo logAndGetMavenModuleInfo(String message, Package aPackage) {
    MavenModuleInfo moduleInfo = aPackage.getAnnotation(MavenModuleInfo.class);
    System.out.println(message);
    System.out.println("  " + moduleInfo.groupId());
    System.out.println("  " + moduleInfo.artifactId());
    System.out.println("  " + moduleInfo.version());
    return moduleInfo;
  }
}

Run Maven build

Now run the Maven build via mvn clean test:

(...)
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ application ---
[INFO] Surefire report directory: C:\Users\alexa\Documents\java-src\SO_Maven_ArtifactInfoRuntime_68321439\application\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running de.scrum_master.stackoverflow.q68321439.application.ModuleInfoTest
Library Maven info
  de.scrum-master.stackoverflow.q68321439
  library
  1.0-SNAPSHOT
Application Maven info
  de.scrum-master.stackoverflow.q68321439
  application
  1.0-SNAPSHOT
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.094 sec
(...)

Identifying the caller

Assuming that all calling modules implement the same scheme with package info + special annotation, you can print the caller info like this:

package de.scrum_master.stackoverflow.q68321439.library;

import de.scrum_master.stackoverflow.q68321439.annotation.MavenModuleInfo;

public class LibraryClass {
  public void doSomething() {
    StackTraceElement callerStackTraceElement = new Exception().getStackTrace()[1];
    try {
      Class<?> callerClass = Class.forName(callerStackTraceElement.getClassName());
      MavenModuleInfo mavenModuleInfo = callerClass.getPackage().getAnnotation(MavenModuleInfo.class);
      System.out.println(mavenModuleInfo.groupId());
      System.out.println(mavenModuleInfo.artifactId());
      System.out.println(mavenModuleInfo.version());
    }
    catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

  public void doSomethingJava9() {
    Class<?> callerClass = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass();
    MavenModuleInfo mavenModuleInfo = callerClass.getPackage().getAnnotation(MavenModuleInfo.class);
    System.out.println(mavenModuleInfo.groupId());
    System.out.println(mavenModuleInfo.artifactId());
    System.out.println(mavenModuleInfo.version());
  }

}

While doSomething() also works in old Java versions (tested on Java 8), on Java 9+ you can use the JEP 259 Stack-Walking API as shown in doSomethingJava9(). In that case, you do not need to manually parse an exception stack trace and handle exceptions.

Solution C: Identifying the calling JAR via URL classloader

Assuming that you use my sample project and call the library from the application module (like in the previous section), a quick & dirty way to print JAR information would be this:

Add this method to LibraryClass:

  public void doSomethingClassLoader() {
    StackTraceElement callerStackTraceElement = new Exception().getStackTrace()[1];
    try {
      Class<?> callerClass = Class.forName(callerStackTraceElement.getClassName());
      // Cheap way of getting Maven artifact name - TODO: parse
      System.out.println(
        callerClass
          .getClassLoader()
          .getResource(callerStackTraceElement.getClassName().replaceAll("[.]", "/") + ".class")
      );
    }
    catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

Again, on Java 9+ you could make the code nicer by using the Stack-Walking API, see above.

Call the method from Application:

public class Application {
  public static void main(String[] args) {
//    new LibraryClass().doSomething();
//    new LibraryClass().doSomethingJava9();
    new LibraryClass().doSomethingClassLoader();
  }
}

Now build the Maven application from the command line and run with 3 different classpaths, pointing to

  1. the target/classes directory
  2. the JAR in the target directory
  3. the JAR in the local Maven repository in order to see what kind of information gets printed to the console:
$ mvn install
(...)

$ java -cp "annotation\target\annotation-1.0-SNAPSHOT.jar;library\target\library-1.0-SNAPSHOT.jar;application\target\classes" de.scrum_master.stackoverflow.q68321439.application.Application

file:/C:/Users/alexa/Documents/java-src/SO_Maven_ArtifactInfoRuntime_68321439/application/target/classes/de/scrum_master/stackoverflow/q68321439/application/Application.class

$ java -cp "annotation\target\annotation-1.0-SNAPSHOT.jar;library\target\library-1.0-SNAPSHOT.jar;application\target\application-1.0-SNAPSHOT.jar" de.scrum_master.stackoverflow.q68321439.application.Application

jar:file:/C:/Users/alexa/Documents/java-src/SO_Maven_ArtifactInfoRuntime_68321439/application/target/application-1.0-SNAPSHOT.jar!/de/scrum_master/stackoverflow/q68321439/application/Application.class

$ java -cp "annotation\target\annotation-1.0-SNAPSHOT.jar;library\target\library-1.0-SNAPSHOT.jar;c:\Users\Alexa\.m2\repository\de\scrum-master\stackoverflow\q68321439\application\1.0-SNAPSHOT\application-1.0-SNAPSHOT.jar" de.scrum_master.stackoverflow.q68321439.application.Application

jar:file:/C:/Users/alexa/.m2/repository/de/scrum-master/stackoverflow/q68321439/application/1.0-SNAPSHOT/application-1.0-SNAPSHOT.jar!/de/scrum_master/stackoverflow/q68321439/application/Application.class

As you can see

  • in case 1, you can indirectly infer the Maven artifact from the project path,
  • in case 2, you see artifact ID and version in the JAR name and the group ID indirectly in the project path,
  • in case 3, you see artifact ID and version in the JAR name and the group ID directly in the Maven repository path.

Of course, you could parse that information and print it in a more structured way, but I suggest to simply print it like this and let the human brain reading the log do the parsing.

Like I said in a comment before, this works nicely in the case I showed you, also with different projects, not just in a single multi-module project. What kinds of information you would see in case of an application server deployment or uber JAR situation, strongly depends on the exact situation. There is no single, generic answer, and I cannot do your whole job for you. I showed you several options, now you can select one.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Please note my massive update, adding a full Templating Maven Plugin solution + GitHub link. – kriegaex Jul 10 '21 at 04:06
  • For other ways of solving this problem, depending on your exact situation, please also see [this question](https://stackoverflow.com/q/3697449/1082681) and the various answers. – kriegaex Jul 10 '21 at 04:33
  • Thankyou for details. It will be helpful for others awell. – Rag Jul 11 '21 at 17:30
  • But this is not working for my scenario. As mentioned in description, both the solution you provided will work only within individual project or multi-module project . BUT WILL NOT WORK FOR TWO DIFFERENT PROJECT. – Rag Jul 11 '21 at 17:33
  • I mean , our requirement is get the maven pom details of calling projects during runtime. Example : Project A->Method A is called by Project C or D, during runtime when MethodA is called by Project C, we want to get ProjectC pom details. Same way if ProjectD calls the MethodA , then ProjectD pom details we need to get. Facing difficulty in adding the poject to github , trying and will keep you posted. – Rag Jul 11 '21 at 19:00
  • Of course, my solution would work with different projects, given that the calling project also implements the package info + annotation scheme I explained above. My answer was meant to show you how to get the Maven artifact info into your code. The additional step of identifying the caller can either be done by parsing a stacktrace of by AOP. I am updating this answer with a short snippet showing you how to do the former. I see you asked a related AOP question already, so I am going to answer about that there. – kriegaex Jul 12 '21 at 01:12
  • The problem with you question is, it is unspecific. Your own sample code prints information from a properties file from the called module, not from the calling one. Also, you did not explicitly mention if you control the callers and can add information to it like in my example. If you can, you are fine. Otherwise, you cannot use this solution for obvious reasons. – kriegaex Jul 12 '21 at 01:34
  • But then I need to know what you can rely on. For example, Maven JAR Plugin by default creates a file `META-INF/maven/[groupId]/[artifactId]/pom.properties` which already contains group ID, artifact ID and version properties without any resource filtering or templating magic in your build process. But of course, this information can optionally be filtered out and also would not work in uber JARs (Maven Shade, Maven Assembly) filtering out those files. Also, you have a bootstrapping problem there, because you do not know the group and artifact IDs yet, hence cannot determine the path. – kriegaex Jul 12 '21 at 01:43
  • This whole approach to try and rely on build time information during runtime is flawed, because it only works under certain circumstances, whichever approach you choose. For example, do you simply put file system JARs on the classpath? Are you working with EARs deployed in a container? Uber JARs with nested JARs like Spring Boot or uber JARs with shaded/unpacked JARs? – kriegaex Jul 12 '21 at 01:46
  • After previously adding section "Identifying the caller" to my answer, now I also added "Solution C: Identifying the calling JAR via URL classloader". I think, now you have enough information for at least 3 answers, all in one. – kriegaex Jul 12 '21 at 02:24
0

SOLUTION to the scenario explained in the post main description and considering pom present at root of every project .

Note - Please look at @kriegaex suggestions for the better approach.

  1. Add maven-model Dependency:

       <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-model</artifactId>
        <version>3.3.1</version>
      </dependency>
    
  2. This dependency has methods which helps to get all pom related informations at the runtime and across projects.

quick example:
model.getArtifactId() -> gets you the artifact id of the project.

> import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

public class MavenTest {
private static String FILE_NAME = "pom.xml";
private MavenXpp3Reader reader;
private Logger log = Logger.getLogger(MavenUtil.class.getName());

private Model model;

public MavenUtil() throws FileNotFoundException, IOException, XmlPullParserException {
  this(FILE_NAME);
}

 

public MavenUtil(String absoluteFilePath) throws FileNotFoundException, IOException, XmlPullParserException {
  log.info("[" + this.getClass().getSimpleName() + "]");
  reader = new MavenXpp3Reader();
  FileReader fr = null;
  try {
   fr = new FileReader(absoluteFilePath);
   model = reader.read(fr);
  } finally {
   if (fr != null)
    fr.close();
  }
}

public String[] populateBuildInfo() {
  String[] buildInfo = { model.getArtifactId().toUpperCase() + ":" + model.getVersion() };
  return buildInfo;
}

public String getArtifactId(String absoluteFilePath) {
  return model.getArtifactId();
}

 

}




         
Rag
  • 23
  • 5
  • 1
    You have to be kidding me! You are accepting this as a solution? It is answering a completely different question. You tagged your question with _aspectj_ and we talked about how you can determine the information during runtime from AspectJ. Not only is this self-accepted solution actually stolen from [my own solution here](https://stackoverflow.com/a/41791885/1082681) - just worse, because it only works during build time, not with JARs like my own answer. Furthermore, here there is no relationship to AspectJ whatsoever. – kriegaex Aug 08 '21 at 11:29
  • This a rather bad _"solution"_ since: 1. you are assuming that the `pom.xml` file is in the current working directory: this is only true inside your project's working directory, it will fail in the compiled JAR file, 2. you are using a 200 KiB dependency to do the job of an XPath expression, 3. it gives you the version of the **called** method, not the calling one. – Piotr P. Karwasz Aug 09 '21 at 06:17
  • If you want to retrieve the version information from your `pom.xml` file you should build upon [kriegaex's solution B](https://stackoverflow.com/a/68324028/11748454) by: 1. retrieving the calling class and the JAR from which it was loaded (`getProtectionDomain().getCodeSource().getLocation()`), 2. find the `pom.xml` file inside the JARs `META-INF/maven` folder, 3. parse the `pom.xml` file to retrieve the information. – Piotr P. Karwasz Aug 09 '21 at 06:25
  • 1
    I don't mind the `maven-model` library, if the goal is to access this kind of information during build time only, e.g. during a test. My own post which I linked to above can mitigate the problem of finding the POM inside a JAR (if you know the containing JAR artifact name or scan `/META-INF/maven`), even though that requires default JAR plugin settings and probably does not work in a shaded JAR consisting of many other JARs. What I mind is, that there was no mentioning that this info is required only during build time. When I suggested runtime solutions, the OP did not object in any way. – kriegaex Aug 09 '21 at 06:26
  • Moreover, with regard to third-party JARs you can never rely on `META-INF/maven` to exist. For example, I remove it most of the time via Maven JAR plugin option, or the information gets filtered out when a consumer of my library uses Maven Shade or Maven Assembly. Last but not least, not all libraries are built with Maven at all, but maybe manually, maybe via Gradle or Ant and whetever alternatives there are out there. Therefore, scanning POMs should only be used if you sufficiently control the build environment for all relevant dependencies. – kriegaex Aug 09 '21 at 06:32
  • @Piotr P. Karwasz we checked and all the project have pom at the root. – Rag Aug 09 '21 at 13:22
  • Thanks for accepting my answer. My point was: If you had specified your requirements more clearly, we both would have saved lots of time, I for writing comments and answers and you for research. I simply would have closed your question as a duplicate of my other answer, and we would have been done. You would have had your answer immediately. – kriegaex Aug 09 '21 at 16:18