Adding another project's jar as a resource using Maven - java

Within my project I have a sub-project auto-updater. Basically a jar file that is extracted and run when an update is available.
Is it possible to compile the sub-project, then place the outputted jar as a generated-resource so that the updater.jar is included in the final jar such as:
Project-1.0.jar
|-updater.jar
|-Main.class
|-B.class
Thanks in advance for any help(I'm new to Maven)

This task is calling for maven-assembly-plgin or maven-dependency-plugin
(I expect that updater is also maven project) this shoudl be proper configuration for maven-dependency-plugin [I did not test this, you might also need to put updater to project depndencies]
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>company.com.project</groupId>
<artifactId>Updater</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<outputDirectory>${project.build.outputDirectory}/classes</outputDirectory>
<destFileName>updater.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>

It would be nice if your little jar is also built with Maven.
Then let's say your little jar POM's contains this:
<groupId>company.com.project</groupId>
<artifactId>Updater</artifactId>
<version>0.0.1-SNAPSHOT</version>
Then your Project-1.0 should use this dependency:
<dependency>
<groupId>company.com.project</groupId>
<artifactId>Updater</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

Add the sub project to your parent project as follows
<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/maven-v4_0_0.xsd">
<modelVersion>1.0.0</modelVersion>
<groupId>Project-1.0</groupId>
<artifactId>myproject</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Project-1.0</name>
<modules>
<module>../updater</module>
</modules>
...
</project>
Then in you updater project pom file make the following changes
<?xml version="1.0"?>
<project>
<parent>
<artifactId>myproject</artifactId>
<groupId>Project-1.0</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>Project-1.0</groupId>
<artifactId>updater</artifactId>
<version>1.0-SNAPSHOT</version>
...
</project>
When you compile your parent project, the child project will automatically get compiled.
Then to add the sub project jar in your jar, add the following plugin in parent pom.xml
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/lib">
<fileset dir="${location of updater1.0.jar}"/>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Related

Make windows stand-alone executable file for spring boot project and angular project which can access offline in windows

I have one jar file which bundles with UI now I want to make one standalone window executable file. in the jar file, I have code with PostgreSQL database tomcat server
my pom file for the project like
I want only one exe which has run directly on double click
<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">
<parent>
<groupId>dev.marco</groupId>
<artifactId>java-angular-example</artifactId>
<version>0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputEncoding>UTF-8</project.build.outputEncoding>
</properties>
<artifactId>backend</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>frontend</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
....
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<mainClass>dev.marco.ShlowinApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
</project>
The closest I can think of would be launch4j, adding an exe launcher for your application. This will add the exe, but will not magically make it a desktop-application, for that you may need to adjust code.
A configuration in the pom.xml would look similar to the following:
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>l4j-gui</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
<configuration>
<headerType>gui</headerType>
<outfile>target/${project.artifactId}.exe</outfile>
<jar>target/${project.artifactId}.jar</jar>
<dontWrapJar>false</dontWrapJar>
<addDependencies>true</addDependencies>
<errTitle>Error in launch4j plugin</errTitle>
<classPath>
<mainClass>${mainClass}</mainClass>
</classPath>
<icon>src/main/resources/Images/logo.ico</icon>
<jre>
<path>./java</path>
</jre>
<versionInfo>
<fileVersion>${project.version}.0</fileVersion>
<txtFileVersion>${project.version}.0</txtFileVersion>
<fileDescription>${description}</fileDescription>
<copyright>Copyright(c) ${distributor}</copyright>
<companyName>${distributor}</companyName>
<productVersion>${project.version}.0</productVersion>
<txtProductVersion>${project.version}.0</txtProductVersion>
<productName>${project.artifactId}</productName>
<internalName>${project.artifactId}</internalName>
<originalFilename>${project.artifactId}.exe</originalFilename>
<language>ENGLISH_UK</language>
</versionInfo>
</configuration>
</execution>
</executions>
</plugin>

Antlr4 in own Maven module

When I build the maven Module that is using Antlr4 and look in the Jar the compiled generated sources from Antlr4 are in the Root folder.
But when I want to include the Jar with the generated sources in my Antlr4-impl module as dependency where I want to use the generated classes they can't be found.
How I can link them up correctly ? Do I have to move the generated Sources to the maven src/main/java section ? Do they need a package ? If yes, how can I set the package for the sources in the maven plugin ?
Here is My pom.xml form the antlr generation module:
<?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">
<parent>
<artifactId>net-site-arti</artifactId>
<groupId>net.site.reverse</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>net-site-arti-antlr</artifactId>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.7.1</version>
<configuration>
<outputDirectory>src/main/generated-sources</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And here is the pom.xml form the module where I want to implement the classes:
<?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">
<parent>
<artifactId>net-site-arti</artifactId>
<groupId>net.site.reverse</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>net-site-arti-antlr-impl</artifactId>
<dependencies>
<dependency>
<groupId>net.site.reverse</groupId>
<artifactId>net-site-arti-antlr</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7.1</version>
</dependency>
</dependencies>
</project>
EDIT: Add build-helper-maven-plugin same result - the classes are in the root folder from the generated jar but the module that will use them don't pick up the classes.
Tried also with the maven-shade-plugin in this configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern></pattern>
<shadedPattern>org.shaded.plexus.util.</shadedPattern>
<excludes>
<exclude>org.codehaus.plexus.util.xml.Xpp3Dom</exclude>
<exclude>org.codehaus.plexus.util.xml.pull.*</exclude>
</excludes>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
different jar but some result - in the jar the classes are under: org/shaded/plexus/util/ but the module can't import the classes.
Not a perfect solution but a solution:
In this post they say you can add the package name in a #header tag in the *.g-File. Unfortunately ANTLR doesn't generate the package in the Sourcefolder it only generated the Class-Files with the package declaration. So you have to generate them in the package:
here is an example pom:
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.7.1</version>
<configuration>
<outputDirectory>src/main/java/net/site/antlr</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
And if you add this to the g-File:
#header {
package net.site.antlr;
}
But you can't generate, with this solution, different grammar in different packages.

