How to Load File Outside of, but Relative to, the JAR? - java

I need to load a file outside of the JAR, but relative to it (lib/config/config.ini to be exact). I used that exact path, and it works fine as long as the working directory is where the JAR is, i.e.
/path/to/jar$ java -jar JAR.jar
If it's run like this:
~$ java -jar /path/to/jar/JAR.jar
It can't find it. How can I correctly load a file relative to the location of the JAR?

Try using getClassLoader().getResource("classname") to find the URL of a class in your jar file. You'll find it's delimited with a ! between the path to the jar, and the path within a jar, which you can easily slice.

Related

Executable Java JAR can't find file path

I am facing problem while running executable .jar file via java -jar my.jar. I've created a project which contains a .sh file under src/main/resources/ path. In the code i am referring it to execute as:
Process pb = new ProcessBuilder("src/main/resources/stacktrace.sh",pid, traceFilePath,timeInMin).start();
It works just fine when I run my application from Intellij but when I export it to executable jar file and try to run it complains:
Exception in thread "main" java.io.IOException: Cannot run program "src/main/resources/stacktrace.sh": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
The path you used in your ProcessBuilder is relative to the current working directory. When you run your code from your source project the path exists, but when running the jar the current working directory is different as you are not running it from within your source project. Therefore when your code attempts to find "src/main/resources/stacktrace.sh" it fails to find it.
For example, maybe your source project is located in:
/myCodeProject
So when you run your project your path resolves to:
/myCodeProject/src/main/resources/stacktrace.sh
When you run your jar perhaps you're running from somewhere like:
/opt/app/myApp
Therefore your path resolves to:
/opt/app/myApp/src/main/resources/stacktrace.sh
and it is this path which does not exist.
EDIT:
As requested I am adding some ideas regarding how to correct the problem. However, your requirements are not clear as to where you want the file to live. Should it be outside the jar? Inside the jar? If it's outside will it be located in a specific constant path or relative to the jar?
There's the obvious fix: put the file in the expected path so that it will be found.
The other obvious fix: change the relative path so that it points to where the file is actually located.
Build your jar such that the file is included inside the jar and use one of these methods to access it. Note that you may not be able to directly run the file, but you could read its content and generate an external temporary file and run that.

MATLAB: importing java libraries

I have the following lines in my MATLAB code:
javaaddpath('C:\Users\localadmin\SkyDrive\IdeaProjects\DrawModels\out\artifacts\DrawModels_jar\DrawModels.jar')
javaaddpath('C:\Users\localadmin\SkyDrive\IdeaProjects\DrawModels\out\artifacts\DrawModels_jar\itextpdf-5.4.1.jar')
I then go on to instantiate some JAVA objects defined in the files.
I would like to copy the JAR files to where the .m file sits, and then write the following instead (i.e. I want to use a relative path rather than an absolute one).
javaaddpath('DrawModels.jar')
javaaddpath('itextpdf-5.4.1.jar')
However, the MATLAB path doesn't seem to apply to javaaddpath and so the JAR files do not get loaded.
Any ideas as to how I may achieve a relative path addressing of JAR files?
The background for this is I want the MATLAB code to run both on Windows and Linux, i.e. whereever it is unpacked. The user may unpack it in any folder he chooses, so I don't want a hard-coded path in the source.
Any help appreciated.
You can use mfilename to find the path of the running M file, which you can concatenate with the JAR file name like,
javaaddpath(fullfile(fileparts(mfilename('fullpath')),'DrawModels.jar'))
That must go in the M file with which you would like to add the Java class to MATLAB.

How to make jar files that draw from a source folder

I've been wanting to make executable jar files with java lately. When executing my code with Eclipse it works perfectly. But when I use Eclipse to export the same code as a runnable jar, Most of my jars work except the ones that draw from separate source folders.
The jar will be made but when launched it will try and open and then just say to check to console for possible errors. I try and run the jar through the console with the command "java -jar test.jar". and It says it cannot access the jar. Any Ideas? Btw Im on a macbook pro osX. Thank you!!
picture of where my files are within eclipse
If you have a file you want to store in a jar and access from there, you don't really have a Java File any more. Look at Class.getResourceAsStream() and Class.getResource() - the first can give you an InputStream to the (used-to-be) file, the second returns a URL and can be used for things like images. Note that the file being accessed can be accessed relative to the package/folder location of the class or relative to a classpath root (by putting "/" at the front of the resource name ("/resource/funny.jpg")).
When you execute the jar from a command line, be aware that you have a thing called the "default directory"; it is a folder in which your commands execute by default. If your jar is not in the default directory, you have to specify a valid folder path to your jar to execute it.

The dreaded java.lang.NoClassDefFoundError

