mojo-executor support for plugin dependencies? - maven

I'm using the mojo-executor library to call a number of Maven plugins from within another Maven plugin.
However, I can't find any way to specify dependencies on the plugins as I'm invoking them. This is an issue for the maven-assembly-plugin, where I need to add an assembly descriptor file as a dependency. Adding the dependency at another level doesn't seem to get the descriptor file onto the plugin's classpath.
Any idea if this is possible, or if mojo-executor could be improved to provide this functionality? Thanks.

The mojo-executor will execute the mojo in an environment without any classpaths.
You need to manually add the dependency.
Dependency dep = new Dependency();
dep.setGroupId("groupId");
dep.setArtifactId("artifactId");
dep.setVersion("0.0.1-SNAPSHOT");
Plugin assembly = MojoExecutor.plugin(
"org.apache.maven.plugins",
"maven-assembly-plugin",
"2.3");
assembly.addDependency(dep)
MojoExecutor.executeMojo(assembly,
MojoExecutor.goal("single"),
...
)

You know that it's possible to define dependencies for plugins as well:
<plugin>
<groupId>com.soebes.maven.plugins.mlv</groupId>
<artifactId>maven-license-verifier-plugin</artifactId>
<version>0.4</version>
<dependencies>
<dependency>
<groupId>com.company.licenses</groupId>
<artifactId>allprojects</artifactId>
<version>1.0</version>
</dependency
</dependencies>
<configuration>
<!-- Optional you can put your configurations here -->
</configuration>
</plugin>
This will put the dependency on the classpath of the plugin. That might solve your problem.

Maybe you need to place a requiresDependencyResolution parameter at the #Mojo annotation of our Maven plugin's goal class. Something like this:
#Mojo(name = "your-goal", defaultPhase = LifecyclePhase.xxx,
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME
)
public class YourGoalMojo...
This is necessary for YOUR Maven plugin to have dependencies resolved and available before/to its execution. The mojo-executor project's README page mentions this just after its maven-dependency-plugin based example:
https://github.com/TimMoore/mojo-executor/blob/master/README.md
Further information about the #Mojo annotation parameterization can be found here:
http://maven.apache.org/developers/mojo-api-specification.html

Related

How to deal with dependencies with "provided" scope in OSGi

There are lots of tutorials, which shows how to cope with dependencies of the OSGi project and how should they be converted to the bundle. After more than one day research, I have still not found how to deal with the dependencies with provided scope.
Let me give an example. I am currently using Dropbox (dropbox-core-sdk 3.0) and it has two dependencies (com.google.android and javax.servlet) with provided scope. When I use the techniques such as maven-bundle-plugin or bnd, it only downloads the artifacts and its transitive dependencies. However, I need also provided dependencies in order to be able to import my project to the OSGi container.
I am using maven-bundle-plugin and my pom.xml looks like:
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>*</Export-Package>
<Embed-Transitive>true</Embed-Transitive>
<Embed-Dependency>*</Embed-Dependency>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
even if Embed-Dependency says include everything, only the dependencies + transitive dependencies are in the jar. However, I want the provided-scoped jars are also in the jar.
Is there any way to download dependencies with provided scope. If not, how to deal with this situation?
I would have to defer to the Maven BND experts out there, but I don't think you can include provided dependencies through a Maven build. Since it is unlikely you will be using the Android components outside of your bundle, couldn't you just manually download the needed Jars and place them in your bundle (Bundle-Classpath)?
I think you can specify the scopes of the dependencies you want to embed. Be careful though that some dependencies like the OSGi spec jars should never be deployed.
In general you may only embed dependencies that are hidden inside the bundle. Any packages that are needed to talk to other bundles should better not deployed.
For example the servlet api is typically provided by the httpservice bundle you use.
Try this option:
<Embed-Dependency>*;scope=compile|provided</Embed-Dependency>

Does Maven need to explicitly specify the dependency that Spring/Hibernate dependented?

I'm new to Maven, I try to use Maven with Spring, Hibernate in my project. After go though the Spring and Hibernate reference, I found that "there is no need to explicitly specify the dependent liberaries in POM.xml file for such Apache commons liberaries".
My questions is that : If my other parts of project refer to Apache commons liberary, such as commons-io, SHOULD I explicit specify this dependency in POM.xml file?
You should define those dependencies in Maven which your project is using. For example, even though some library depends on commons-io but if your code needs this then you should directly define commons-io in your pom.xml
You should not worry about the dependencies of the libraries you have defined in your pom.xml. Maven will do that for you.
Maven is used to avoid the issue of having to run down JAR files that are dependent on other JAR files. Of course you do not HAVE to use maven to do this, but you should. Maven will automatically download the dependent JAR files of the JAR file you require. THe hibernate-entity manager JAR file, for example, has over 100 dependencies and maven does the work for you.
Anyway,even if you do add the commons-io file to the build path/classpath of the maven project,and then update the project configuration, maven will kick it out.
You can provide a lib name on a site like mvnrepository.com to see what it depends on (e.g. take a look at a section called "This artifact depends on ..." in case of spring-webmvc library). Those dependencies (which your artifact depends on) are called transitive dependencies. You don't have to specify these in your pom.xml as maven will resolve them for you.
For the sake of readability you should only state those dependencies in your module that you rely on directly. You want JUnit to test your software, only declare JUnit; you need hibernate to use ORM, declare hibernate, and so on. Leave the rest to Maven.
And most of the time you should state what you intend to use in the very module you want to use it in. So if you want to use a dependency in more than one module, consider moving it into a dependencyManagement block in a parent pom and referencing it from there in the module you want it in.
parent pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
child pom.xml
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
This guarantees you version-stability and still allows you to find out what a module uses by only looking in it's pom (and not all over the place).