maven-assembly-plugin step failure: "[WARNING] The following patterns were never triggered in this artifact inclusion filter"

I am trying to add a global version property to my multi-module
Maven project, so that I can easily update the version of all
modules by updating a single property rather than several pom
files. The problems is that this property is breaking maven-
assembly-plugin that collects the compile module jars into a zip
folder for distribution. When the version was hard-coded in all
the pom files, everything worked swimmingly. When I converted to
a property, however, the individual module jars still compiled,
but the maven-assembly-plugin step failed after the following
warning: "[WARNING] The following patterns were never triggered
in this artifact inclusion filter"
The assembly filters seem to be missing the modules, I just can't
explain why this happens when I use the global property, or how
to fix it.
Project structure:
MyProject
--ModuleA
pom.xml
--ModuleB
pom.xml
--Distribution
src\main\assembly\distribution-assembly.xml
pom.xml
pom.xml
MyProject/pom.xml:
<groupId>com.mycompany</groupId>
<artifactId>MyProject</artifactId>
<packaging>pom</packaging>
<version>${global.version}</version>
<properties>
<global.version>1.0.1-SNAPSHOT</global.version>
</properties>
ModuleA/pom.xml:
<parent>
<artifactId>MyProject</artifactId>
<groupId>com.mycompany</groupId>
<version>${global.version}</version>
</parent>
<artifactId>ModuleA</artifactId>
ModuleB/pom.xml:
<parent>
<artifactId>MyProject</artifactId>
<groupId>com.mycompany</groupId>
<version>${global.version}</version>
</parent>
<artifactId>ModuleB</artifactId>
Distribution/pom.xml:
<parent>
<artifactId>MyProject</artifactId>
<groupId>com.mycompany</groupId>
<version>${global.version}</version>
</parent>
<packaging>pom</packaging>
<artifactId>Distribution</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>
src/main/assembly/distribution-assembly.xml
</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>
single
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Distribution/src/main/assembly/distribution-assembly.xml:
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>com.mycompany:ModuleA</include>
<include>com.mycompany:ModuleB</include>
</includes>
<binaries>
<outputDirectory>MyBuildFolder</outputDirectory>
<outputFileNameMapping>mycompany${module.artifactId}.${module.extension}</outputFileNameMapping>
<unpack>false</unpack>
</binaries>
</moduleSet>
<moduleSets>
Warning:
[WARNING] The following patterns were never triggered in this artifact
inclusion filter:
o 'com.mycompany:ModuleA'
o 'com.mycompany:ModuleB'
Error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-
plugin:2.4:single (make-assembly) on project Distribution:
Failed to create assembly: Error creating assembly archive bin: You must
set at least one file. -> [Help 1]
Try to add your ModuleA and ModuleB as a depenedency of the distribution pom.
the Dstibution/pom.xml should look like this :
<parent>
<artifactId>MyProject</artifactId>
<groupId>com.mycompany</groupId>
<version>${global.version}</version>
</parent>
<packaging>pom</packaging>
<artifactId>Distribution</artifactId>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>ModuleA</artifactId>
<version>${global.version}</version>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>ModuleB</artifactId>
<version>${global.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>
src/main/assembly/distribution-assembly.xml
</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>
single
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

Shaded/Repackaged jar as a dependency

We have a situation where we need one application to be able to connect to to two versions of kafka(0.7.2 and 0.10.0+) and act as a router. I'm trying to omit using two runtimes here as we need this to be stupid fast, so want to prevent additional serialization/deserialization when sending data between runtimes.
To do this, i've tryied to repackage the old kafka driver from package kafka to old.kafka like so:
<?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">
<parent>
<artifactId>kafka-router</artifactId>
<groupId>org.deer</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>old-kafka</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kafka.version>0.7.2</kafka.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>unpack</id>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.9.2</artifactId>
<version>${kafka.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>**/*.class,**/*.xml</includes>
</artifactItem>
</artifactItems>
<includes>**/*.java</includes>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>kafka.</pattern>
<shadedPattern>old.kafka.</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I'm using dependency plugin to unpack kafka classes to target/classes & shade plugin to repackage them. The reason for this is that the final jar should act as if it is a kafka driver jar(it has no other transitive dependencies, therefore it can't cause some mismatch using kafka instead of old.kafka. But that's not really the point here, just trying to prevent out-of-topic questions.
The main problem here is that when i look at the jar that has been installed to .m2, it looks correct(having the old.kafka package):
But when i try to use this jar as dependency like so ...
<?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">
<parent>
<artifactId>kafka-router</artifactId>
<groupId>org.deer</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>router-app</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.deer</groupId>
<artifactId>old-kafka</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
... and reference it in a class like so ...
package org.deer.test;
import old.kafka.producer.ProducerData;
public class TwoKafkaDriversExample {
public static void main(String[] args) {
new ProducerData();
}
}
... the import it self is not working. I have a suspicion that the shaded jar is missing something maven-related, but haven't noticed anything. Another possible though is that shade plugin or asm doesn't like the bytecode that scala classes are generating.
Ok, so i've been able to figure this out. The import error is a problem with intelij, for some reason it doesn't see the repackaged classes. But the maven does, with using correct constructor and adding scala-lang dependency(it was complaining about missing Seq class) i was able to build this.
Full example uploaded on github - https://github.com/Marssmart/kafka-router

How to run a dependency jar in maven before running the current project

I have a maven project in which I'm trying to get a jar from a remote repository and add it to my local repository. After adding instead of referring its class, I need to run that jar which acts as a input for my current project.
I tried, and there are no build issues, but still it is not triggering to run the dependency.
My 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>secmaven</groupId>
<artifactId>secmaven</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>secmaven</name>
<description>secmaven</description>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>exec-one</id>
<phase>verify</phase>
<configuration>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<executableDependency>
<groupId>parent</groupId>
<artifactId>parent</artifactId>
</executableDependency>
<!-- Look up the main class from the manifest inside your dependency's JAR -->
<mainClass>mainclass</mainClass>
<arguments>
</arguments>
</configuration>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>parent</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>C:\....\parent.jar</systemPath>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
You can use a maven aggregator project pom for that.
Example:
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<modules>
<module>proj1</module>
<module>proj2</module>
</modules>
</project>
This way proj1 will always run before proj2.
I think is this what you want.
See https://maven.apache.org/pom.html#Aggregation for more information.

Categories