I've looked through many of the existing threads about this error, but still no luck. I'm not even trying to package a jar or use any third-party packaging tools. I'm simply running from within Eclipse (works great) and then trying to run the exact same app from the command line, in the same location it's built to (getting this error). My goal is to be able to zip up the bin folder and send it off to be run by someone else via a command line script. Some details:
It's a command-line app and I'm using the commons-lang-2.4.jar for string utilities. That is the file that cannot be located (specificaly "java.lang.NoClassDefFoundError: org/apache/commons/lang/StringEscapeUtils")
I have that jar in my lib folder and have added it to my build path in Eclipse via right-click "Build Path -> Add to Build Path"
The .classpath file looks correct and contains the reference to the jar, but I assume that file is only used by Eclipse (contains this line: <classpathentry kind="lib" path="lib/commons-lang-2.4.jar"/>)
Could this be related to the Eclipse working directory setting? I have some internal template files that I created that are under src/templates, and the only way I can seem to get those to be seen is by setting the project working directory to AppName/src. Maybe I should be putting those somewhere else?
Let me know if any additional info would help. Surely this is something simple, but I've wasted too much time on it at this point. This is reminding me why I originally left Java back in '05 or so...
A NoClassDefFoundError basically means that the class was there in the classpath during compiletime, but it is missing in the classpath during runtime.
In your case, when executing using java.exe from commandline, you need to specify the classpath in the -cp or -classpath argument. Or if it is a JAR file, then you need to specify it in the class-path entry of its MANIFEST.MF file.
The value of the argument/entry can be either absolute or relative file system paths to a folder containing all .class files or to an individual .jar file. You can separate paths using a semicolon ;. When a path contains spaces, you need to wrap the particular path with doublequotes ". Example:
java -cp .;c:/path/to/file.jar;"c:/spacy path/to/classes" mypackage.MyClass
To save the effort of typing and editing the argument in commandline everytime, use a .bat file.
Edit: I should have realized that you're using an Unix based operating system. The above examples are Windows-targeted. In the case of Unix like platforms you can follow the same rules, but you need to separate the paths using a colon : and instead of an eventual batch file, use a .sh file.
java -cp .:/path/to/file.jar:"/spacy path/to/classes" mypackage.MyClass
Are you specifying the classpath to java on the command line?
$ java -cp lib/commons-lang-2.4.jar your.main.Class
The classpath setting you are setting in Eclispe are only for the IDE and do not affect how you application is run outside the IDE. Even if you use the Eclipse Functionality to export your application as an executable jar file there is no out of the box way to package all the jars your application depends on.
If you have packaged you application into a jar file called myapp.jar then running a command like below will run the application with the jar you depend on, if you have more than one just add them separted by ; on Windows or : on Unix:
java -jar myapp.jar -cp .;c:/pathtolibs/commons-lang-2.4.jar
If you are just running the classes directly then either run the folder containing your .class files will also need to be on the path (though I assume it already is since you are able to run the program and get errors).
Consider File -> Export -> Runnable jar to create a jar file which can be invoked directly with
java -jar yourProgram.jar
There are several variants depending on your needs.
Eclipse does not move any of the jars in your classpath into the bin folder of your project. You need to copy the util jar into the bin folder. If you move it to the root of the bin folder, you might be able to get away without any classpath entries but it's not the recommended solution. See #BalusC's answer for good coverage of that.
Eclipse doesn't build executable java classes by default. Don't ask me why, but it probably has something to do with using their own tools.jar (somewhere in plugins/org.eclipse.core ?) so that Eclipse can run without a JDK.
You can usually go to your project bin directory and do:
java -cp . MyClass
But if you have external jars, Eclipse handles those internally in another weird way, so you'll need to add those too.
make sure your jar commons-lang-2.4.jar in classpath and not redudance.
I ever add jar file to my classpath, and have 2 file jar in my classpath. After I delete it, work smooth

How do you extract a JAR in a UNIX filesystem with a single command and specify its target directory using the JAR command?

I am creating a Python script within which I am executing UNIX system commands. I have a
war archive named Binaries.war which is within an ear archive named Portal.ear
The Portal ear file resides in, say /home/foo/bar/
jar xf /home/foo/bar/Portal.ear Binaries.war
Will extract the Binaries.war file out of the /home/foo/bar/Portal.ear archive into the current directory I am running the script from.
How do you specify a target directory to be extracted to using just one command?
I would like to do something like this to extract Binaries.war into the directory /home/foo/bar/baz
jar xf /home/foo/bar/Portal.ear Binaries.war [into target directory /home/foo/bar/baz]
I searched the the JAR man page for options and can't seem to find a simple way to do this. Of course I can extract the archive into my current directory and then move it using mv but I'd like to do this in one shot and not shuffle directories and files around.
If your jar file already has an absolute pathname as shown, it is particularly easy:
cd /where/you/want/it; jar xf /path/to/jarfile.jar
That is, you have the shell executed by Python change directory for you and then run the extraction.
If your jar file does not already have an absolute pathname, then you have to convert the relative name to absolute (by prefixing it with the path of the current directory) so that jar can find it after the change of directory.
The only issues left to worry about are things like blanks in the path names.
I don't think the jar tool supports this natively, but you can just unzip a JAR file with "unzip" and specify the output directory with that with the "-d" option, so something like:
$ unzip -d /home/foo/bar/baz /home/foo/bar/Portal.ear Binaries.war
Can't you just change working directory within the python script using os.chdir(target)? I agree, I can't see any way of doing it from the jar command itself.
If you don't want to permanently change directory, then store the current directory (using os.getcwd())in a variable and change back afterwards.
If this is a personal script, rather than one you're planning on distributing, it might be simpler to write a shell function for this:
function warextract { jar xf $1 $2 && mv $2 $3 }
which you could then call from python like so:
warextract /home/foo/bar/Portal.ear Binaries.war /home/foo/bar/baz/
If you really feel like it, you could use sed to parse out the filename from the path, so that you'd be able to call it with
warextract /home/foo/bar/Portal.ear /home/foo/bar/baz/Binaries.war
I'll leave that as an excercise to the reader, though.
Of course, since this will extract the .war out into the current directory first, and then move it, it has the possibility of overwriting something with the same name where you are.
Changing directory, extracting it, and cd-ing back is a bit cleaner, but I find myself using little one-line shell functions like this all the time when I want to reduce code clutter.

Categories

Resources