I am trying to create a custom parameter less plugin by referring to create simple mojo creation instructions by apache in the below link.
https://maven.apache.org/guides/plugin/guide-java-plugin-development.html#
But I am unable to run the same using maven goal. Kindly suggest what I am missing. As I am new to maven and there aren't many tutorials on custom mavem plugin creation. Any suggestions on this topic will be helpful to me. Thanks in advance.
pom.xml
<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>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<name>Sample Parameter-less Maven Plugin</name>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.0</version>
</dependency>
<!-- dependencies to annotations -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>sayhi</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
GreetingMojo.java
package sample.plugin.hello_maven_plugin;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
/**
* Says "Hi" to the user.
*
*/
#Mojo( name = "sayhi")
public class GreetingMojo extends AbstractMojo
{
public void execute() throws MojoExecutionException
{
getLog().info( "Hello, world." );
System.out.println("My first maven plugin.");
}
}
I am trying to run the pom.xml using package command and mvn install command.
Generally you shouldn't execute the plugin goal in the plugin you are trying to build. The reason you cannot build the plugin with mvn install is because you have configured maven to expect the plugin to already be built.
This section belongs in a different POM file, not the plugin POM file.
<build>
<plugins>
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>sayhi</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
After you have removed this section from the plugin POM you can run mvn install to install your plugin locally. Once installed you can re-add the section to the POM if you really wanted to, but ideally you would add it to a completely different maven project and execute maven in that project.
Related
I am new to Quarkus and try to use it in a Maven multi module project. My project is structured as followed:
- quarkustest (pom)
- quarkustest-application (jar)
- quarkustest-backend (pom)
- quarkustest-backend-rest-api (jar)
- quarkustest-dependencies (pom)
- quarkustest-parent (pom)
The application module executes the quarkus-maven-plugin with build-goal. The quarkustest-backend-rest-api contains a simple REST controller and thus also a beans.xml in /src/main/resources/META-INF. The rest-api-module is references by the application module.
If I package the whole project with mvn package, the resulting runner-jar works as expected. However, if I try to start the project in dev mode with mvn compile quarkus:dev, I get following exception:
ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:1.0.0.CR2:dev (default-cli) on project quarkustest-application: Failed to run: Failed to resolve Quarkus application model: Failed to resolve dependencies for test.quarkustest:quarkustest-application:jar:1.0.0-SNAPSHOT: Could not find artifact test.quarkustest:quarkustest-backend-rest-api:jar:1.0.0-SNAPSHOT -> [Help 1]
I am not quite sure how to solve this. Is there any kind of best practice on multi module projects for Quarkus? Any obvious mistake I am doing here?
Edit 1 (relevant pom files)
quarkustest-application
<parent>
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../quarkustest-parent</relativePath>
</parent>
<artifactId>quarkustest-application</artifactId>
<dependencies>
<dependency>
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-backend-rest-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
quarkustest-parent
<parent>
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../quarkustest-dependencies</relativePath>
</parent>
<artifactId>quarkustest-parent</artifactId>
<packaging>pom</packaging>
quarkustest-dependencies
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
...
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-backend-rest-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
</plugin>
</plugins>
</build>
quarkustest (aggregator)
<parent>
<groupId>test.quarkustest</groupId>
<artifactId>quarkustest-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>quarkustest-parent</relativePath>
</parent>
<artifactId>quarkustest</artifactId>
<packaging>pom</packaging>
<modules>
<module>quarkustest-dependencies</module>
<module>quarkustest-parent</module>
<module>quarkustest-backend</module>
<module>quarkustest-application</module>
</modules>
If you've never ran mvn install it might be because when you're in a subproject maven does not look in its sibling projects to resolve the dependencies, it only looks in the local maven repository which does not contain the dependency. If you have ran mvn install it might be something else at play.
Keep the quarkus-maven-plugin in the quarkustest-application and run
mvn clean install
mvn quarkus:dev -pl quarkustest-application
Now it will pick up changes in all submodules.
I was able to successfully run quarkus submodule in dev (with dependency to other module) in the following way:
Install "Quarkus Run Configs" plugin
Define new Run configuration for Quarkus
-> in VM options provide additional maven parameters in:
-Dmaven.am -Dmaven.pl=<name-of-you-quarkus-module>
In parent pom define quarkus plugin:
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
</plugin>
I have 2 maven projects
1) My Utils Project - imports datecalc-common as a dependency, contains my custom utility classes. Note that it doesn't have a main class.
2) My Main Project - imports 'My Utils Project' as a dependency.
'My Main Project' shows the error 'Cannot find class HolidayCalculator'.
My Utils Project-pom.xml is given below.
How do I modify it so that the dependency jars are included as part of 'My Utils Project'.jar ?
<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>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<groupId>com.mycompany.mycommoncode</groupId>
<artifactId>myutilsjar</artifactId>
<version>0.0.12-SNAPSHOT</version>
<name>myutilsjar</name>
<description>Common Date Utils used by my classes</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>net.objectlab.kit</groupId>
<artifactId>datecalc-common</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>net.objectlab.kit</groupId>
<artifactId>datecalc-jdk8</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
<distributionManagement>
<snapshotRepository>
<id>snapshots</id>
<url>my maven url</url>
</snapshotRepository>
</distributionManagement>
</project>
NOTE: I DO NOT want to use 'shade' plugin. Is there any other way of doing this?
I had to solve that same issue some months ago. I wrote a small library that was to be shared between many projects and I wanted to add it to maven.
This is what I did.
For your "Utils project"
Compile it using maven-assembly-plugin:
Add this to your pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Build the library with it's dependencies using the following command:
mvn clean compile assembly:attached
For your main project
Add this plugin to your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-external</id>
<phase>clean</phase>
<configuration>
<file>${project.basedir}/src/main/resources/lib/sso-client-1.0.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>SSOClient</groupId>
<artifactId>sso-client</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
</executions>
</plugin>
As you can see, I wrote a custom SSO Client.
This will read the jar you compiled in the previous step, and make it available as a dependency. I decided to place it in the resources folder of the main project. The version has to match the one in your "utils project".
Also add the dependency to the pom.xml:
<dependency>
<groupId>SSOClient</groupId>
<artifactId>sso-client</artifactId>
<version>1.0</version>
</dependency>
That's it! You can now reference the classes of the package in your main project.
Let me know if you need clarification.
The Apache Maven Shade Plugin provides the capability to package your artifact in a "uber-jar", that is to say a jar including all dependencies required to run the project. If needed this plugin also supports packages shading (renaming) for some of the dependencies.
More info at:
https://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html#
Goal: Create an executable uber jar with maven shade plugin that can be executed during the mvn compile of another pom.
Repro steps:
Create a pom.xml for the "publisher" component using below pom.
Use a Jenkins build to mvn deploy it (mvn install will work as well)
Add dependency to pom.xml for "consumer" (pom below)
mvn compile the consumer
Expected behavior:
Uber jar for publisher is downloaded somewhere in consumer/target directories
Actual:
Uber jar does not appear in consumer directory
Component 1: Publisher
<?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.mec.experiment</groupId>
<artifactId>publisher</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.mf</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Component 2: Consumer
<?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.mec.experiment</groupId>
<artifactId>consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.mec.experiment</groupId>
<artifactId>publisher</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
The answer from the possible duplicate I linked to in the comments has a link to a dead example page. Here's a supplement for you. The plugin configuration would belong inside the consumer pom.
exec:java
Full name:
org.codehaus.mojo:exec-maven-plugin:1.5.0:java
Description:
Executes the supplied java class in the current VM with the enclosing project's dependencies as classpath.
Attributes:
Requires a Maven project to be executed.
Requires dependency resolution of artifacts in scope: test.
The goal is thread-safe and supports parallel builds.
Since version: 1.0.
See especially executableDependency for your use case. That looks like it will allow you to reference producer according to its group id and artifact instead of hard-coding a path.
There is a class in a maven dependency that is incompatible with Java 8.
How do you properly fix that problem?
Right now I'm doing the following:
Create a package with the same name
Create a class with the same name in that package
Copy and paste the code
Fix the incompatible API call
The problem is that this class contains API calls to restricted classes and although I changed the Eclipse compiler settings (Window -> Preferences -> Java -> Compiler -> Error/Warnings -> Deprecated and restricted API -> Forbidden reference (access rule): Error -> Warning) to allow access the project will only compile sometimes. If it doesn't compile I'll get a "can't find symbol" error.
Edit:
Here are the details you asked for:
Dependency: http://mvnrepository.com/artifact/com.sun.xml.wss/xws-security/3.0
Class: EncryptionProcessor
Necessary change:
// Change line 1053 FROM:
// _dataEncryptor = XMLCipher.getInstance(dataEncAlgo, _dataCipher);
// TO:
_dataEncryptor = XMLCipher.getInstance(dataEncAlgo);
Edit-2:
Maven build error:
[ERROR] symbol: class XMLCipher
[ERROR] location: class com.sun.xml.wss.impl.apachecrypto.EncryptionProcessor
[ERROR] /C:/Users/{name}/development/eclipse_workspace/git/xws-security/src/main/java/com/sun/xml/wss/impl/apachecrypto/EncryptionProcessor.java:[1482,98] cannot find symbol
Here is a detailed guide describing what I did exactly:
Create new Maven project in Eclipse
Configure Maven settings of new project (Important: Use the same group and artifact ID and only change the version number)
<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.sun.xml.wss</groupId>
<artifactId>xws-security</artifactId>
<version>3.0-java8-fix</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
</project>
Add dependency of bugged JAR
<dependencies>
<dependency>
<groupId>com.sun.xml.wss</groupId>
<artifactId>xws-security</artifactId>
<version>3.0</version>
<exclusions>
<exclusion>
<artifactId>xmldsig</artifactId>
<groupId>javax.xml.crypto</groupId>
</exclusion>
<exclusion>
<artifactId>activation</artifactId>
<groupId>javax.activation</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Create Java file in the same package of class that needs to be fixed
package com.sun.xml.wss.impl.apachecrypto;
public class EncryptionProcessor {
// The FIX goes here
}
Add Maven shade build plug in to handle creation of patched JAR file (this is not the only plug in to handle this kind of task - e.g. dependency:unpack)
<build>
<plugins>
<!-- plug in for creation of patched JAR file -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>com.sun.xml.wss:xws-security:3.0</artifact>
<includes>
<include>**/*.class</include>
<include>**/*.xml</include>
</includes>
<excludes>
<exlude>
com/sun/xml/wss/impl/apachecrypto/EncryptionProcessor.class
</exlude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Include patched JAR in other projects as necessary (Note: If you experience ClassNotFoundExceptions or similar errors do this: Right-click on the project -> Properties -> Maven -> "Resolve dependencies from Workspace projects":false)
In case you are not familiar with Maven. Here is the complete pom.xml: http://pastebucket.com/88444
Similar to Steven S.'s answer, but using the maven-dependency-plugin. Based on this blog post.
I changed the name of the patched library (not the version), but it depends on your needs what works better for you.
The dependency on the original library should be marked as <optional>true</optional>. Otherwise, the projects that depend on your patched library will also depend on the original library, which means that both the patched and the original version will be on the classpath, which can lead to all kinds of problems.
If your project is a child project, you can still use a completely different groupId and version than your parent pom. Doesn't matter.
You can exclude the classes you patch from unpacking, but it's probably not necessary, because Maven will first unpack the original library and then compile your new version, which means that the original classes are overwritten. Nice!
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<!-- remove this if you don't have a parent pom -->
<parent>
<groupId>my.company</groupId>
<artifactId>my.company</artifactId>
<version>1.2.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.foo</groupId>
<artifactId>foo-bar-patched</artifactId>
<version>4.5.6</version>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo</groupId>
<artifactId>foo-bar</artifactId>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<!-- excludes are probably not necessary -->
<!-- <excludes>**/Foo.class,**/Bar.class</excludes> -->
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>foo-bar</artifactId>
<version>4.5.6</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
General solution:
download all project sources
apply your modification
use version control so that change isn't lost
change version in pom.xml, for example from 3.0 to 3.0-patched
launch maven build
copy generated artifacts to you repository/Artifactory, if you use one
change dependency version in your own project
I am using Eclipse Indigo. I installed the maven package on eclipse. I configured the Pom and nearly everything is fine. Just maven is not building the default folder bath
src/main/java
Here is the 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>TestProject</groupId>
<artifactId>TestProject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.0.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.6</version>
<configuration>
<ajdtVersion>1.6</ajdtVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
I cleaned the project,installed and build it.... also I upgradet the project... the dependencies are all fine... no error at all.. why isn't the folder build ?
Eclipse's integration with maven is (to say at least) appalling. If you want to create a new project: create the pom and the folders, and then run mvn eclipse:eclipse to create the project files for eclipse. The simple solution that I've followed for a couple of years is to use the community edition of Intellij.
Aswering your second question: well... again, the integration is so poor that sometimes you'll need to close and reopen the project for eclipse to read the new changes. Most of the time, a refresh + clean project will force eclipse to read the project configuration.