What is the difference in Maven between dependency and plugin tags in pom.xml?

Created project with Spring, Hibernate & Maven. My question is what is the logic behind plugin versus dependency ?
Both plugins and dependencies are Jar files.
But the difference between them is, most of the work in maven is done using plugins; whereas dependency is just a Jar file which will be added to the classpath while executing the tasks.
For example, you use a compiler-plugin to compile the java files. You can't use compiler-plugin as a dependency since that will only add the plugin to the classpath, and will not trigger any compilation. The Jar files to be added to the classpath while compiling the file, will be specified as a dependency.
Same goes with your scenario. You have to use spring-plugin to execute some spring executables [ I'm not sure what spring-plugins are used for. I'm just taking a guess here ]. But you need dependencies to execute those executables. And Junit is tagged under dependency since it is used by surefire-plugin for executing unit-tests.
So, we can say, plugin is a Jar file which executes the task, and dependency is a Jar which provides the class files to execute the task.
Hope that answers your question!
Maven itself can be described as food processor which has many different units that can be used to accomplish different tasks. Those units are called plugins. For example, to compile your project maven uses maven-compiler-plugin, to run tests - maven-surefire-plugin and so on.
Dependency in terms of maven is a packaged piece of classes that your project depends on. It can be jar, war etc. For example, if you want to be able to write JUnit test, you'll have to use JUnit annotations and classes thus you have to declare that your project depends on JUnit.
Plugins and dependencies are very different things and these are complementary.
What plugins are ?
Plugins perform tasks for a Maven build. These are not packaged in the application.
These are the heart of Maven.
Any task executed by Maven is performed by plugins.
There are two categories of plugins : the build and the reporting plugins :
Build plugins will be executed during the build and they should be configured in the <build/> element from the POM.
Reporting plugins will be executed during the site generation and they should be configured in the <reporting/> element from the POM.
According to the maven goal specified in the command line (for example mvn clean, mvn clean package or mvn site) , a specific lifecyle will be used and a specific set of plugins goals will be executed.
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's site documentation.
A plugin goal may be bound to a specific phase of a specific lifecyle.
For example the maven-compiler-plugin binds by default the compile goal to the lifecycle phase: compile.
Most of maven plugins (both core plugins and third party plugins) favor convention over configuration. So these generally bound a plugin goal to a specific phase to make their usage simpler.
That is neater and less error prone :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
than :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
What dependencies are ?
Dependencies are Maven artifacts/components required for the project.
Concretely most of dependencies are jar (that is libraries) but these may also be other kinds of archives : war, ear, test-jar, ejb-client ... or still POM or BOM.
In a pom.xml, dependencies may be specified at multiple places : the <build><dependencies> part , the dependencies management part or still in a plugin declaration ! Indeed some plugins may need to have some dependencies in the classpath during their execution. That is not common but that may happen.
Here is an example from the documentation that shows that plugin and dependency may work together :
For instance, the Maven Antrun Plugin version 1.2 uses Ant version
1.6.5, if you want to use the latest Ant version when running this plugin, you need to add <dependencies> element like the following:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
...
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>
In Maven, dependencies are referenced in a specific format :
groupId:artifactId:packaging:classifier:version.
The classifier (that is optional) and the packaging (JAR by default) are not commonly specified. So the common format in the dependency declaration is rather : groupId:artifactId:version.
Here is an example of dependency declared in the <build><dependencies> part :
<build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.14.Final</version>
</dependency>
<dependencies>
</build>
Dependency doesn't have a phase binding as plugins to address the "when" question.
But it has a counterpart : the scope.
Indeed declared dependencies are usable by the application at a specific time according to the scope we defined for these.
The scope is a central concept about how a dependency will be visible for the project.
The default scope is compile. That is the most commonly needed scope (convention over configuration again).
The compile scope means that the dependency is available in all classpaths of a project.
The scope defines in which classpaths the dependency should be added.
For example do we need it at compile and runtime, or only for tests compilation and execution ?
For example we previously defined Hibernate as a compile dependency as we need it everywhere : source compilation, test compilation, runtime and so for....
But we don't want that testing libraries may be packaged in the application or referenced in the source code. So we specify the test scope for them :
<build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
<dependencies>
</build>
One line answer - basic understanding
Plugin is a tool you use at the execution of your maven build
Dependency means kind of any library which you will use in your code
If you're coming from a front-end background like me, and are familiar with Grunt and npm, think of it like this:
First you would run, say, npm install grunt-contrib-copy --save-dev. This is like maven's <dependency></dependency>. It downloads the files needed to execute a build task.
Then you would configure the task in Gruntfile.js
copy: {
main: {
src: 'src/*',
dest: 'dest/',
},
}
This is like maven's <plugin>/<plugin>. You are telling the build tool what to do with the code downloaded by npm/<dependency></dependency>.
Of course this is not an exact analogy, but close enough to help wrap your head around it.
Plug-ins are used for adding functionalities to Maven itself (like adding eclipse support or SpringBoot support to Maven etc.). Dependencies are needed by your source code to pass any Maven phase (compile or test for example). In case of JUnit since the test code is basically part of your code base and you call JUnit specific commands inside test suites and those commands are not provided by Java SDK therefore JUnit must be present at the time Maven is in the test phase and this is handled by mentioning JUnit as a dependency in your pom.xml file.
In simple words:
Plugins are used to add some additonal features to the software/tools(like Maven). Maven will use the added plugins at the time of building when we use the build command.
Dependecies are used to add some addtional code to your source code, so a dependency will make some extra code (like Classes in Java) in the form of library available for your source code.
Maven at its heart is a plugin execution framework -- as per formal and standard compact definition. To make it more clear, the commands you use like maven-install/clean/compile/build etc for creating/executing jars, which we sometimes manually run too. So, the things which you want to run (or configure or execute) you basically put them in dependency tag of mavens pom and the answer so as to who will run these dependencies (required for environment setup) be the plugins.
javac (compiler) dependency.java (dependency)
A plugin is an extension to Maven, something used to produce your artifact (maven-jar-plugin for an example, is used to, you guess it, make a jar out of your compiled classes and resources).
A dependency is a library that is needed by the application you are building, at compile and/or test and/or runtime time.

