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!
Related
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"));
I manually inject a properties file inside a jar.
How to load properties from a jar file before java 1.7 ?
I tried many workarounds and nothing worked so far.
There's plenty questions about it, but everything is focused on ClassLoader methods from java 1.7.
When you have a properties file inside your classpath or inside your jar file it becomes a resource. Any other case is a simple file.
What you need to do, before you package your jar file, is add to your classpath the folder where the properties files are (i.e myproject/src/main/resources/) then wherever you do a
Properties properties = new Properties();
properties.load(MyClass.class.getResourceAsStream("/yourPropsFileName"));
it will load it!
Although, if you are using an external property file you can also load it by using:
Properties properties = new Properties();
properties.load(new FileInputStream("extenalPropsFileLocation"));
Hope it helps!
From some class, call:
getClass().getResourceAsStream("/path/to/props.props")
Make sure that the path matches up with a classpath location.
How to load property files placed in resource folder of an executable jar file. Here my app itself is a jar and it executes on it own. It need to find this property file (placed within itself under resource folder) at runtime depending on the path mentioned in the code. I have used below two methods but it didn't help me. Point here is, both these options are working fine when i execute in eclipse, but doesn't work when I pack it into an executable jar. It throws NullPointerException. Only problem I see here is that jar is not able to pick the property files with given path. Any help would be appreciated.
Method 1: Using Apache Commons Configuration
URL propFileURL = XYZ.class.getClassLoader().getResource("/config.properties");
Configuration propertyConfiguration = null;
propertyConfiguration = new PropertiesConfiguration(propFileURL);
In above case I'm getting ConfigurationException. Class is not able to find file mentioned in given path.
Method 2: Using getResourceAsStream. I know that getResource doesn't work if we are to load files from network on in any other location.
InputStream is =XYZ.class.getClassLoader().getResourceAsStream("/config.properties");
Properties prop = new Properties();
prop.load(is);
In this case, I'm getting nullPointerException.
Let me know if you need more details.
jar content Heirarchy
Properties file - /java-file-io-application/src/main/resources/config.properties
XYZ class - /java-file-io-application/src/main/java/org/bc/xyz/iplugin/utilities/XYZ.java
Looks like you might be building your jar incorrectly. Files from 'src/main/resources' would be expected at the root of the jar file. If your jar file contains the 'src/main/resources' directory, something's off with your build.
I am using CLIPSJNI.
What I have is:
Environment clips = new Environment();
clips.load("main.clp");
where main.clp is put in the same level as src and bin folder.
This runs fine in Eclipse. However when I export to JAR. It cannot work.
I understand that there are some problems with the path when we export to JAR.
So I've seen people suggesting using this.getClass().getResourceStream() but this is not the case. Because what I need is the name of the file, not its content.
Any suggestions on how to fix this?
The issue is that the load is being done within the native library on the C side which is being passed a file name as an argument. The C code has no concept of a JAR file or how to extract files embedded within one. I think what you would need to do is always place your .clp files within the JAR file and then have a routine which extracts the data from the JAR file and saves it to a file. You can then load it using the load method and delete the file once done.
I'm trying to have my application load a resource (binary file) transparently:
If the file exists under the current directory, open it.
If not, try looking in the current JAR file if applicable.
If not, try looking in other JAR files. (This is optional and I don't mind explicitly specifying which JAR files.)
So far I know of File which opens a local file and ClassLoader which has getResource* for JAR contents.
Is there a class which combines the two? If not, how should I go about writing it myself? Should I write a ClassLoader which also checks the local filesystem? Using File? (I'm very unfamiliar with Java and don't even know what's a good type to return. InputStream?)
Thanks
P.S. By "file" I mean "path", e.g. "data/texture1.png".
Doing #1 and #3 is pretty easy. Doing #2 (just looking in the current JAR only) is much harder as it requires you figuring out what JAR you
If you wanted to check the filesystem first, otherwise load from classpath, it would be something like:
public java.io.InputStream loadByName(String name) {
java.io.File f = new java.io.File(name);
if (f.isFile()) {
return new FileInputStream(f);
} else {
return getClass().getResource(name);
}
}
If you want to prefer loading from the same JAR file first, you will need to figure out where it is. Check out Determine which JAR file a class is from for more info on figuring out the JAR file you want to load the resource from.
A URLClassLoader should be able to load both and try the file path first if the file path is on the class path ahead of the jar.
Regarding your comments:
I know that relative jar URLs don't
work. That's why the Spring guys came
up with the Resource abstraction.
Read about it here.
You might want to check the answers
to this Question: Loading a file
relative to the executing jar
file. The problem is similar to
yours.
Current jar file and current directory are not concepts in the JVM like they are when you're running a shell script. You would need to specify a directory to be used for loading the files that you're interested in, such as with a system property while executing the JVM:
java -Ddirectory.to.scan=/home/aib
Then retrieve this property:
String dir = System.getProperty("directory.to.scan");
Now when talking about JAR files, all JAR files specified explicitly on the classpath when you start the JVM are loaded by the ClassLoader. You can get the ClassLoader of a specific class by:
InputStream is = <Your class>.class.getClassLoader().getResourceAsStream("binary file");
Note that any jar file loaded by the current class loader is searched.