Java reloading text file from resources within jar - java

I have a standart maven project:
src/
| --- main/*.java
| --- resources/
|--- settings1.ini
|--- settings2.ini
That's the way I am reading this settings files:
InputStream settingsFileInputStream = ClassLoader.getSystemResourceAsStream(this.configurationFileName);
All works fine but I have to provide functionality to reload these settings1.ini and settings2.ini files at runtime when I am running maven-compiled .jar file. How can I do this?
Because as far as I know I can't access any data in .jar archive and modify it.

You can access a file in one of your application's JAR files (assuming it is on the classpath) using a stream opened using ClassLoader.getResourceAsStream(resourcePath).
However, you cannot update a file in a JAR file. Or to be more accurate:
updating a JAR (using the Java SE libraries) entails rewriting it,
there are many situations where a application won't be able to write to its JAR file,
even if it can do it, the application may only see the results of the updates after it has been restarted, and
it is a bad idea for an application to update itself in this way for various reasons ... including security.
If you want the file to be updateable, I suggest the following approach:
Pick a standard location for the file on the user's machine; e.g. on Linux, you might pick a hidden subdirectory of the current user's home directory.
On starting the application, see if the file exists, and if it doesn't populate it from the copy in the JAR file.
When the application then needs to read or update the file, read or update it at the above location.

Related

Deployed spring boot jar file to Docker - how to access and change static resources

I'm kinda new to spring and web development as a whole.
My question is:
When you build a spring boot project (using Maven) into jar file and deploy it via Docker, everything is in one jar file. How can you access your resources (css, js, images, html...) if you want to edit something? Like change something in css file or add something to html page. Is it even possible? Or do you have to build a new jar file everytime, when you need to change something (in frontend)? Also, when there are being uploaded some images or other files, where are they stored? This stuff is very confusing for me and i can't find any related books or help at all.
Thanks for help!
when you package any java program it is nothing but a zip file. Based on what kind of package it is, you wither name it as a Jar or War.
Jar == Java archive
War == Web archive
Now, given the fact that jar and war both are essentially a zip archive, it gives you flexibility to extract and modify them just like any other zip file.
On windows, I think softwares like 7zip let you update the jar inline. I have done it multiple times, especially when I wanted to change application.properties alone on cloud machines, and no other code changes were required. In such cases, building the whole jar and transferring it again to cloud machine could be time consuming. So I would just extract the contents, update whatever I want to, and rezip the package.
Here is the commands you can use -
jar xf jar-file
This should extract the files into a directory.
This SO thread will guide you towards creating jar files.
Something like jar cf myJar.jar ** should be enough to generate a jar file IMO, but syntax might vary.
The jar file is actually just a zip file containing all the files and classes of your application, so technically you can change files in it like any other zip archive. Best practice is to build the jar file using Maven or Gradle from source every time you need something changed.
It's good practice to keep the source in version control using Git, and tag each build in the git repository - that way you can easily keep track of changes to the jar file by looking at what's in git at the time of the build.

what's the ideal way to store files in spring boot application?

I am working with one spring boot maven application, so here on registration form customer has to upload two documents.
License
PAN card.
so these documents i am storing on physical location and path i am keeping in DB.
So to store License i have created one folder customerLicense under proejct root folder parellet to POM and for PAN card also i created customerPANcard folder on same location parellel to POM.
and in yml file i have made entry for path, so in code i am reading folder location and storing documents.
application:
customerLicensePath: /customerLicense
customerPANPath: /customerPANcard
So to build the project i run command mvn clean install under the root folder where POM is there. then target folder generated and to run the war i run command java -jar ./target jarName.war that command also i run from root folder.
i don't go inside target because those folder where i am keeping documents that are under project root folder, if i run war file from target folder then will not be able to access those folders.
Here my question is :- Now if i give this war file to client , so first client has to create two folder manually to store documents otherwise he will get error in file upload.
Do we have option like that client don't have to do anything he will only run war file and automatically these folder should get created ?
A few things.
You don't want to put things 'parallel' to the pom.xml. Do this instead:
projectRoot/src/main/java/uniquePackageNameHere/ // all your code in here
/pom.xml
If you want the client to provide the files themselves, simply accept the path at runtime. Something like java -jar jarName.jar -license /path/to/license -pan /path/to/pan (use Apache Commons-cli or something)
If instead you want to provide the files, then include them in the resources folder of your project:
src/main/resources/customerLicense
src/main/resources/customerPANcard
then, in your code, refer to the files by calling:
Main.class.getClassLoader().getResourceAsStream("customerLicense")
Main.class.getClassLoader().getResourceAsStream("customerPANcard")
This will make it such that wherever the code is run from, your program will always go in resources to find them.

Use File Input and Output in .jar FIle

So I've created just a simple application which I'm using to apply for a highschool internship. It was built using Eclipse.
I initially exported into a runnable .jar file, but the location I initially saved files, ("src/fileDirectories") didn't work on export.I then set the location to "./fileDirectories") which works and the app can actually run, however the .jar file creates the folder directory in the same folder as the .jar file.
This isn't too bad, as I can create a folder with the .jar and the saved files in it, which is fine, but similar to images, I'm wondering if there is a way to save .txt files in a directory to the .jar file so everything works with just the .jar application.
Assuming the files you want to access are static, and are not changed by the application, you can do this using the classpath.
When you access a file using new File("path"), Java will look for it in the file system, relative to the working directory (i.e. where the application was launched from.
An alternative way to access files is to look them up from the classpath - this is the list of locations Java searches for resources. It includes, among other things, the top level of your JAR archive. You can access this as follows:
this.getClass().getResourceAsStream("/my_file.txt")
Build tools will generally have preconfigured directories (e.g. src/main/resources) which get copied from your source tree into the JAR so they can be accessed in this way.
This is great if you have some static resources or config which you want to access at runtime, but don't want to have to pass around with your application.
However, if what you want is a working folder for files which your application will make changes to or create new instances of, like user documents, you don't want this to be editing the JAR - you'll need to make a separate folder for these.

launch4j and external files on classpath

I am working on a java application that uses gradle with the launch4j plugin to create a windows exe wrapper. I am required to write a 'help' framework to display help documentation to the user from within the application, and I am unsure of a method to do this, given that the only items in the classpath are the various jar files in the lib folder.
I had planned on making HTML documents for the help files, and loading these documents in the GUI through the JavaFX WebView control. With this in mind, I have the following directory structure in my application distribution:
root
|
+ config
+ help
+ lib
- Application.exe
- LICENSE
Assuming I can continue to do this as I had planned, how might I get the help and config folders into the classpath for launch4j, using only gradle config scripts (not manually editing the launch4j.xml file). If this can't be done, is there another recommended way I can include external files on the classpath so I can safely reference them using ClassLoader.getSystemResource()?
You should put your help (and config) directories as resources into the JAR. To do so with Gradle, move these directories to the src/main/resources directory. From there you can access their contents via getClass().getResource() / getClass().getResourceAsStream().

Dependency issues in deploying using Java Webstart

I am working on a project in Java which has a directory structure something like this:
MainFolder
/ | \
Folder1 Folder2 Folder3...
|
Program.jar|Run.sh
In Folder1 I have main jar file along with the shell script to run the program.
In Folder2 I'm having configuration files in xml which may later be modified by the program
and In Folder3 I'm having jar files that the main program depends on.
Now I want to deploy this program using Java web-start.My current understanding is that web start allows us to deploy programs using 1 or more jar files.My problem is that I need the directory structure also.Can anyone suggest a solution for this.
As mentioned by others, the shell script raises problems. What does it do specifically to 'run the program'?
For the configuration files - 'Folder 2', webstart provides the PersistenceService. I have a small demo. (1)
As far as the Jars in 'Folder 3' go. Move them, as well as the Jar's in folders 2 & 1 to a single directory named 'lib'. The main Jar and the configuration files will be required eagerly, which is the default for JWS. If any of the other Jars (ex. '3') might not be needed immediately or at all, they should be deployed as download='lazy'.
To access the local file system - for reading input supplied by the user or writing a new file they created - a JWS app. normally needs to be digitally signed and trusted. But JWS also provides the much more limited form of access through the FileContents object. For more details, see the demo. of the File Service in the page linked below. (1)
1) Demos of the JNLP API, including the PersistenceService & FileContents object.
I think you will have to make some changes to the structure for webstart deployment (possibly package it as a jar or set of jars), also the launching will be done via JNLP, by webstart and not Run.sh.
Additionally you will have to sign your deployment if you need permissions to write to the disk.
See the FAQ for webstart here
Also check out the developer guide on how to deploy using webstart
Java WebStart does not provide any help in making the filsystem as you need it - it only provides the program components for memory.
If you need this structure, you will need to maintain it yourself (and then, where?)
If the only thing you need is a shell script to run, you can keep the contents of that file as a resource inside your jar, create a temporary file at each run, put the desired contents inside, and execute it, and then delete the temporary file when you are done. Note that this brings you into the wonderful world of code signing which is rather tedious.

Categories

Resources