Update maven properties after a new release, using versions plugin

Im having a problem with a multimodule project in maven/jenkins.
For example my structure is like this:
---ProjectA
----pom.xml
--------ModuleA
---------pom.xml
--------ModuleB
---------pom.xml
---ProjectB
-----pom.xml
For example ModuleA has a dependency for something in ProjectB which is defined in ModuleA's pom except for the version which is only defined as property and is inherited from ProjectA's properties section.
I want to automate the release process to get rid of all the manual update of versions in all the poms. So after making a release of ProjectB I what to bump all references in ProjectA.
EDIT
More accurate I want to Release ProjectB which has to include a release of ProjectA (because of dependencies) and in the new Snapshots of ProjectA I want references to the newest ProjectB there is.
The maven plugin versions does this pretty well if one would specify the dependency and the version number in the same pom. My problem as you can see is that (I'm speculating) when version plugin tries to check the property field in ProjectA's pom the property can't be associated with a dependency. And I guess that versions plugin looks on the effective pom because it CAN find that the dependency in ModuleA's pom should be updated. It just can't update it due to the fact that its not defined there.
Would be much obliged for a solution which could keep my properties in the parent pom.
Thanks
Ok. SO I think I've worked something out, but i'll post it here for others to see.
So the thing I think is the problem is that the autoLinkItem only searches the current file for linkage and if you want a property to get assosiated with a dependency not specified in the same file one could explicitly tell the plugin in this.
Like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<properties>
<property>
<name>basis.version</name>
<dependencies>
<dependency>
<groupId>com.mycompany.app.basis</groupId>
<artifactId>ModuleBasis</artifactId>
</dependency>
</dependencies>
</property>
</properties>
<includeProperties>basis.version</includeProperties>
<generateBackupPoms>false</generateBackupPoms>
<allowSnapshots>true</allowSnapshots>
</configuration>
</plugin>

How to add resources to the classpath of Maven plugins?

I've got a Maven plugin that depends on slf4j for logging. The default behavior is too chatty for my liking but I can't figure out how to add my logback.xml to the plugin's classpath.
<plugin>
<dependencies>
</dependencies>
</plugin>
allows you to add dependencies to the plugin's classpath, but how do you add local (resource) directories?
You have to wrap your logback.xml into a proper Maven artifact (i.e. a jar) and install it to local repository or deploy to your shared repository, or use systemPath in your dependency declaration to point to a jar placed somewhere inside of your project, which is highly not recommended.
The reason for this is reusability of your build. Think how others would be able to reproduce it.
You don't. You must package them up as an artifact and add it as a dependency.

Resources