Maven-webstart-plugin to include runtime dependencies - maven

When building a jnlp with the maven-webstart-plugin, I found that the runtime dependencies weren't being included in the jnlp.
I'm using a template like this:
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="$jnlpspec" codebase="${url}/${appName}" href="${outputFile}">
<information>
<title>${appName}</title>
<vendor>$project.Organization.Name</vendor>
<homepage href="${url}/${appName}"/>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="$j2seVersion"/>
$dependencies
</resources>
<application-desc main-class="${main}" />
</jnlp>
How can I include the runtime dependencies? Well, I can include them all individually:
<plugin>
<groupId>org.codehaus.mojo.webstart</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<configuration>
<dependencies>
<includes>
<include>groupId:artifactId</include>
...
</includes>
</dependencies>
...
</configuration>
</plugin>
...but ideally, I don't want to have to remember to change this every time I add a runtime dependency to my project.
Is there a way to instruct the plugin to include all runtime dependencies?

So it turns out that the default is to include all compile and runtime dependencies.
What was going on?
Well, I'm also using ant to deploy the jnlp onto a server, and in the ant file, $dependencies was being set using mvn:dependencies without the scope being specified as runtime. So adding the scope changes the $dependencies fileset which is incorporated into the jnlp file.

I use a parent pom configuration where one of the modules is the web start project. I like to keep this as minimal as possible. I have compile dependencies only to a logging library, the main application module (another module in the same parent pom structure), and jar files including native binaries. In addition to these compile dependencies, I have some test dependencies and a system dependency to a local javaws.jar file.
It seems that the maven webstart plugin includes any runtime dependencies from modules which is included to the web start project as a compile dependency.
It might be a solution for you to split up your project in a similar manner.
Regarding the native binaries. I had to modify the velocity template somewhat to get these dependencies as nativelib instead of jar resources.

Related

Running docker-maven-plugin on the very end of parent pom building

I'm trying to build the docker image containing a group of .jar files built during building parent POM file. What I found till now was the case where the single build of particular module creates separate docker image.
My docker image contains Karaf with the deployed bundles. At some point I achieved the creating docker, but when everything was build. I'm afraid that docker-maven-plugin may not support the case where I want to create docker image from particular folders of bundles (each child project is deploying its bundles to particular folder).
For now I found that parent POM package types supports only three phases, but anyway - all of them are run just as first project during the build. So the question is:
Is it possible to create docker image
containing all bundles built during building the parent POM project which are deployed to one folder
automatically after run some parent POM goal
Below some part of parent POM which finally may not be related to my needs
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<inherited>false</inherited>
<version>0.4.10</version>
<configuration>
<imageName>test1</imageName>
<dockerDirectory>../karaf-deploy</dockerDirectory>
<resources>
<resource>
<targetPath>../karaf-deploy/</targetPath>
<directory>../karaf-deploy/</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
Child-parent relationship is simply a special form of dependency, where child depends on parent. As such, parent is always built first, before any children. This also means you cannot build anything in parent that depends on children, because parent depending on a child would be basically a cyclic dependency.
So if you want to bundle just a single artifact, you can add docker plugin to the lifecycle of that single project. But if you want to bundle multiple artifacts, you should follow advice by #khmarbaise:
Define a new separate distribution project (can even be pom packaging or use a special extension)
Add distribution project as child module to existing parent
Add normal Maven dependencies on any artifacts you want to bundle/wrap/include
Define copy-dependencies step for prepare-package phase to copy dependencies to build directory
Define docker-maven-plugin settings for package phase to bundle copied dependencies
Skip step 4 if your distribution plugin can pick dependencies from Maven directly. We're using io.fabric8 docker-maven-plugin where you can define assembly-style descriptor such as this:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>all-artifacts</id>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>

Maven install goal does not generate pom for modules

