Maven - Executable file from a java project - java

I need to use maven (for a school project) to create an executable file from a single maven command. I've never used maven and tried many solutions here on stackoverlow. The solutions created a jar file, but the file never opened.
This is my project structure
src
com
project
code
swing
programm
interface
Main.class
I know this isn't maven convention, however changing it now would mean I would have to adjust the imports (as intelliJ doesn't refactor everything perfectly) for around 40 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">
<modelVersion>4.0.0</modelVersion>
<groupId>MyGroup</groupId>
<artifactId>myProgramm</artifactId>
<version>0.7-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Hello World</name>
<description>Course Project</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.25.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit/junit5-engine -->
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit5-engine</artifactId>
<version>5.0.0-ALPHA</version>
</dependency>
</dependencies>
<build>
</build>
What do I have to put inside to make an executable file?

TimurJD's answer is correct however I would like to explain step by step what is actually happening and why.
To have a jar be executable the JVM needs to know where your main method is.
For that you need a file called META-INF/MANIFEST.MF inside the jar you create.
This file must contain a reference to the class containing your main method which is done like this:
Main-Class: com.example.ClassContainingMainMethod
There are many ways of creating said file but since you are using maven here is the plugin that will help you create this manifest file
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.my.packege.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Once you have the plugin in your pom.xml simply run the maven install goal, either from your IDE or the command line. After you should find a folder called target in your project. That folder will contain the executable jar.
To run the jar you can call from the command line:
java -jar MyProject.jar
It should also be noted that unless you abide by the maven standard of keeping your source code in src/main/java you will have to specify your source folder explicitly.

You need to add plugin to your pom.xml file
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.example.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
and to run the program: mvn clean install exec:java
... here is the link for doc http://www.mojohaus.org/exec-maven-plugin/usage.html
There are possible different solutions, depends on your requirements: https://www.baeldung.com/executable-jar-with-maven

Related

Multi-module JavaFX maven project packaging issue

This is an attempt to create a multi-module JavaFX application with maven.
Given the following structure of the project:
project
| pom1.xml
|_____ Word Generator (Folder)
| pom2.xml
|_____logic (folder)
| WordGenerator
|_____UI (folder)
| pom3.xml
|_____marty
| App
| PrimaryController
| SecondaryController
We have the following structure of the pom files in order of the scheme above:
pom1.xml
<?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>org.games.marty</groupId>
<artifactId>words</artifactId>
<packaging>pom</packaging>
<version>0.1</version>
<modules>
<module>UI</module>
<module>Word Generator</module>
</modules>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
pom2.xml
<?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>words</artifactId>
<groupId>org.games.marty</groupId>
<version>0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>word.generator</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.games.marty.logic.WordGenerator</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
pom3.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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>UI</artifactId>
<version>0.1</version>
<parent>
<artifactId>words</artifactId>
<groupId>org.games.marty</groupId>
<version>0.1</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.games.marty</groupId>
<artifactId>word.generator</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>16</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>org.games.marty.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.games.marty.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
The way we have attempted to build the application in order for the UI to have access to the WordGenerator logic is to maven package the result from the pom1.xml directive
We get the above error as mentioned earlier:
Error: Could not find or load main class org.games.marty.App
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
As far as my understanding goes, the JavaFX dependencies are installed throught maven and should be available but they are missing?
Packaging via mvn package using the maven-jar-plugin is not enough
mvn package, by default, is just going to package the jar for your application code, it isn't going to include all of the dependant library code (which is why the dependent code cannot be found when you attempt to run your application).
You could package your application code and dependant libraries using an assembly, as detailed in How can I create an executable JAR with dependencies using Maven?, though that approach is not the only one to solve your problem.
You need to build some kind of runtime image
There are numerous options for building runtime images and I don't know your requirements, so I can't recommend what you should do instead. Example options are:
A zip/tar of your application plus libraries in a separate directory.
The creation of a single jar that includes all dependant code.
Either of solutions 1 or 2, plus the inclusion of a packaged JRE.
A runtime image with your code and libraries which also uses just the custom runtime portions of the JRE and JavaFX modules you need (using jlink).
A native installer for either 3 or 4 (using jpackage + a native installer creation tool, e.g. WIX, RPM, DEB installer creators).
The last method (native installer), is the packaging, distribution, and installation method I would recommend for most non-trivial applications.
You need to research how to do this
To get your solution, you will need to do your own research, and, once you have chosen an approach and toolset, you could create a new question regarding the implementation of that approach, if you continue to have difficulties.
Related resources
How can I create an executable JAR with dependencies using Maven?
openjfx Runtime images documentation
maven shade plugin
Maven Shade JavaFX runtime components are missing
openjfx JavaFX maven plugin
badass runtime plugin
badass jlink plugin
jlink guide
jpackage script
JEP 392: packaging tool
Warning for shaded jars
If you bundle all JavaFX code into a single jar using the maven shade plugin, you will get a warning like the following when you run your application from Java 16+:
WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module #28c71909'
This indicates that such a configuration is not supported, and may (and probably will) break in future and perhaps current JavaFX platform revisions. Thus, shaded jars that include JavaFX platform code are not recommended by me, even though such jars might currently work for your deployments.
JavaFX 11+ is built to be used as a set of modules. Configurations are not supported if they do not run the JavaFX platform off of the module path but instead run the platform code off of the classpath (as a shaded jar would).

Maven not generating Main Class entry in MANIFEST.MF

