Maven: unzip os-based zip file to WEB-INF/lib - java

I have 2 .zip files: shared-lib-windows.zip and shared-lib-linux.zip. A maven dependency jar looks for the the shared-lib directory under WEB-INF/lib/ and expects .exe or .out file to be present in the shared-lib directory.
How do I setup the .zip files in my pom.xml so that the appropriate zip file is picked up, extracted to the renamed(shared-lib, without the -os) directory?
I have already setup the maven dependency (jar) as:
<profiles>
<profile>
<id>Linux</id>
<dependencies>
<dependency>
<groupId>com.dependency</groupId>
<artifactId>depedency-linux</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>Windows</id>
<dependencies>
<dependency>
<groupId>com.dependency</groupId>
<artifactId>dependency-windows</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>
</profile>
</profiles>
Now I just want Maven to pick up the .zip files from either src/main/resources or .m2/.../ and do the magic!
I have looked into answers which suggested maven-ant-plugin, but someone mentioned that'd be uncool.
[edit: add info]
I have a Maven web-project packaged as a .war and deployed to Tomcat.
Also, the .exe/.out files are a 3rd party dependency with a size of 120/150 MB respectively. Since my git does not have large file support and the binaries won't be updated, I've zipped it and added to my Git managed Maven web-project.

I went through official documentation about Maven profiles, phases and properties.
I came up with a solution that uses maven-antrun-plugin. I'm still looking for a solution that does not rely on it.
Run the below pom.xml on Linux with: mvn package -P Linux
<profiles>
<profile>
<id>Linux</id>
<properties>
<binary.zip>${project.basedir}/src/main/resources/binary-linux.zip</binary.zip>
<unzip.folder>${project.build.directory}/${project.build.finalName}/WEB-INF/lib/binary</unzip.folder>
</properties>
<dependencies>
<dependency>
<groupId>com.dependency</groupId>
<artifactId>depedency-linux</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>Windows</id>
<properties>
<binary.zip>${project.basedir}/src/main/resources/binary-windows.zip</binary.zip>
<unzip.folder>${project.build.directory}/${project.build.finalName}/WEB-INF/lib/binary</unzip.folder>
</properties>
<dependencies>
<dependency>
<groupId>com.dependency</groupId>
<artifactId>dependency-windows</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>
</profile>
</profiles>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>unzip-binary</id>
<phase>prepare-package</phase>
<configuration>
<tasks>
<echo message="unzip the binary" />
<unzip src="${binary.zip}" dest="${unzip.folder}" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
This will extract the .zip into the ..WEB-INF/lib/binary directory (in the prepare-package phase) before archiving it into a .war (in the package phase) with maven-war-plugin plugin.

Related

Maven javafx:jlink. How to specifiy the module-path used?

