Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read Java build path entries inside a Maven project

I have a project which has dependencies in its classpath (Java buildpath). Now I have converted it to maven project and compiling it using my customized Maven plugin. Following will be my POM file -

<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>com.test</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>ear</packaging>


  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <build>
      <plugins>
         <plugin>
            <groupId>com.my.maven.plugin</groupId>
            <artifactId>my-maven-plugin</artifactId>
            <version>0.0.1</version>
            <extensions>true</extensions>
         </plugin>
      </plugins>
  </build>
</project>

And in my-maven-plugin, I have overridden compile phase -

maven-plugin pom-

    <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>com.test</groupId>
  <artifactId>my-maven-plugin</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>maven-plugin</packaging>

  <name>my-maven-plugin</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-core</artifactId>
        <version>3.3.9</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>3.3.9</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-compat</artifactId>
      <version>3.3.9</version>
    </dependency>   
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-embedder</artifactId>
      <version>3.3.9</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-archiver</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.5</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.plugin-tools</groupId>
      <artifactId>maven-plugin-annotations</artifactId>
      <version>3.4</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>maven-surefire-common</artifactId>
      <version>2.19.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-api</artifactId>
      <version>2.19.1</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.plexus</groupId>
        <artifactId>plexus-component-annotations</artifactId>
        <version>1.6</version>
        <exclusions>
            <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
       <groupId>org.apache.maven.surefire</groupId>
       <artifactId>surefire-junit47</artifactId>
       <version>2.19.1</version>
    </dependency>
  </dependencies>
</project>

lifecycle.xml -

<?xml version="1.0" encoding="UTF-8"?>
<lifecycles>  
  <lifecycle>  
    <id>customLifeCycle</id>  
    <phases>  
      <phase>  
        <id>compile</id>  
        <executions>  
          <execution>  
            <goals>  
              <goal>mycompile</goal>  
            </goals>  
          </execution>  
        </executions>  
      </phase> 
    </phases>  
  </lifecycle>  
</lifecycles> 

components.xml

 <?xml version="1.0" encoding="UTF-8"?>
<component-set>
  <components>
    <component>
      <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
      <role-hint>ear</role-hint>
      <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
      <configuration>
        <type>ear</type>
        <extension>ear</extension>
        <language>java</language>
        <packaging>ear</packaging>        
      </configuration>
    </component>

   <component>
      <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
      <role-hint>ear</role-hint>
      <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
      <configuration>
        <phases>
          <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
          <compile>com.test:my-maven-plugin:mycompile</compile>
          <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
          <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
          <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
          <install>org.apache.maven.plugins:maven-install-plugin:install</install>
          <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
        </phases>
      </configuration>
    </component>
  </components>
</component-set>

And , overridden compile mojo -

 @Mojo( name = "mycompile", defaultPhase = LifecyclePhase.COMPILE )
 public class MyCompileMojo extends AbstractMojo{

   @Parameter( defaultValue = "${project}", readonly = true, required = true )
    private MavenProject project;
    public void execute() throws MojoExecutionException, MojoFailureException {
    }
}

Now, in compile phase, I want a list of JAR files which are present in classpath. How can I get it? I have tried following - but most of them returns target folder path and classes folder path

List<String> list1 = project.getCompileClasspathElements();
List<String> list2 = project.getRuntimeClasspathElements();
List<String> list3 = project.getSystemClasspathElements();
List<String> list4 = project.getTestClasspathElements();
List<Dependency> list5 = project.getCompileDependencies();
Properties list6 = project.getProperties();
List<Dependency> list7 = project.getSystemDependencies();
List<Dependency> list8 = project.getRuntimeDependencies();

My project structure to be compiled

enter image description here

like image 260
Disha Avatar asked Dec 13 '16 08:12

Disha


People also ask

What directory are build artifacts placed in by Maven?

Maven's local repository is a directory on the local machine that stores all the project artifacts. When we execute a Maven build, Maven automatically downloads all the dependency jars into the local repository. Usually, this directory is named . m2.

