How to read properties file from external jar in maven project - java

I am new to maven and Java . I am working on a large codebase which uses the Spring web framework. I may be missing fundamentals but I have done my best to go over all the basics of the project implementation.
For the feature I am building,I have properties files that I had earlier saved in src/main/resources in
my maven project and was reading from my class named ReaderClass with this statement
ReaderClass.class.getResourceasStream("xyz.properties");
Now I have externalized these files into a separate project and have built a jar out of it. This jar only has the properties files under a folder named resource.
I have added this jar file as an dependency in the IntelliJ IDE and would like to read the properties files from this jar. Had it been a .class file I would use an import statement in ReaderClass but how would I read properties files?
ADDITIONAL INFORMATION
Also, I am not sure if this is a problem but IntelliJ doesn't actually show the jar in the External Libraries Tab but does show my jar in the dependencies tab of the Modules Section in Project Structure. I wanted to make sure this wouldn't affect the solution.

If you are using Spring, try
#Value("${property.name}")
private String property;
to read properties from resources folder.

There are numerous ways to do this.
Assuming your xyz.properties file looks like this:
a=b
y=z
mykey=myvalue
Using java.util.ResourceBundle
If you don't need to pass around the read data as a Properties object, this is the easiest way.
ResourceBundle rb = ResourceBundle.getBundle("xyz");
System.out.println("a=" + rb.getString("a"));
Using java.util.Properties
A bit more work and some boiler-plate, but accomplishes the same thing.
Properties p = new Properties();
try (InputStream is = getClass().getClassLoader().getResourceAsStream("xyz.properties")) {
p.load(is);
}
catch (IOException e) {
// Handle as appropriately.
}
System.out.println("mykey=" + p.getProperty("mykey"));

Related

How can I add file version detail on properties to a .jar?

I'm looking to add a product version number to appear in my .jar file information. Currently I'm using Maven in my Spring boot project for API Rest.
I have read a lot of solutions about the manifest versioning. There you have to decompress and access to the META-INF/MANIFEST.MF to check the Implementation-Version. That's too tedious for what I'm looking for.
Like for a .exe. where you can found it under right mouse click -> details -> "product version" or simply checking on File Version column as shown on image. Example of a file version description.
Also I read that JAR file is a file format based on the popular ZIP file format and is used for aggregating many files into one. Kinda that I'm looking to add a file version to .zip, but I want to ask anyway if that is possible.
Regards, Gaspar.
A JAR file itself can't have a version. But you're using Maven, and that means you can already access the Maven version:
try (InputStream inputStream = getClass().getResourceAsStream("/META-INF/maven/<groupId>/<artifactId>/pom.properties")) {
Properties properties = new Properties();
properties.load(inputStream);
// available properties:
// - artifactId=xxx
// - groupId=xxx
// - version=xxx
}
Note that this often doesn't work in unit tests (especially when run from IDEs) because the files are only added to the JAR file.
Just include a text file anywhere in your jar. Build systems of all stripes make this trivial. Then write in your code that you read out this text file with the version, and show it on screen.
In maven, gradle, etc, to include a plain text file in the jar, just put it in src/main/resources/version.txt and it gets included automatically.
To read it in java:
public class Main {
public static String getVersion() {
try (var in = Main.class.getResourceAsStream("/version.txt")) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}
}
This:
Asks the classloader to load version.txt using the same systems that load .class files.
reads that inputstream fully, and turns it into a string using the UTF_8 encoding.
Uses try-with-resources because, it's a resource, you have to do that if you don't want leaks.

Scala jar read external properties file

I have written some code and exported it as a jar file. In this jar there is a file named automation.properties with defaults that I'm loading using
val automationPropertiesFileURL = getClass.getResource("/automation.properties")
if (automationPropertiesFileURL != null) {
val source = Source.fromURL(automationPropertiesFileURL)
config = new Properties()
config.load(source.bufferedReader())
}
But when this jar file gets added as a gradle dependency in C:\User\abc\.gradle and I want to read automation.properties from my current project, how can I override the location and read the file from my project and not from the jar file itself?
The class loader will load the file from the location it finds first.
In your case, the file exists in two places:
Inside the current project itself
Inside a jar dependency
Which file will be found by the class loader,
depends on the ordering of the "current project" and the jar dependency on the classpath.
That's what you need to review,
that's the key to loading the right file.
Your current code is correct as it is,
this is a matter of classpath configuration.
I think
Source.fromInputStream(
getClass.getClassLoader.getResourceAsStream("/automation.properties")
)
should work.
API Docs
Source#fromInputStream
Class#getClassLoader
ClassLoader#getResourceAsStream
Java and so does SCALA, have different ways of reading properties file, in one of my answers I explain the difference between reading from properties file inside the Jar and properties file in a disk location.
See my answer HERE:
Loading Properties from a JAR file (java 1.6)
This will work for JAVA and for SCALA too! (Note, for SCALA you could change basic sintax but same concept)
Hope it helps!

FileInputStream in Spring MVC fails to find file