I'm currently working on a modular JavaFX application and I'm using maven to compile/deploy it.
One of the dependencies of my application is JBibTex which doesn't have a module-info file so it's used as an automodule. In order for my javafx:jlink to work (because javafx:jlink cannot work on automodules), I had to convert JBibTex to an explicit module. I used the maven's ModiTect plugin for that.
I used ModiTect to generate the module-info file for the JBibTex library and I added it to the JBibTex's jar file (I used moditect:add-module-infos for that).
Now the problem is that javafx:jlink uses the JBibTex.jar file that is located in my ".m2" folder (where maven automatically downloads all your projects' dependencies). The JBibTex.jar file located in my .m2 folder is not the file to which I added the module-info file.
So I still get the error:
Error: automatic module cannot be used with jlink: jbibtex
The explicit JBibtex module that I have generated through the use of ModiTect is automatically put in target/modules by my ModiTect plugin configuration.
How can I get javafx:jlink to use the target/modules/JBibTex.jar file that contains the module-info.class file and not the JBibTex.jar of my .m2 folder?
Here is my pom.xml just in case:
<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>xxx</groupId>
<artifactId>BRM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>BRM</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
<mainClass>xxx.App</mainClass>
<moduleName>xxx.brm</moduleName>
<javafx.version>17.0.1</javafx.version>
<javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version>
</properties>
<dependencies>
<!-- javafx dependencies -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jbibtex/jbibtex -->
<dependency>
<groupId>org.jbibtex</groupId>
<artifactId>jbibtex</artifactId>
<version>1.0.17</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>configs</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>15</source>
<target>15</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.maven.plugin.version}</version>
<configuration>
<mainClass>${mainClass}</mainClass>
<launcher>launcher</launcher>
<jlinkImageName>BRM</jlinkImageName>
</configuration>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>1.0.0.RC2</version>
<executions>
<execution>
<id>add-module-infos</id>
<phase>generate-resources</phase>
<goals>
<goal>add-module-info</goal>
</goals>
<configuration>
<overwriteExistingFiles>true</overwriteExistingFiles>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<modules>
<module>
<artifact>
<groupId>org.jbibtex</groupId>
<artifactId>jbibtex</artifactId>
<version>1.0.17</version>
</artifact>
<moduleInfoSource>
module jbibtex
{
exports org.jbibtex;
}
</moduleInfoSource>
</module>
</modules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Specifically to answer your question:
How to specify the module-path used?
You could run jlink from the command-line instead of via Maven.
That way you can specify any module path you wish.
From the man page for jlink:
jlink [options] --module-path modulepath --add-modules module [, module...]
modulepath
The path where the jlink tool discovers observable modules. These modules can be modular JAR files, JMOD files, or exploded modules.
module
The names of the modules to add to the runtime image. The jlink tool adds these modules and their transitive dependencies.
If you wish to continue using the openjfx maven plugin jlink command, you can do that.
The code which configures the module path passed to jlink by the maven plugin is in git.
if (modulepathElements != null && !modulepathElements.isEmpty()) {
commandArguments.add(" --module-path");
String modulePath = StringUtils.join(modulepathElements.iterator(), File.pathSeparator);
if (jmodsPath != null && ! jmodsPath.isEmpty()) {
getLog().debug("Including jmods from local path: " + jmodsPath);
modulePath = jmodsPath + File.pathSeparator + modulePath;
}
commandArguments.add(modulePath);
commandArguments.add(" --add-modules");
if (moduleDescriptor != null) {
commandArguments.add(" " + moduleDescriptor.name());
} else {
throw new MojoExecutionException("jlink requires a module descriptor");
}
}
This is based on the javafx:jlink options:
jmodsPath: When using a local JavaFX SDK, sets the path to the local JavaFX jmods
So if you put your module on the path specified by that option, it should be found.
Here are some other options.
Package your app as a non-modular app using jpackage
I think mipa's suggestion of using JPackageScriptFX is probably the best approach:
github.com/dlemmermann/JPackageScriptFX
Create a new jar from binaries
Unjar the JBibTex.jar.
Add in the compiled module-info to unjared directory.
Create a new jar, e.g. JBibTexModule.jar.
Install that to your maven repository via a mvn install command.
Add a maven dependency on JBibTexModule instead of JBibTex.
Add any needed statements to your main app module-info file to use the library.
Then, I believe you are done, and it would build, link, and run ok.
Create a new jar from source
The jbibtex library is also in github, so you could create an issue or pull-request on the project to ask it to be modularized.
Also, you could:
Clone the repository.
Add the module-info.java.
Build the jar file.
Install it locally in your local maven repository.
Then depend on the local version you have created.

How do I include tools.jar in my dependencies?

