Problem : I want to access com.sun.tools.javadoc.Main from code in a Mojo plugin.
I have two parts to this question.
Part 1:
When creating a mojo plugin, is it best to use annotations or parameters inside the #Mojo
For example you can set 'requiresDependencyResolution' in both.
/*
* #goal install
* #phase process-classes
* #configurator include-project-dependencies
* #requiresDependencyResolution compile+runtime
*/
#Mojo(name = "document", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class CreatorMavenPlugin extends AbstractMojo
Part 2: (Main question)
I want to execute the following code in my plugin, I want to hook into the Javadoc generation.
com.sun.tools.javadoc.Main.execute(new String[]
{
"-private",
"-doclet",
"com.test.tools.APIDocGenDoclet",
javaFilePathAndName
});
return APIDocGenDoclet.getCurrentClassDocs();
The problem is that eclipse recognises com.sun.tools.javadoc.Main from the JDK it has.
Maven when it runs can't find the class and gives the error....
Number of foreign imports: 1
import: Entry[import from realm ClassRealm[maven.api, parent: null]]
-----------------------------------------------------
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:125)
... 20 more
Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javadoc/Main
I've tried adding tools directly to start with as a dependency...
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.6.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
But this doesn't work. (Same error)
I've tried adding it as a dependency of the profile my plugin runs under...
<profile>
<id>auto-doc</id>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.6.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.test</groupId>
<artifactId>updater</artifactId>
<version>1.0.0-SNAPSHOT</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>document</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
But not change, same error.
I feel this is something to do with the classpath setup defined for the Mojo Plugin, but I've tried many different combinations, but I'm stumped.
Can anyone help please?
Note: I'm using Maven 3.0.4 & JDK 1.6.0_43 32 bit on Windows.
Part 1: if you don't need backward compatibility with ancient Maven versions, go with the annotations. It's the new and better way of specifying Mojo configuration, and your IDE will give you autocomplete and hovers.
Part 2:
Taking a look at what the existing Maven Javadoc plugin does:
It seems it uses the Toolchain API to locate the appropriate Javadoc tool to run. The Maven Compiler Plugin also does this to get javac.
Summarizing from the toolchain documentation:
add
#Component
private ToolchainManager toolchainManager;
#Component
private MavenSession session;
to your Mojo. Then in your code
Toolchain tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
String javadocExecutable = tc.findTool( "javadoc" );
and then you can execute it. Read the toolchain documentation in the link for more detailed information.
If you were using Java 8 or later, you could use ToolProvider.getSystemDocumentationTool().
I was putting the Profile section in the project that was being built, not in the project that contains the Mojo Plugin.
This is what I've got in Mojo Plugin Project
<profiles>
<profile>
<id>default-tools.jar</id>
<activation>
<property>
<name>java.vendor</name>
<value>Sun Microsystems Inc.</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.6.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
The Mojo plugin is defined as this...
/**
* #goal install
* #phase process-classes
* #configurator include-project-dependencies
* #requiresDependencyResolution compile+runtime
*/
#Mojo(name = "document", requiresDependencyResolution= ResolutionScope.COMPILE_PLUS_RUNTIME)
public class DocumationUpdatorMavenPlugin extends AbstractMojo
My project that uses the plugin, has this in its POM...
<profile>
<id>auto-doc</id>
<build>
<plugins>
<plugin>
<groupId>com.test</groupId>
<artifactId>updater</artifactId>
<version>1.0.0-SNAPSHOT</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>document</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Then my command "mvn install -Pauto-doc" kicks off my AutoDoc plugin.
Related
I am trying to run my tests but I am facing an issue where I cannot run my tests when I run the following command:
mvn clean test
my project contain 3 modules (see image attached):
Every module in the project contains pom.xml file which contains only the dependencies relevant for the module.
the main pom.xml (the reactor) is the file which run the test and control the project, and this is its content:
<?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>com.hackeruso</groupId>
<artifactId>neo</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<modules>
<module>automation-ui</module>
<module>automation-api</module>
<module>morpheus</module>
</modules>
<name>neo</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<aspectj.version>1.8.10</aspectj.version>
<testng.version>7.3.0</testng.version>
</properties>
<dependencies>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.13.6</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
when I run the command mvn test I am getting the following message:
No tests to run.
And this image shows where I hold my tests:
src/test/java/com/hackeruso/automation/ui/LoginTest
This is an example for my test class:
--------------------EDIT-------------------------------------------
package com.hackeruso.automation.ui;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class LoginTest extends BaseTest{
#Test(dataProvider = "userDetailsProvider")
public void loginTest(String username, String password){
signIn(username, password);
}
#DataProvider(name = "userDetailsProvider")
public Object[][] userDetailsProvider(){
return new Object[][] {
{"user#mail.com", "*******"}
};
}
}
From documentation:
For example, a project that is purely metadata (packaging value is
pom) only binds goals to the install and deploy phases (for a complete
list of goal-to-build-phase bindings of some of the packaging types,
refer to the Lifecycle Reference).
As you can see, only install and deploy phases (not test) are valid for a pom packaged project.
The Java code should be not there, since a pom project should be purely metadata.
The parent project has a packaging of <packaging>pom</packaging>. This means this is a meta-project and should not contain any source code.
What you need to do is to move the tests in any of the existing modules or create a new one for these tests. By looking at the package structure of the tests, I guess it would be automation-ui in your case.
Then use the following command to run the tests from all the modules
mvn test -am
Where -am will make all the submodules.
If you want to run tests for a single module, use
mvn test -pl <submodule-name>
So eventually what I did was creating another module for testing and the main project module will contain only Metadata as #Yasin suggested, I also deleted the 'src' package from my main project module leaving it just with a pom.xml file which will manage the other modules (the reactor).
Now everything is working as expected.
Thanks!
I have a framework where I have multiple classes and one of my class is a mojo class which gets some data from a different class and then pass that data to some other class for execution.
The first time when I use command mvn clean install I would get error - Could not find artifact com.io:MyDataProject:0.0.1-SNAPSHOT. Then I have to comment out the second plugin section inside build tag as shown below and again use command mvn clean install which would then install my plugin and once installed I would then uncomment the commented code again so that I can use my installed plugin which executes the mojo and then everything runs fine.
Issue is if I would share my project with other team members they have to do the same steps which I don't want. I need something like using mvn clean install would install my plugin and can execute my mojo at the same time.
#Mojo(name = "dependency-counter", defaultPhase = LifecyclePhase.COMPILE)
public class DependencyCounterMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
System.out.println("$$$$$$$$$$$$$$ ....Mojo execution begins.... $$$$$$$$$$$$$$");
GenerateFeature ob=new GenerateFeature();
ob.getData();
}
}
Pom.xml:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
</plugin>
<plugin>
<groupId>com.io</groupId>
<artifactId>MyDataProject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>dependency-counter</goal>
</goals>
</execution>
</executions>
<configuration>
<scope>test</scope>
</configuration>
</plugin>
</plugins>
</build>
You need two separate projects or modules:
One for the plugin, containing the mojo and the POM for the plugin.
One for your framework, where the POM lists the plugin under <plugins>.
You cannot list the plugin in the same POM that produces the plugin.
You might also consider not putting the plugin into the POM at all, but run it on command line.
I have a maven project project A that has a dependency on a different maven project project B. I publish Project B as two jars, one with the regular class files and one for its tests (I need to re-use some componenents). Maven has a plug-in for this.
The pom.xml for project A looks like this:
<properties>
<project-B.version>abcd123</project-B.version>
</properties>
<dependencies>
<dependency>
<groupId>group-id-project-B</groupId>
<artifactId>project-B</artifactId>
<version>${project-B.version}</version>
</dependency>
<dependency>
<groupId>group-id-project-B</groupId>
<artifactId>project-B</artifactId>
<classifier>tests</classifier>
<type>test-jar</type>
<version>${project-B.version}</version> <!-- Doesn't work! -->
<scope>test</scope>
</dependency>
</dependencies>
Somehow, both my IDE (IntelliJ) and mvn CLI are unable to compile this and both give an unresolved reference in my test classes (where I re-use test files from project B).
If, however, I replace ${project-B.version} with abcd123 in the test-jar dependency everything loads fine. I can't make any sense of this as to why mvn doesn't like me to use a variable in properties? This behaviour is consistent between my IDE and mvn cli.
For what it's worth, this is the output for project B when I use mvn dependency:list
group-id-project-B:project-B:test-jar:tests:abcd123:test
group-id-project-B:project-B:jar:tests:abcd123:compile
And the rest of my pom:
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
is there a bug in maven or am I missing something?
Edit:
I use mvn clean install and the truncated output is:
[INFO] --- kotlin-maven-plugin:1.3.72:test-compile (test-compile) # optimization-engine-service ---
[ERROR] MyClass.kt: (16, 19) Unresolved reference: functionName
[ERROR] MyClass.kt: (19, 28) Unresolved reference: SOME_FIELD
... etc.
Maven cannot resolve artifact that were installed/deployed with a version from parameter.
In order for your artifacts to be resolvable after build, you will have to use flatten-maven-plugin so you get an effective pom which will be resolvable by maven.
You can see an example on how to do this in maven-ci-friendly
I'm using IntelliJ IDE with maven. I have a project (main module) with a parent pom, that includes 2 sub modules, each with their own pom.
<!-- main pom module part -->
<packaging>pom</packaging>
<modules>
<module>ModuleA</module>
<module>ModuleB</module>
</modules>
<!-- example for sub module pom -->
<parent>
<artifactId>main-module</artifactId>
<groupId>my.main.module</groupId>
<version>0.5.0</version>
</parent>
Image ModuleA includes the OpenCV Java wrapper and ModuleB is an executable java program (having the main class) using ModuleA.
The compiling works fine, but when I run ModuleB with having set the library path in the launcher, I'll get the following error for ModuleA:
java.lang.NoClassDefFoundError: org/opencv/core/Core
Any suggestions how to fix this?
Ok, I found a solution my self. The problem was, that the opencv java wrapper was included with a system path. Now I use the maven install plugin within the validate live cycle step instead.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>3.3.0</version>
<packaging>jar</packaging>
<file>${project.basedir}/../lib/opencv/opencv-330.jar</file>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Works fine for me, but was not the way I wanted it to be... The system-path type dependency seems to be buggy in maven.
Try to add the following dependency to your ModuleA:
<dependency>
<groupId>nu.pattern</groupId>
<artifactId>opencv</artifactId>
<version>2.4.9-7</version>
</dependency>
I have a working IzPack installer project set up with maven and added following to my install script install.xml to [installation][listeners]:
<listener classname="(company-name).listener.InstallerListener" stage="install"/>
Sadly, the line seems to be ignored and the debugger does not halt on set breakpoints in the InstallListener class. I have read the documentation for InstallListeners, but it is not useful as I have the build process integrated with maven; here are the relevant parts of the Project Object Model pom.xml:
<properties>
<izpack-standalone.version>4.3.1</izpack-standalone.version>
</properties>
<dependencies>
<!-- izpack -->
<dependency>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-standalone-compiler</artifactId>
<version>${izpack-standalone.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<plugins>
<!-- IzPack compiler -->
<plugin>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-maven-plugin</artifactId>
<version>${org.codehaus.izpack.izpack-maven-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-standalone-compiler</artifactId>
<version>${izpack-standalone.version}</version>
</dependency>
</dependencies>
<configuration>
<izpackBasedir>${staging.dir}</izpackBasedir>
<customPanelDirectory>${staging.dir}</customPanelDirectory>
</configuration>
<executions>
<execution>
<id>standard-installer</id>
<phase>package</phase>
<goals>
<goal>izpack</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
What am I missing here?
Note: The compiled installer does contain the specified InstallerListener class file, so it is available at runtime.
You must place the jar file containing your panel classes into the {customPanelDirectory}/bin/panels folder where it will be picked up automatically by the izpack-maven-plugin.
In the case above this folder would resolve to {staging.dir}/bin/panels since you configured <customPanelDirectory>${staging.dir}</customPanelDirectory>.
Adding it to install.xml file will not work, since this would be resolved at install time, but not at installer build time.