I'm running a multi-module maven project and have an unexpected behavior. First time I'm seeing this...
My parent module configures the install plugin, defining its classifier.
<plugin>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<generatePom>true</generatePom>
<classifier>${env}</classifier>
</configuration>
</plugin>
<!-- ... -->
<modules>
<module>webapp-formation</module>
<module>db-formation</module>
</modules>
But when I'm running mvn install the .pom files are not generate for my modules. Only my parent is associated with a .pom file in my repositories. Thus trying to browse to my module's artifact on Archiva (after running mvn depoy of course!) it simply fails. I can browse to the parent but not its children.
So... I need to add the undocumented attribute generatePom to my plugin configuration to have the .pom files generated --copied would be a better word actually-- for all my modules. --I said undocumented attribute because this attribute is documented only for the install-file goal which is not the one ran by default. The install goal is not expecting that attribute...
Of course, if I do not configure my install plugin --so not configuring the classifier-- I have no problem and all .pom files are generated properly.
For you guys, is that a normal behavior? Something that you have already seen? Or should I just file a bug?
Thanks,
Olivier.
What you describe as an undocumented attribute is simply wrong, cause the attributes are specific on a goal base which means the given configuration will not change anything, cause the generatePom attribute is only valid for install-file goal. So you can remove it.
In general such configuration does not make sense, cause if you have different environments you should go a different way. Just removed hte configuration with <classifier>${env}</classifier> as well and try to deploy via:
mvn clean deploy

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.

Order of maven multi module is not maintained for eclipse plugins

We have a bunch of eclipse plugin projects, features and update sites. We have created a master pom where we define the modules:
<modules>
<module>bundles/b1</module>
<module>features/f1</module>
<module>p2/site1</module>
<module>bundles/b2</module>
</modules>
We wanted to preserve this order and as per Guide to working with Multiple Modules
As per the link above we assumed that the order will be preserved as per the order in which the module elements were listed.
Our requirement:
site1 produces a site_assembly.zip. We wanted to take this zip file and wrap into around into a bundle which is what "b2" bundle does.
Our observation:
Maven reactor order which is printed at the beginning of the multi-module build is proper, however the build for every module is forked.
Because of (1) the bundle b2 get built before the site1 project is build and is able to produce a site assembly zip.
We tried adding a dependency in "b2"'s pom.xml to site1 but the build failed as it tries to build b2 first which has dependency on site1 which has not been built till now.
We observed the same behavior when we had unit test as osgi fragment. In the order we clearly specified that the host comes before the test fragment but when the maven build is invoked then it always built the fragment before the host and it used to fail.
Plugins that are defined in master pom:
<plugin>
<!-- enable tycho build extension -->
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>${tycho-version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<disableP2Mirrors>true</disableP2Mirrors>
<resolver>p2</resolver>
<target>
<artifact>
<groupId>com.x.y</groupId>
<artifactId>p2.build.target</artifactId>
<version>${project.version}</version>
<classifier>x</classifier>
</artifact>
</target>
</configuration>
</plugin>
We are not sure if maven-tycho-plugin interferes with the reactor order, so any help would be appreciated.
Tycho resolves the dependencies from the Eclipse descriptor files (MANIFEST.MF, feature.xml, etc.) and re-orders the modules so that required artifacts are built first.

How can I share non-OSGi libraries between bundles in an OSGi container?

I came across this question when trying to share the Struts packages among multiple bundles inside an OSGi container. I wanted to avoid both duplicating dependencies inside the bundles and introducing a new dependency between them (by having one bundle export its internal dependencies for the other to share).
It turns out the answer is very easy if you happen to use Maven, and if you aren't, you can still use the Maven solution to learn how to create the same result with some other mechanism.
I found this approach useful multiple times during my project, so I'll post an example here.
An additional path for those not so keen on maven, unable to port, or perfectly happy with ant/ivy
I've found the that easiest way to accomplish the stated task is to turn the non-OSGi library into an OSGi library by letting the manifest export every package and add on some approriate symbolic names / versions. I've been able to do this VERY easily with bnd via ant tasks (or even direct command line invocation). There are also repositories which contain "osgi-ified" version of many popular libraries. Some libraries (joda-time) are already shipping with correct OSGi manifests.
Using Maven, it is very easy to create an OSGi bundle from any library. However, I think the same result can be created with other mechanisms, too. The Maven solution helped me understand how it works.
Creating the bundle is done by creating a project which has the library as a dependency and then packaging the project using the maven-bundle-plugin from the Apache Felix project and specifying the library packages with the Export-Package instruction. I used this to share Google Protocol Buffers between bundles inside an OSGi container:
<?xml version="1.0" encoding="UTF-8" ?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.lib</groupId>
<artifactId>protobuf-dist</artifactId>
<version>2.1.0</version>
<name>Google Protocol Buffers OSGi Distribution</name>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.google.protobuf</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
If you want all transitive dependencies rolled into the bundle, too, use the bundleall goal of the plugin.
The plugin recognizes and honours existing OSGi manifests in the dependency.
You can also use the bundle plugin to just create the manifest and tell the jar packaging plugin (or the jar-with-dependencies builtin assembly) to use that manifest via the archive section. The plugin's page linked above shows how to do that.

Resources