This reference explained how to include tools.jar in the dependencies.
But I don't know where should I insert that code to?
Should I insert it to the setting.xml of Maven or the pom.xml of my Java project?
I used the default maven in Eclipse 4.5.2(Mars.2 Release in Win7).
I want to include tools.jar in my project.
I could use the following code to include it in the pom.xml.
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<scope>system</scope>
<version>1.4.2</version>
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
I also want to try to use java.home, not JAVA_HOME.
I only know that they are different, but I don't exactly know the differences between them.
After reading that reference, I want to try it out. But I failed.
So how should I use java.home to configure the pom.xml file to include tools.jar?
UPDATE:
I could reference java.home like this:
<project ...>
...
<properties>
<java.home>D:\Program Files\Java\jdk1.6.0_45</java.home>
</properties>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.4.2</version>
<scope>system</scope>
<systemPath>${java.home}/lib/tools.jar</systemPath>
</dependency>
</dependencies>
</project>
You can define a similar profile in your pom.xml as -
<!--This can help you use a custom java home path-->
<properties>
<java.home>/your/path/to/java</java.home>
</properties>
...
<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.4.2</version>
<scope>system</scope>
<systemPath>${java.home}/relative/path/to/lib/tools.jar</systemPath>
</dependency>
</dependencies>
</profile>
Using the reference mentioned to form the profile above.
You need to specify the path to your custom Java home under the properties which can further replace it in the systemPath under the dependency where you specify further the relative path to the tools.jar.
#nullpointer is correct, just to add on the maven properties regarding your java home, you can see the output of the Maven java.home property as compared to your JAVA_HOME environment variable with running mvn validate and adding to your pom the code snippet below:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Displaying value of java home property: ${java.home}</echo>
<echo>Displaying value of JAVA_HOME variable: ${env.JAVA_HOME}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
For example, on my system it outputs (among other things):
[echo] Displaying value of java home property: /usr/lib/jvm/java-8-openjdk-amd64/jre
[echo] Displaying value of JAVA_HOME variable: /usr/lib/jvm/java-8-openjdk-amd64

Including classes and jars from a local war file with maven

I have a War file that has dependencies and class files that I need in it that I am trying to include in my project with Maven. Inside the War file, there is a WEB-INF that contains those libs and classes. I have tried everything that I know to try to get this going, but my knowledge of Maven is limited.
I have tried simply listing the War as a dependency and following the process described here to install the third-party library, but when I do that Maven says it can't find my packages that I need when I try to install.
I have tried overlaying the War as described here with no luck.
I have tried maven-warpath-plugin but didn't really have any luck either.
Should any of these tools solve my problem? Is how I am trying to solve the problem possible in this way? Or am I completely off base?
Here are the important parts of my pom.xml from using the maven-warpath-plugin:
<build>
...
<pluginManagement>
<plugins>
<plugin>
<groupId>org.appfuse</groupId>
<artifactId>maven-warpath-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>add-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
...
</build>
<repositories>
<repository>
<id>data-local</id>
<name>data</name>
<url>file://${project.basedir}/o</url>
</repository>
</repositories>
<dependencies>
...
<dependency>
<groupId>my.local.dep</groupId>
<artifactId>MyLocalDep</artifactId>
<version>1.1.1.1</version>
<type>war</type>
</dependency>
<dependency>
<groupId>my.local.dep</groupId>
<artifactId>MyLocalDep</artifactId>
<version>1.1.1.1</version>
<type>warpath</type>
</dependency>
</dependencies>
Unpack the war in a separate clean step first and add the unpacked jars as system dependency in the main step.
Idea is from here: https://stackoverflow.com/a/6120395/503025

mvn generate-sources fails, why isn't xml beans on classpath?

