How to copy an external file into the current running jar? - java

I want to edit a configuration file located in the current running jar.
Is there a way that allows modify directly this file or copy it from external?

You cannot modify the jar being run at runtime like Andreas suggested in the comments. I'll just put in a possible alternative to why you might need this in here, so this question doesn't show up in unanswered page.
Why?
When a jar is running (that is, it is being used by JVM), the file (archive >>file) is locked by the Operating System. When any file is locked (or marked as locked) it cannot be changed, in other words it is as good as a read-only file.
Why you might be in need of doing this.
Reason why usually people try to write into jar is that, they want a file which they want to use with absolute/relative path (with reference to jar file).
What option do we have in this case?
So, if this is your issue, you can make a directory in the jar's location and use it.
If your jar is at C:\Users\<Something>\Desktop\testDir\, then you create a directory 'conf' (C:\Users\<Something>\Desktop\testDir\conf\) in this place. You can write/create files in this directory and reference them from your code easily (with reference to the current working directory's path).

Related

Is it safe to manually recreate a jar file to change just a properties file inside

I've got this .jar file with a Java Application inside (For Oracle SOA Policies). I just needed to change a properties file inside to change an endpoint URL.
Is it safe to turn the .jar file into a .zip file, change the .properties (not a Java class, the .properties does not need to be decompiled), then zip it again and trough the extension name, turn it back to a .jar file?
Thanks
I would say - Yes, you can do such trick, if you, for instance, are on production system and do not have access to any IDE for rebuilding jar. This is essentially ok to do so, because jar is really ZIP.
Yes you can do that.JAR files are built on the ZIP file format and have the .jar file extension.Just do not modify or change unless it is really required.You will need to extract the jar via a WinZip/Winrar or any other software.Then modify the things you need to.Then put it back to the archive.It is safe to the extent that you do not modify the vital classes/properties
Yes, in your case it is safe. It would however not work on a signed jar.

Extract a directory from a jar

I have a jar file that's running, but it needs an exe and a couple dlls with it to work.
To make it convenient for the user, I want to package the folder with the exe and the 2 dlls in the jar, and have it extract it when the jar is ran.
I've read answers like this one, and this one, but I still don't understand how to apply that code to what I need. I understand that a jar file is essentially a zip, but I don't know how I can get the path to the zip, and extract the folder I need from it.
I tried using the code posted here to just extract the exe for a start, but it looks like it's trying to extract the exe from the class (if that makes any sense?)
Does anyone have a code snipped they could share to show how to extract a folder with a certain name from the currently executing jar?
If you guys could help me out I would really appreciate it!
If you want to access the resources from a JAR that is on the classpath at runtime, you simply access the resources from the classpath. So no need to read it via the JAR API. Therefore your first link points to a valid solution.
It may be tricky to use the appropriate classloader. If your resource is in the same folder as a Java class file, this link may help you: How to access resources in JAR file?
URL url = getClass().getResource("path/to/img.png");
or
URL url = MyClass.class.getResource("path/to/img.png");
I think you could access the two files separately and store them to a file. There are also methods to open a stream to copy. Here is a similar question: getResourceAsStream returns null

Packaging an Eclipse Program With External Files

I'm not sure if this was answered previously, I tried searching for the kind of question I am asking, but I couldn't find something satisfactory. If someone could point me to a similar question, that would help.
What I am trying to do is to package an eclipse program that has external files, such as images, into a single file, rather than a jar file and the supporting files placed in the same directory.
I am not sure if that is even possible, but is there some way in eclipse that would allow you to somehow package the external files along with the jar file in a single, neat file that can be executed easily?
EDIT:
Thanks to ortis and Thorbjørn Ravn Andersen, I figured out how to do it. Here are the steps for working it out:
Firstly, ensure that all of your external files are in your src folder, not in your bin or workspace or whatever else. If you have packages in your project, they will appear as folders and the external files must be placed into those folders for use within that package.
As for calls to the external files, don't do something like this:
Image img = new Image("fileName");
Rather do this:
Image img = new Image(getClass().getResourceAsStream("fileName"));
while ensuring that "fileName" is in the src folder or package folder, if you have packages.
Some points:
-If you are initializing a global variable using a file name that is outside of your main constructor or function call, getClass(), won't work. Use:
yourClassName.class.getResourceAsStream("fileName");
-if your using JavaFX Scenebuilder and you need to package your external CSS file, here is a solution that will help you load the style sheet in your program instead of using the .fxml file to do it.
-An InputStream variable can be assigned the result of
getClass().getResourceAsStream("fileName"));
and be used instead of the whole mess.
Yes. You must reference all external files as inputstreams instead (because you want the classloader to get them from inside a jar file), and then wrap the resulting single jar file as an EXE file using http://launch4j.sourceforge.net/