I am working on a SpringMVC project which runs a number of automated tests on a database. The access details for this database are located in a .properties file. This file is located within the project directory.
FileInputStream fis = new FileInputStream("batch-dm.properties");
propFile = new Properties();
propFile.load(fis);
As the file is stored in the project directory the FileInputStream should be able to access it no?
If I provide the absolute path e.g.
FileInputStream fis = new FileInputStream("C:/workspace/Project/batch-dm.properties");
It recognises the file and runs properly.
Do I need to sore this file in a different location because it is a Spring MVC project?
Thanks
Just to clear out your mind, try to see what is the value that outputs System.getProperty("user.dir") (let's call it A), this will print the complete absolute path from where your application was initialized, more specifically it will print the directory from where the JVM was started.
If you doesn't supply a parent path to the file that you are trying to open, the (A) path is taken by default and the file is looked inside that directory. So please, have in mind that.
Aditional information
If you absolutely need that file you should include it in your project so you can access it as a resource. Resource is a file that is included in your project and came bundled with the generated .jar or .war for re distribution.
My advice is to put the file in the package and use as a resource as it the safer way to work with external resources that should be shipped with your project.
Take a deeper look at this post for more about practical way of handling resources.
Please refer below link:
https://stackoverflow.com/a/2308388/1358551
You may have to use getResourceAsStream().

How to use a .properties file in Eclipse Java Dynamic Web Project?

I'm developing a Dynamic Web Project in Eclipse. I created a .properties file for store database details (Username, Password etc.). I added it by right clicking on the project and New -> File . I used the Java util package Properties class. But it does not working. I can not retrieve any property from the file. Here is the code I used,
Properties prop = new Properties();
try {
prop.load(new FileInputStream("database.properties"));
String db = prop.getProperty("database");
String userName = prop.getProperty("dbuser");
String password = prop.getProperty("dbpassword");
} catch (IOException ex) {
ex.printStackTrace();
}
Is there something wrong or Is there any particular place where I should put properties file.
What you did is correct, ie right clicking the project and new--file.You have to Put your properties where you start your jvm from. Please look into the attached image. The properties file is marked in red. Look if your properties file is also located something like this.
Also add this in your code to find out where to put your file:
System.out.println(new File(".").getAbsolutePath());
For more details please follow this link- FileNotFoundException when using java properties file
Normally, you make sure the properties file is in the project runtime classpath (e.g. WEB-INF/classes) and then load it using either the System classloader or the property file handler's classloader, i.e. (Freehand typing from memory -- NOT COMPILED)
try{
Properties p = new Properties();
InputStream in = MyPropertyHandler.getClass()
.getClassLoader()
.getResourceAsStream("com/package/props/database.properties");
p.load(in);
catch(IOException e){
e.printStackTrace(System.err);
}
I'm betting you aren't pointing at the correct location. Make sure you're properties file is in the correct place. Using that code, I believe it is looking for ${CURRENT_WORKING_DIR}/database.properties, which is the case of a web app in eclipse is WEB-INF/classes (i think).
You should instead be using the more portable java.util.Properties#load(InputStream) with the result of javax.servlet.ServletContext#getResourceAsStream(String).
Try to give absolute path or relative path to the proprty file, also check this propery file path has been add to source folders or not, if not it will not be copied to your classes folder. (Right cclick on project , check java build path under source tab.
You should have .properties file in same package as class that is using it.
Or better, read properties file with getResourceAsStream method (otherwise you can have some problem later when you'll have file in .war archive).
InputStream inputStream =
getClass().getClassLoader().getResourceAsStream("database.properties");

Config files - where to put them in Java?

I have a java desktop app and the issue of config files is vexing me.
What I want is for my distributable application folder to look like this:
MyApp/Application.jar
MyApp/SpringConfig.xml
MyApp/OtherConfig.xml
MyApp/lib
But at the moment SpringConfig.xml is inside Application.jar and I can't even find OtherConfig.xml programmatically.
I don't care how I set up the various files in my compilation path, so long as they end up looking like the above.
So..
where do i put the files in my dev setup?
and how do i access them programmatically?
thanks
the spring config file is related to the code and wiring of your application, hence it'd better be inside the jar, and should be subject to change by the users
(new File(".")).getAbsolutePath(); returns the absolute path of your jar - then you can load the OtherConfig.xml by a simple FileInputStream
if the SpringConfig.xml contains configuration data like database credentials, put them in an external application.properties and use a custom PropertyPlaceholderConfigurer to load the external file.
Answering the question "where do I put the files in my dev setup" is not possible because we don't know your environment.
Actually, if you want to be able to edit the config yourself (and not necessarily end-users), you can open the jar with any zip software (WinRAR for instance) and edit the config file from within the jar.
Update: as it seems you can't make the config files to be places out of the jar. Well, for a start, you can do it manually - whenever the .jar is complete, just remove the config file from inside and place it outside.
I typically create a structure where I have a src/ directory and then other directories exist at the same level. Some of those directories include:
lib/ - External Libraries
config/ - Configuration Files
resources/ - Various resources I use (images, etc)
At that same level, I then create an Ant script to perform my build so that the appropriate config files, resources, lib, etc are copied into my JAR file upon build. It has worked great for me up to this point and is a fairly easy to understand organizational structure.
Update: Accessing my config files is done, typically, by knowing their location and opening them up and reading them in the code. Because I use Ant to build, I make sure that my config files are in a location that I expect. So, for example, in a recent application I created, when I compile, my JAR file is in the top level directory (relative to the application release structure). Then, there is a "main" config file at that same level. And there is a "theme" config file that is in a themes folder.
To read the various files, I just open them up as I would any other file and read them in and go from there. It's nothing particularly fancy but it works well and it makes it easy to manually change configurations if I need to do so.
In dev mode, put them in source dir and they will be copied to your classes folder, you can then access them using classloader.
Example:
URL url = ClassLoader.getSystemResource("test.properties");
Properties p = new Properties();
p.load(new FileInputStream(new File(url.getFile())));
In Prod mode, you can make them part of your jar.

Categories