I'm trying to generate java classes for OGC KML 2.2 as part of the maven generate-sources process using the org.codehaus.mojo xmlbeans-maven-plugin. The java code appears to be generated correctly, but I get tons of errors during compilation complaining that 'package org.apache.xmlbeans'. XMLBeans is clearly a dependency, it exists in my ~/.m2 repository, and I've been peek in the jar to make sure the classes are there. It looks like XMLBeans is successfully generating java files in target/generated-sources, but somehow its absent from the classpath during compilation.
I've tried changing the scope of the org.apache.xmlbeans dependency, but to no avail.
Here's the pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>net.opengis</groupId>
<artifactId>ogc-kml</artifactId>
<version>2.2.0</version>
<packaging>pom</packaging>
<name>ogc-kml</name>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xmlbeans-maven-plugin</artifactId>
<version>2.3.3</version>
<executions>
<execution>
<goals>
<goal>xmlbeans</goal>
</goals>
</execution>
</executions>
<inherited>true</inherited>
<configuration>
<download>true</download>
<schemaDirectory>src/main/xsd</schemaDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
The project consists of a single src/main/xsd folder containing the two xsds from http://schemas.opengis.net/kml/2.2.0/. The entire folder structure is at https://github.com/iancw/maven-xmlbeans-question.
I can compile the classes by hand if I put the xmlbeans jar from my ~/.m2 repo on the classpath, e.g.
xmlbeans$ javac -classpath ~/.m2/repository/org/apache/xmlbeans/xmlbeans/2.4.0/xmlbeans-2.4.0.jar org/w3/x2005/atom/*.java org/w3/x2005/atom/impl/*.java net/opengis/kml/x22/*.java x0/oasisNamesTcCiqXsdschemaXAL2/*.java x0/oasisNamesTcCiqXsdschemaXAL2/impl/*.java net/opengis/kml/x22/*.java net/opengis/kml/x22/impl/*.java
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
xmlbeans$
I've looked through a number of examples and it seems like I'm doing this right. I haven't seen anyone else complain of this issue. Any maven mavens have suggestions?
(A curious side note is that although i've tried both 2.4.0 and 2.6.0 of the xmlbeans dependency, maven hasn't ever seemed to download the 2.6.0 version into my repository)
From the POM file that you've included in your question you have only defined the xmlbeans dependency in the dependencyManagement section. You also need to define it in your dependencies section of your POM before it will be included in the classpath at build time.
So for example your POM would be:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xmlbeans-maven-plugin</artifactId>
...
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
</dependencies>
One Additional issue that may look similar,
Check your java install jdk and ext folders for older beans jar.
The plugin puts the project dependencies at the end of the classpath.

GWT project deployment to tomcat in STS(Eclipse)

I have a maven project in STS(Eclipse) and I try deploying it to Tomcat 6 in STS. For maven install I use gwt-maven-plugin. Installed war contains all folders (WEB-INF/, META-INF/, compiled GWT frontend folder). When I deploy this project to tomcat (in STS), there are only WEB-INF and META-INF folders in webapps/project folder. Folder with compiled GWT frontend is nowhere to find. In context.xml I even tried to set docBase to installed war, but no difference in result. Have anyone an idea where problem could be?, because now I have to manually copy this folder to unpacked folder in webapps. Thanks alot.
Might be a configuration problem, post your gwt-maven-plugin xml here.
Here's mine, just for reference
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${gwt.version}</version>
<configuration>
<logLevel>DEBUG</logLevel>
<style>PRETTY</style>
<runTarget>/ApplicationScaffold.html</runTarget>
<hostedWebapp>${project.build.directory}/${project.build.finalName}</hostedWebapp>
<!-- <modules><module>${project.groupId}.Main</module></modules>-->
<copyWebapp>true</copyWebapp>
<debugPort>8001</debugPort>
<extraJvmArgs>-Xmx900m</extraJvmArgs>
<!-- instruct plugin not to require open browser in test mode -->
<mode>htmlunit</mode>
<!-- compiler speed up -->
<draftCompile>true</draftCompile>
<optimizationLevel>0</optimizationLevel>
<disableAggressiveOptimization>true</disableAggressiveOptimization>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
</execution>
</executions>
<dependencies>
<!-- must override the plugin's default dependencies -->
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwt.version}</version>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>${gwt.version}</version>
</dependency>
</dependencies>
</plugin>

Categories