Java cannot save to a resource folder with jar

I am writing a program which is dependent on saving to a resource folder that is exported with the jar. I have a source folder titled "resources/inputs" and it exports correctly. I can load from it which is great, but the problem is, when I use:
getClass().getResource(path);
I cannot save to the path returned. I need to be able to save to it and I was wondering, is there any way I can save to this resource folder (or to some other folder existent in the same directory as the jar) no matter where the user has saved the jar file?
The error I get is a FileNotFoundException and the background I've read on it is that since jar triggers java "read-lock" you can only ever read from a jar and can never write to it? Not sure if that is accurate or not, but if it is, how can I work around this using an external folder?
I've never tried this, but its probably having a hard time because the you need to use specialized classes to access files within a jar file (which is a zip file with a different extension). Google "JarEntry" and see if that points you in the right direction.
Does this answer your question

How do you get file path for file when user directory changes?

I have a java app, and the log4j.properties file is in src/com/my/path/props. On compile, it's copied into classes/com/my/path/props
The file is loaded via PropertyConfigurator.configureAndWatch(user.dir + "/classes/com/my/path/props/log4j.properties").
This all works fine normally, though it's not ideal because of using user.dir (but I do not know another way to reference a file relative to the "application's start directory"). The problem manifests when trying to run this application using an NT Service wrapper. When done this way, the user.dir changes from the application's root dir to wherever the NTService wrapper's exe file is.
My question is: What's the appropriate way to get a the String file path representation of the log4j.properties file in my classes/com/my/path/props/ directory? I realize this would completely break down if the props file were in a jar; but in this case, it's not and is simply a file on the file system.
I've tried new File(this.getClass().getClassLoader().getResource("com/my/path/props/log4j.properties").getURI()).getAbsolutePath(), but that fails because on production, the path to the file is actually a UNC path and consequently throws a "URI has an authority component" exception.
How do other people deal with this problem?
Thanks.
OK. So... you asked how other people deal with this problem. First, they do not leave it up to Eclipse for where files get placed. They choose where they want them, how they want to access them, and then have their build tool (which unless they are just playing around, should not be an IDE like Eclipse, but rather a dedicated build tool like Maven or Ant) where to place it.
The choice of where you want the file depends on what you want to do with it. If its simply a config file that will never be edited at runtime, you typically place it inside your JAR (which is another practice - applications are placed in one or more JARs, WARs, or EARs, not a classes directory). If the file is to be edited at runtime, which from your "watching" it appears to be the case, you typically put it in a config directory outside your JAR.
How you access it (from the filepath or the classpath) is another choice. Where possible, I favor accessing files from the classpath because it is more portable - and when in a JAR, pretty much required. If that doesn't make sense in your case, then choose a path other than "user.dir" if that is changing when you deploy. You can hard-code it, use an environment variable, a property, a config file, a command line argument, etc. to set the actual path.
Always choose where things go and how you access them. Don't let your tools choose for you. It will make your life easier :-)
I took singleshot's advice and kept the properties files out of src and instead in a separate directory which I added to the classpath. In retrospect, this was indeed boneheaded to have configured it the way I did originally.
From there, my problem was getting a File from a URL. I ended up finding what I needed in Commons IO FileUtils, with its toFile(URL) method.
The code ended up looking like this:
private URL maintenanceConfigPath = this.getClass().getClassLoader().getResource("MaintenanceConfig.properties");
....
File f = FileUtils.toFile(maintenanceConfigPath);
....
Again, thanks to all for your feedback and for pointing me down a path that got me towards an answer

Categories

Resources