Load a config file into the classpath while using an executable jar - java

I am building an assembly in Maven for a command line utility. I can run it as an executable jar, but it fails because I need to load the config file externally. Assuming the following config, how would I run the jar?
Jar is in /opt/myapp/lib/myapp-assembly.jar
Config is in /etc/myapp/config/settings.xml
I'm loading the code from the classpath using ClassPathResource("/settings.xml");
Any help is appreciated!

I see two ways you could do it:
Launch the program using the jar as an archive rather than an executable jar, specifying the main class at run time. In other words, do java -classpath /opt/myapp/lib/myapp-assembly.jar:/etc/myapp/config [name of your main class].
Use the Class-Path field of the jar manifest file. Entries in it are directly added to the run time classpath, and there's nothing stopping you from specifying a filesystem directory rather than another jar file. So your manifest would contain: Class-Path: /etc/myapp/config/

Related

Add a jar file to another jar file

In my project I have this code that tell class loader to load Driver.class like so:
Class.forName(org.gjt.mm.mysql.Driver);
In Eclipse it runs with no problems and I have created the Jar file of the project. But I don't know how to insert the
mysql-connector-java-5.1.7-bin.jar
into a Jar file of my project. The folder structure look like this:
MANIFEST file:
Manifest-Version: 1.0
Main-Class: server.MultiServer
I am assuming that you finally just want to run your code as
java -jar myjar.jar
There are two options.
Keep mysql-connector-java-5.1.7-bin.jar next to your jar in the same folder and add classpath: mysql-connector-java-5.1.7-bin.jar to the manifest.
Copy all the classes in mysql-connector-java-5.1.7-bin.jar to your jar. Do not copy the jar but the classes in the jar. This is called a fat jar or uber jar. You can automate the same using maven shade plugin.
When you invoke your application jar add the -cp or -classpath option and provide the path to the dependent libraries, here the mysql-connector-java-5.1.7-bin.jar.
for example refer the below example
java -jar -classpath C:\myproject\lib\mysql-connector-java-5.1.7-bin.jar myproject.jar

java.lang.NoClassDefFoundError after building jar file in Intellij

The structure of my first app is simple:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
out
artifacts
...
production
...
src
META-INF
MANIFEST.MF
pl.krzysiu
App.java
CsvReplacer.java
Everything is fine during the compile and running the program. After building artifact jar file in the default out\artifacts directory, I get
java.lang.NoClassDefFoundError: net/sourceforge/yamlbeans/YamlException
when I try to run it by java -jar CsvReplacer.jar command
The libraries are included inside the jar file (they are there after unpacking it) - they are added to Libraries section in Project Structure (separately - one file per one lib), the whole libs dir is included in the Dependencies tab of Modules section (with export checkbox checked) and the libs dir is added in Output Layout of Artifacts section similarily.
The manifest file contains:
Manifest-Version: 1.0
Class-Path: libs\yamlbeans-1.0.jar libs\opencsv-3.8.jar
Main-Class: pl.krzysiu.App
Why the libs aren't visible for the App? If I copy this dir manually to the CsvReplacer.jar file's location - everything works fine.
The structure inside CsvReplacer.jar file looks like:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
META-INF
MANIFEST.MF
pl
krzysiu
App.java
CsvReplacer.java
IDE: Intellij IDEA 2016.3
The standard Java classloaders cannot find a JAR file embedded inside another JAR file.
You have two choices when making an executable JAR with dependencies.
Create a so-called uberJAR file by merging the contents of the dependent JARs into your main JAR.
References:
IntelliJ IDEA export Runnable program as Uber Jar
https://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/
Give your JAR a "Class-Path" manifest attribute to tell it where the (external!) dependent JARs are located.
You can't give a -cp and a -jar option together. But another alternative would be to get rid of the -jar option and use a -cp argument to specify the classpath.
Alternatively, you could implement a custom classloader that can load from a jar inside a jar, or use something like one-jar or Spring Boot.

NoClassDefFoundError Jar Error for org/apache/poi/ss/usermodel/Sheet

