I'm creating a new project that run as a Java application(.jar), but I am confused about how to package the lib folder into the final jar file.
And I try to use Maven, but did not found some eligable plugins.
The project structure is here
first, I try to package with IDEA's build Artifact. it will extract all jar file into final jar and create a MANIFEST file, but the impact is there are some file like "*.SF, *.RSA", it destory the java -jar xxx.jar, But we can solve it by delete these .sf/.rsa file. Next problem occur, cause I use some springframework dependency, when extract these jar file, they will create a file like spring.handles, but its not complete.
second, I try to use MAVEN. I use the maven-jar-plugin maven-compiler-plugin maven-dependency-plugin to copy all jar file into final jar, and create the correct MANIFEST file. BUT a java.lang.NoClassDefFoundError occur, I am DEAD!!!
So, the actual question is how can I package the lib folder into final executable jar???
Related
For a project, I created an executable jar using the maven shade plugin. So far it runs, as it should, double clicking it starts the application just like executing the main method in my IDE. My next task is to have a properties file (named connection.properties), which is needed for the application, outside of the jar (at best in the same directory that the jar is in). I have already successfully excluded it from the jar with a filter, but I don't know how make the jar use the file while it is in the same directory, but not in the jar itself.
Any help or comments would be appreciated very much.
if the jar is in the current directory:
Paths.get("").resolve('myfile')
if the jar is elsewhere, see That answer
You can do the following to find the file in the current path (where the jar is running from)
File propertyFile = new File(Paths.get("").toAbsolutePath().toString() + File.separatorChar + "connection.properties");
So, I've added a git repo to my project (sjxlsx). I've then right-clicked the repo and imported into the package explorer. I then went to Project->Build path in order to make sure it's on "Required projects on the build path".
When I debug on Eclipse, works just fine.
I'm now trying to export as a running jar and when I execute it outside of Eclipse, it somehow is giving an error (empty.xlsx not found). That is, because in the XLSXWriterSupport, the open method is fetching this empty.xlsx file. On debug, it's working as expected but on converting to a running jar, it's giving me this error.
This is due to this 'empty.xlsx' file being on the resources of the other project. How can I solve this?
https://github.com/davidpelfree/sjxlsx/blob/master/src/main/java/com/incesoft/tools/excel/support/XLSXWriterSupport.java
This is because a resource on the class path is not a File on the file system.
Here it is packed in a jar (zip format).
The wrong code:
if (getClass().getResource("/empty.xlsx") == null) {
throw new IllegalStateException("no empty.xlsx found in classpath");
}
workbook = new SimpleXLSXWorkbook(new File(getClass().getResource("/empty.xlsx").getFile()));
As SimpleXLSXWorkbook has only a File constructor (AFAIK), you need to create a temporary file.
Path tempPath = Files.createTempFile("sjxlsx-", ".xlsx");
Files.copy(getClass().getResourceAsStream("/empty.xlsx"), tempPath);
workbook = new SimpleXLSXWorkbook(tempPath.toFile());
Better have some provision to delete temp files, for instance creating them in a specific directory, see Files.
You probably have the Eclipse Project build path configured to use absolute library references. When you try to run your runnable jar, the jvm cannot find the required dependencies.
Edit:
If you want to export your software as a RUNNABLE jar file, then the jar must contain a MANIFEST file which specifies the dependencies and main class. Example:
Manifest-Version: 1.0
Main-Class: com.example.Main
Class-Path: lib1.jar lib2.jar
(assuming your main class is com.example.Main)
In order to run your runnable jar file, place lib1 and lib2 on the same directory as your runnable jar and run:
java -jar myJar.jar
Otherwise you could just compile your main class and run it like this (assuming lib1 and lib2 are copied into a lib/ dir on your main class root path):
java -cp '.:/libs/*.jar' com.example.Main
You could also use a dependency manager tool such as maven and configure your build to create an "uberJar":https://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html
uberJars contain all your software dependencies in one heavy runnable jar file.
Hope this helps.
This question already has answers here:
Reading a resource file from within jar
(15 answers)
Closed 6 years ago.
My goal is to create an executable jar from Eclipse. I have an Eclipse project which runs fine with the structure below.
My Eclipse project
src/main/java
-com.main
->MyClass
src/main/resources
->MyProps.properties
MyClass is able to access MyProps.properties file successfully.
After I export the Eclipse project and create a runnable jar then my jar structure is like below.
MyJar.jar
-com.main
->MyClass
-resources
->MyProps.properties
When I run the jar file it fails to access the properties file throwing a NullPointerExeception.
My code
InputStream input = MyClass.class.getClassLoader()
.getResourceAsStream("resources/MyProps.properties");
When I export my project as an executable jar file, I cannot access MyProps.properties anymore.
Can someone help me please?
You can use code like below to read a properties file on the Class Path:
MyClass.class.getClassLoader().getResourceAsStream("MyProps.properties")
In onder to load a file from a jar. You have to use Class.getResource() or Class.getResourceAsStream().
URL properties = ConfigLoaderTest.class.getResource("/resources/MyProps.properties");
This will load the file from your classpath, this means it will also look inside the jars on your classpath (the executable jar is on your classpath automatically). The first '/' indicates to look from the root of the jars on your classpath, you have omitted this in your code.
The URL you can then read like any URL (it will return null if none is found). For instant by using properties.openStream().
Note that it seems you are using the default maven structure src/main/resources, however you have src/main on your eclipse buildpath, so in your jar you get the resources directory. Normal for maven projects is to have src/main/resources on your buildpath. Which would place your properties file in the root of your jar.
Using Eclipse I created some parser classes I want to provide to another project as a jar archive for validation purposes. So the parser project look like this:
ParserProject
- src
-- com.package.x
--- ClassA
--- ClassB
- lib
-- external1.jar
-- external2.jar
The ClassA and ClassB use the external jar archives, like Jackson or some Apache commons. To provide the functionality to another project, I exported the entire project as jar archive and executable jar archive (Right click on project > Export... > Java > JAR file > Select all files and "Export generated class files and resources" > Finish).
The jar file is created without any errors. When I use the parserproject.jar in my validation project, I can access all my methods using auto completion, but when I run the validation project, I get a java.lang.ClassNotFoundException: com.fasterxml.jackson.core.JsonParseException.
Now three strange things:
All jackson jars are included in the parser project. Besides, I can run a main() method in the parser project and everything works fine, no ClassNotFoundException occurs.
When I add the parserproject.jar to my validation project in the class path and open the jar archive in the Package Explorer, the parserproject.jar seems to contain all jars it needs.
For the executable jar archive, all required external jars are contained in the MANIFEST.MF (Package Explorer > validation project > Referenced Libraries > + besides parserproject.jar > META-INF > MANIFEST.MF). It looks like this:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ json-20140107.jar jackson-annotations-2.5.4.jar ja
ckson-core-2.5.4.jar jackson-databind-2.5.4.jar commons-io-2.4.jar co
mmons-validator-1.3.1.jar slf4j-api-1.7.5.jar slf4j-log4j12-1.7.5.jar
json-schema-validator-2.2.6.jar jackson-module-jsonSchema-2.4.4.jar
juniversalchardet-1.0.3.jar snakeyaml-1.15.jar commons-beanutils-1.7.
0.jar commons-digester-1.6.jar commons-logging-1.0.4.jar joda-time-2.
8.1.jar jopt-simple-4.6.jar jsr305-3.0.0.jar json-schema-core-1.2.5.j
ar libphonenumber-6.2.jar jackson-coreutils-1.8.jar commons-lang-2.6.
jar guava-16.0.1.jar msg-simple-1.1.jar btf-1.2.jar mailapi-1.4.3.jar
uri-template-0.9.jar
Class-Path: .
Rsrc-Main-Class: com.package.SchemeValidator
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
I get the exception if and only if I use the generated jar file in my validation project. In case I get rid of the parserproject.jar and define a dependency to the ecplise parser project instead (Right click on validation project > Properties > Java Build Path > Projects) I do not get the ClassNotFoundException.
So now my question is, how I should export the jar so that every class is found. Thank you!
Eclipse only takes care of the compile-time dependencies while generating a .jar
Since your generated .jar can be moved to virtually anywhere, the dependencies must again be present during execution time.
You have two options:
Execute your jar with the -jar option, while leaving all
dependencies in the same folder. Since your manifest uses "./" as classpath, this means all dependencies must be on the same directory you are executing your jar from. NOTE classpath is relative to the directory you are executing from, not the directory the file is on.
Execute your jar withour the -jar option, and specify the -cp option to point to the dependencies, and the specify the main class.
java -cp "<path to your jar>;<path to dependency 1>;<path to dependency 3>[;...]" <your main class>
You might consider creating a so called fat jar which will contain all the needed classes. For example: http://fjep.sourceforge.net/
If you do not want to go through the hassle of managing all the depencencies by yourself, consider using a build tool like
Maven https://maven.apache.org/ or Gradle https://gradle.org/.
I have added this jar file to my project's build path under "libraries":
http://sunet.dl.sourceforge.net/project/jeplite/jeplite/jeplite-0.8.7/jeplite-0.8.7a-src.jar
and cannot get Eclipse to resolve ANY of the included classes.
Packages are visible, but no classes.
Error message is:
"JEP cannot be resolved to a type"
In eclipse, it should be on the build path if its a source tree .... Remember , a jar is just a glorified zip file, so be sure that the binaries are actually in your jar file. The steps to test are
1) unzip the jar file
2) if its source : then either try adding it to your build path, or just directly import the source folders into your project
3) if you see class files in the jar, then it should be okay to add them to "libraries"
This is only a jar containing the source code. You need a jar with the compiled classes in it. Try the jeplite-0.8.7a-bin.jar.