What is Eclipse build path?

The Java build path is used while compiling a Java project to discover dependent classes . It is made up of the following items − Code in the source folders. Jars and classes folder associated with the project. Classes and libraries exported by projects referenced by this project.

What is the command for Maven build?

To build a Maven project via the command line, you use the mvn command from the command line. The command must be executed in the directory which contains the relevant pom file. You pass the build life cycle, phase or goal as parameter to this command.


Video Answer


1 Answers

The key ingredient you're missing is requiresDependencyResolution, which represent the set of dependencies that will be made available to the plugin. From the Mojo API reference:

Flags this Mojo as requiring the dependencies in the specified class path to be resolved before it can execute. [...] If the annotation is not present at all, the mojo must not make any assumptions about the artifacts associated with a Maven project.

To have access to the compile-time dependencies of the project, you can use ResolutionScope.COMPILE:

compile resolution scope = compile + system + provided dependencies

Among others, there is also COMPILE_PLUS_RUNTIME to have access to runtime scoped dependencies as well, or TEST to add the test scoped dependencies. When this parameter is not present for the Maven plugin, no classpath elements of the Maven project will be available to it, which is the behaviour you encountered.

Therefore, if you want the Maven plugin to get hold of the list of the compile-tile JAR files which are the dependencies of the current Maven project, you can have:

@Mojo(name = "mycompile", defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.COMPILE)
public class MyCompileMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;

    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            List<String> list = project.getCompileClasspathElements();
            getLog().info(list.toString());
        } catch (DependencyResolutionRequiredException e) {
            throw new MojoFailureException("Couldn't resolve compile dependencies", e);
        }
    }

}

The method getCompileClasspathElements() returns the list of path to the JAR files of each compile-time dependencies. It will also contain the path to the target/classes folder of the current Maven project, because it contains the compiled main Java sources of the project. The code above would simply print this list. Similarly, you would use getTestClasspathElements() together with ResolutionScope.TEST to have the list of test scoped dependencies, as well as compile-time dependencies.

If you only want the path to the JAR file of the dependencies, without the classes of the project itself, you can use the method getArtifacts() instead:

public void execute() throws MojoExecutionException, MojoFailureException {
    Set<Artifact> artifacts = project.getArtifacts();
    for (Artifact artifact : artifacts) {
        System.out.println(artifact.getFile());
    }
}

Note that for this to work, you need to make sure the compile phase (or test-compile) has run. The lists are lazily-populated. Running mvn clean test will make sure the plugin has access to the test scope dependencies if it declared a requiresDependencyResolution of TEST. Similarly, running mvn clean compile (along with changing the phase to <phase>compile</phase>) will make sure the plugin has access to the compile scope dependencies if it declared a requiresDependencyResolution of COMPILE.


Couple of side-notes:

  • The file lifecycle.xml has to be located inside src/main/resources/META-INF/maven. Note that this file is actually completely unused in your set-up, because you did not use the new customLifeCycle inside your components.xml, and override ear instead;
  • The file components.xml has to be located inside src/main/resources/META-INF/plexus. Note that the <compile>com.test:my-maven-plugin:mycompile</compile> has to match the group id and artifact id of the plugin;
  • The test project needs to use the plugin like so:

    <packaging>ear</packaging> <!-- because your lifecycle mapping override ear -->
    <dependencies>
      <!-- some dependencies like maven-core -->
      <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-core</artifactId>
        <version>3.0</version>
      </dependency>
    </dependencies>
    <build>
      <plugins>
        <plugin>
          <groupId>com.test</groupId>
          <artifactId>my-maven-plugin</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <extensions>true</extensions>
        </plugin>
      </plugins>
    </build>
    

    Then you can run mvn clean package and the plugin will correctly prints the path to JAR files of maven-core (for example) and its dependencies.

like image 100
Tunaki Avatar answered Oct 18 '22 18:10

Tunaki