I am trying to build a project in Java that should run if executed with double click. That's not been working so I debugged with cmd and there was no main class entry in the manifest.
So i added the contents of this answer (adopted to my application): Missing Main-Class attibute in MANIFEST.MF in Maven generated jar file
I am using jenkins as build platform and have tried executing with mvn clean install and mvn clean package.
pom.xml:
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>de.progii</groupId>
<artifactId>pong</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>pong</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.progii.pong.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
I partly fixed the problem. The problem is not the maven jar plugin, its jenkins. It simply archives the wrong build. The artifact available for download seems to be archived before the maven jar plugin does the job. If I connect with sftp to the workingspace/target folder I can download the artifact with the same name as the artifact at the jenkins download page but execute it successfully!
edit
With the latest Update to Jenkins its working correctly

Maven Build - Class Files Size is reduced

I am trying to mavenize an existing project.
I was able to build the EAR file(since i have to deploy in Websphere), When I try to deploy, using admin console - Able to install successfully , But application is not working, After investigating, I found the class files size is very less compare to the reference EAR file(old existing EAR file)
Steps I followed to build the EAR file
M2E plugin installed
Configure to Maven
Add ALL the jar files from lib folder like below(I read in SO, this is not the recommended way, but to complete the project, I have to do this)
<dependency>
<groupId>JarFile</groupId>
<artifactId>JarFile</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/WebContent/WEB-INF/lib/CRDBXMLExternal.jar</systemPath>
</dependency>
Added the relevant plugins (war, EAR)
Clean Build and Install.
ear file created. ear contains a war file, which has all the project related files including class,jsp etc.
I compared the folder structure with the existing EAR file and its contents , all look good. But only the size of class files(Not ALL but more than 80%) are varying. I use JD to decompile and see the code, Most of the code are not present, including imports.
If anyone has encountered similar issue , could you please tell me what am doing wrong here.
More Info
there are two project folders(both are maven) one will create WAR and another one EAR in EAR pom.xml
there is a dependency
<dependency>
<groupId>com.comp.abc</groupId>
<artifactId>abc</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
Then there is a plugin
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10</version>
<configuration>
<version>5</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<generatedDescriptorLocation>C:\COMP\Dev\may\repos\0.0.1-SNAPSHOT</generatedDescriptorLocation>
</configuration>
</plugin>
</plugins>
</build>
Adding WAR file building(Removed most of the dependencies kept only one sample) 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>com.comp.abc</groupId>
<artifactId>abc</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>ABC</name>
<description>ABC</description>
<dependencies>
<!-- Local Repository -->
<dependency>
<groupId>com.ibm.ws.runtime</groupId>
<artifactId>com.ibm.ws.runtime</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/WebContent/WEB-INF/lib/com.ibm.ws.runtime.jar</systemPath>
</dependency>
</dependencies>
<repositories>
<repository>
<id>nexus-releases</id>
<name>nexus</name>
<url>http://abc-nexus.ldn.xyz.com:9080/nexus/content/groups/public/</url>
</repository>
</repositories>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<!-- <warSourceDirectory>${project.basedir}\WebContent</warSourceDirectory> -->
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
The above does not tell Maven to package the EAR file with the lib directory dependency. It actually tells it to create local dependency on an existing JAR that is provided only at compile time. Thus, when you export the EAR, it does not include any of the JARs because it assumes that they are provided at runtime.
You should use the maven-ear-plugin which package an EAR file instead. You can find the full documentation here.
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>3.0.1</version>
</plugin>
The issue was,
web/WebContent/WEB-INF/classes is not getting updated.
but I could see the latest classes under web/target/classes path.
Now am checking why web/WebContent/WEB-INF/classes is not getting updated.
Just now got the Resolution from the below Link :-
ISSUE SOLVED by with the help of
https://coderanch.com/t/474423/ide/ecplise-doesn-create-classes-folder
Steps
Right click on your project -> build path -> Configure build path -> click on source tab -> click on browse (Default output folder).
After browsing click on WebContent -> Select WEB-INF -> Create new folder (called classes). it will open new window.
Give folder name as classes. Click on Advanced and give path of current classes folder means WEB-INF/classes.
After doing this, eclispe will rebuild your project and classes will be genenrated at WEB-INF/classes directory.

"Could not find or load main class" when running a jar file from a msf4j project

I'm working on a Java project which uses the msf4j library. In IntelliJ IDEA I'm able to run the project, everything works as expected. However, If I build a jar file from this project (aplying the first part of this answer), the jar file cannot run (using java -jar my_jar.jar). It says:
Error: Could not find or load main class Main
I've cleaned the project several times, restarted everything, even tried to use older versions of the msf4j, nothing has helped.
If I replace the msf4j with something else (e.g. javalin), the built jar file is runnable, the problem goes away.
pom.xml:
<?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>my.group.id</groupId>
<artifactId>my_artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.wso2.msf4j</groupId>
<artifactId>msf4j-core</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
<properties>
<microservice.mainClass>src.main.java.Main</microservice.mainClass>
</properties>
</project>
MANIFEST.MF:
Manifest-Version: 1.0
Main-Class: Main
I think the problem is somewhere in the msf4j artifacts. Any idea how to fix this problem?
from the top of my head I thing you need to set in maven a project parent and remove the dependency.
<parent>
<groupId>org.wso2.msf4j</groupId>
<artifactId>msf4j-service</artifactId>
<version>2.5.2</version>
</parent>
HTH,
Gal

Building a maven project for deployment

Hello all I'm pretty new to using maven to build Java project so I'm sure the solution to my problem will be quite easy. I have installed the Eclipse Maven plugin and created a maven project. I now wish to package this project and distribute it as a runnable jar file. However when I run
mvn package
and then try to run the jar file I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: main/Formatter
The pom for this particular file looks like so:
<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>GROUP</groupId>
<artifactId>pcap.csv.xml</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>
Any help would be greatly appreciated.
You need to specify the main class in the jar plugin:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>main.Formatter</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
If you want to distribute a single jar you need to use a single-jarifier (fatjar, jarjar, onejar, etc.)

Categories

Resources