I have seen this question asked a lot, but I still can't figure out a solution to it. Well a solution that works for me. I have a project that is using Apache POI, and I made sure to include all the external JARs. The project compiles and runs fine in eclipse but when I run the jar with "java -jar Test.jar" I get this error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Sheet
I'm not sure if this is useful information, but I created a lib folder for my project and put the poi library in there. This means that the dependcies are in the JAR file when I create it, I figured I should mention this because I saw a few solutions about just having your external jars right next to your executable jar. I also tried setting my classpath to the directory of the project.
What do I seem to be doing wrong?
The Apache POI JAR file is not on your runtime classpath. Rebuild Test.jar with the following manifest entry in the MANIFEST.MF file
Class-Path: poi-3.9-20121203.jar
When the java -jar [filename].jar command fails, it's almost always because of one of two things:
Your MANIFEST.MF is messed up and doesn't list dependencies properly. Make sure all jar dependencies in your manifest file point to jars, relative to your jar's parent directory.
You are missing .class files, either in your specific jar or in one you depend on. Ensure your jar contains org/apache/poi/ss/usermodel/Sheet.class or that your manifest hierarchy points to a jar that contains that class.
You will need to provide classpath in Jar file's manifest file. See this official doc
An Example
We want to load classes in MyUtils.jar into the class path for use in MyJar.jar. These two JAR files are in the same directory.
We first create a text file named Manifest.txt with the following contents:
Class-Path: MyUtils.jar
First check if your target jar (Test.jar) is a fat jar containing all the required dependencies.
$ jar tf Test.jar
You should see your lib/ folder there containing all the required dependencies (including Apache POI). If that's the case do what others suggested, add Apache POI to your MANIFEST.MF.
About having your jar dependencies in a separate folder, as you suggested, that's also possible. Imagine your dependencies where stored in a lib/ folder outside your Test.jar. You could run your code with this command:
$ java -cp ".:lib/*" org.Test.Main
It simply adds all the .jars within lib/ folder to your classpath. In this case you also need to specify the name of the main class (full name).
I also got this problem and tried to google it..
i have found out that i have to read the error log
I cant save my file to .xls so
in my case after reading the error i found that a jar file is missing
i just added the jar file poi-3.7-20101029 located in the ext folder of my ireport
ex.YourIReportFolder/ireport/modules/ext-poi.x.x-xxxx
hope this helps :)

How to attach libraries to JAR file?

It works fine when compiling project, but after exporting it to a runnable jar and launching, it can't find external files and throws an error. What should I do?
Add external libraries to the manifest.mf:
Class-Path: . MyApp_lib/extlib.jar MyApp_lib/extlib2.jar ...
You could attempt building a fat jar that includes all the jars. It contains a custom class loader to load the jars referenced externally by your project.
Try using http://fjep.sourceforge.net/ plugin to build a fat jar.
You can export a java project containing jars using the File -> Export -> Other -> One Jar Exporter.
The jar thus exported works fine.
You have to keep all required jars in the classpath to run your jar. Run your jar like :
java -cp extlib/* -jar yourjar.jar OR java -cp lib1.jar:lib2.jar:.. -jar yourjar.jar
Make sure that while building the jar, you include all the used libraries(include everything from class path). This issue will happen when you refer a external jar.
You can include a classpath variable in the jar's manifest file.
JAR file classpath

Adding External jar's in Eclipse

I have created a program to connect to MySQL. I add Connector/j using eclipse add external jar option. Program works fine in eclipse. But when I created the executable jar using eclipse and when i run it, it always give ClassNotFoundException. Please tell me how to add external jars to my jar. Or is there any other error? Please can anyone help me.
The simplest solution is to export your project as a 'Runnable Jar file' (Right-click on project->Export...->Runnable Jar file) that will place all dependencies in one jar file.
Otherwise you will need to include a classpath to the additional jars either in the manifest.mf file or on the command line with the -cp option.
java -cp .;myjar.jar;mysql.jar my.package.classname
You need to create a jar that includes the files from all the dependent jars. The classloader won't be able to find the classes if you simply include the jar files themselves inside the executable jar. There is an eclipse plugin called FatJar that does this.
http://fjep.sourceforge.net/
You can simply add the class-path element to your jar MANIFEST and list your external jar inside the MANIFEST
like this:
Manifest-version:1.0
Class-Path: class0.jar
class1.jar
class2.jar
class3.jar
class4.jar
...
One jar per line.

Categories

Resources