Currently I am trying to read my config file from root of project directory, in order to make this actual configuration I want to move this to external location and then read from there.
Adding a complete path in following code throws out error :
package CopyEJ;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new java.util.Properties();
try {
// configFile.load(this.getClass().getClassLoader().getResourceAsStream("CopyEJ/config.properties"));
Error Statement ** configFile.load(this.getClass().getClassLoader().getResourceAsStream("C://EJ_Service//config.properties"));
}catch(Exception eta){
eta.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
}
Here's the error:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:365)
at java.util.Properties.load(Properties.java:293)
at CopyEJ.Config.<init>(Config.java:13)
at CopyEJ.CopyEJ.main(CopyEJ.java:22)
Exception in thread "main" java.lang.NullPointerException
at java.io.File.<init>(File.java:194)
at CopyEJ.CopyEJ.main(CopyEJ.java:48)
How can I fix this ?
The purpose of method getResourceAsStream is to open stream on some file, which exists inside your jar. If you know exact location of particular file, just open new FileInputStream.
I.e. your code should look like:
try (FileInputStream fis = new FileInputStream("C://EJ_Service//config.properties")) {
configFile.load(fis);
} catch(Exception eta){
eta.printStackTrace();
}
This line requires your config.properties to be in the java CLASSPATH
this.getClass().getClassLoader().getResourceAsStream("C://EJ_Service//config.properties")
When it is not, config.properties won't be accessible.
You can try some other alternative and use the configFile.load() function to read from.
One example would be:
InputStream inputStream = new FileInputStream(new File("C:/EJ_Service/config.properties"));
configFile.load(inputStream);
Related
I have the following prefix:
String prefix = TemplatesReader.class.getClassLoader().getResource("templates/").getPath();
and have method
public byte[] read(String pathToTemplate) {
return Files.readAllBytes(Paths.get(prefix + pathToTemplate));
}
in intellij idea works correctly, but when starting jar an error occurs:
java.nio.file.NoSuchFileException: file:/app.jar!/BOOT-INF/classes!/templates/request-orders/unmarked/RequestOrderUnmarked.pdf
You must not assume that a resource is a file. When the resource is inside a .jar file, it is a part of that .jar file; it is no longer a separate file at all.
You cannot use Files or Paths to read the resource.
You cannot use the getPath() method of URL. It does not return a file name. It only returns the path portion of the URL (that is, everything between the URL’s scheme/authority and its query portion), which is not a file path at all.
Instead, read the resource using getResourceAsStream:
private static final String RESOURCE_PREFIX = "/templates/";
public byte[] read(String pathToTemplate)
throws IOException {
try (InputStream stream = TemplatesReader.class.getResource(
RESOURCE_PREFIX + pathToTemplate)) {
return stream.readAllBytes();
}
}
When my application starts it reads a configuration properties file using the following code:
Properties properties = new Properties();
// parse the config resource
try (InputStream input = getClass().getClassLoader().getResourceAsStream(filename))
{
if (input == null)
{
// throw exception
}
// read the property list (key-value pairs) from the input byte stream
properties.load(input);
}
I am able to read and set individual properties.
The properties file is located in src/main/resources and after I build the application using maven, a copy of it is placed in target/classes. The jar file that is created also has a copy of it in the root directory when I open it up.
I would also like to be able to overwrite the properties file so that next time the application starts up, then it will read the new updated file. How do I achieve this? Is it even possible?
I found this question but no answers.
I've tried this:
try (OutputStream output = new FileOutputStream(filename))
{
properties.store(output, null);
}
which works if I just want to create a new file altogether. I would then have to modify the application so that it reads from a given folder rather than what originated from the resources folder. Is this what I should be doing?
I'm fairly new to Java so please go easy.
Storing the initial, default properties in the jar file, as resources is fine.
But if you want them to be writable, then you need to really store them as a file somewhere on the disk. Typically, under a .yourapp directory (or in a .yourapp file) inside the user's home directory.
So, try finding the file, and if not present, fallback to the resources. When writing, always write to the file.
This is an example code you can use for this. You create a config folder in the project root directory, an inside it you place your app.properties file
package com.yourparckage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Config {
/* Create basic object */
private ClassLoader objClassLoader = null;
private Properties commonProperties = new Properties();
public static final String CONFIG_FILE = "config/app.properties";
/**
* This method loads config data from properties file
*
*/
public Config() {
objClassLoader = getClass().getClassLoader();
}
public String readKey(String propertiesFilename, String key)
{
/* Simple validation */
if (propertiesFilename != null && !propertiesFilename.trim().isEmpty() && key != null
&& !key.trim().isEmpty()) {
/* Create an object of FileInputStream */
InputStream objFileInputStream = null;
/**
* Following try-catch is used to support upto 1.6. Use try-with-resource in JDK
* 1.7 or above
*/
try {
/* Read file from resources folder */
objFileInputStream = new FileInputStream(propertiesFilename);
/* Load file into commonProperties */
commonProperties.load(objFileInputStream);
/* Get the value of key */
return String.valueOf(commonProperties.get(key));
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
/* Close the resource */
if (objFileInputStream != null) {
try {
objFileInputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
return null;
}
}
My maven structure looks as below:
Have placed property file inside package under src/test/resources
And I trying to read from java class( Browser Test) under src/test/java
I am using below code to ready file, but the getting NullPointerException.
public Static Properties CONFIG
CONFIG = new Properties();
InputStream inputStream = BrowserTest.class.getResourceAsStream(filename);
CONFIG.load(inputStream);
[31mMessage: [0m[31mjava.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Unknown Source)
at java.util.Properties.load0(Unknown Source)
at java.util.Properties.load(Unknown Source)
Put the resource files in the root of the src/test/resources tree (src/test/resources/application.properties). Then use a static initialization block. Like,
public static Properties CONFIG = new Properties();
static {
try {
CONFIG.load(BrowserTest.class.getResourceAsStream(
"application.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
You getting NullPointerException because both BrowserTest.java and application.properties are in different packages.
Either
Move application.properties from com.philips.rs.properties to com.philips.rs.utils and read it directly.
String filename = "application.properties";
InputStream inputStream = BrowserTest.class.getResourceAsStream(filename);
CONFIG.load(inputStream);
Or change the filename to "/com/philips/rs/properties/application.properties"
String filename = "/com/philips/rs/properties/application.properties";
InputStream inputStream = BrowserTest.class.getResourceAsStream(filename);
CONFIG.load(inputStream);
Better explaination can find from https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getResourceAsStream-java.lang.String-
I want to delete the file which is opened and done writing but not closed. Please refer to code below:
Class A (can't be changed):
import java.io.FileOutputStream;
public class A {
public void run(String file) throws Exception {
FileOutputStream s = new FileOutputStream(file);
}
}
Class B:
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class B {
public static void main(String[] args) throws Exception {
String path = "D:\\CONFLUX_HOME\\TestClient\\Maps\\test\\newTest.txt";
A a = new A();
a.run(path);
File f = new File(path);
Files.delete(Paths.get(f.getAbsolutePath()));
}
}
In Class A , just open the stream without closing the file.
In class B , calling A's run method and then try to delete the file.
Since the file is still opened. I'm unable to delete the file.
Error is :
The process cannot access the file because it is being used by another process.
Actual Scenario is :
We are loading the jars dynamically. Classes inside jar are creating the file. When there is an exception, a file gets created whose size will be 0 bytes. We need to delete this file. Since the file is not closed during the exception, we can't delete the file.
We could fix the issue if we could close the streams in the jar classes, but we can't modify the jars that create the files as they are client specific jars.
Please suggest how to delete the opened file, without modifying the code in class A.
Make sure you close the file, even if there was an Exception when writing to it.
E.g.
public void run(String file) throws Exception {
FileOutputStream s = null;
try {
s = new FileOutputStream(file);
} finally {
try {
s.close();
} catch(Exception e) {
// log this exception
}
}
}
You have to close the file before any delete operation as firstly its a bad practice and second is it will lead to memory leaks.
If you are using Tomcat, it is possible to set AntiLockingOption and antiJARLocking in $CATALINA_HOME/conf/context.xml for Windows:
<Context antiJARLocking="true" antiResourceLocking="true" >
Important note:
The antiResourceLocking option can stop JSPs from redeploying when they are edited requiring a redeploy.
Read more about this option:
http://tomcat.apache.org/tomcat-7.0-doc/config/context.html
antiResourceLocking:
If true, Tomcat will prevent any file locking. This will significantly impact startup time of applications, but allows full webapp hot deploy and undeploy on platforms or configurations where file locking can occur. If not specified, the default value is false.
Pass the resource as a parameter and it becomes the caller's responsibility to clear up the resources
public void run(FileOutputStream stream) throws Exception {
...
}
caller:
try(FileStream stream = new FileStream(path)){
A a = new A();
a.run(stream);
}catch(Exception e){
.. exception handling
}
Updated according to OPs comment.
Another approach could be to subclass A and override run().
public static void main(String[] args) throws Exception {
String path = "D:\\CONFLUX_HOME\\TestClient\\Maps\\test\\newTest.txt";
A a = new A() {
#Override
public void run(String file) throws Exception {
FileOutputStream s = new FileOutputStream(file);
s.close();
}
};
a.run(path);
File f = new File(path);
Files.delete(Paths.get(f.getAbsolutePath()));
System.out.println("foo");
}
I don't think you'll find a pure java solution to this problem. One option is to install Unlocker (being careful to hit "Skip" on all the junkware) and invoke it from your code.
If you have UAC enabled, you'll also need to be running your java in an elevated process (e.g. start command prompt as Administrator). Then, assuming unlocker is in C:\Program Files\Unlocker:
Process p = new ProcessBuilder("c:\\Program Files\\Unlocker\\Unlocker.exe",path,"-s").start();
p.waitFor();
And after that you can delete the file as before. Or you could use "-d" instead of "-s" and Unlocker will delete the file for you.
I´ve included a jar (I built it: MyJar.jar) that i use to authenticate, in that jar I have to read some properties that I have in a package (e.g com.myproject.properties) inside a property file of my project.
I have a method in MyJar.jar which receive the name of the property and the path for the property file something like this:
public String getValueOfProperty(String property,String pathToPropertyFile){
BasicTextEncryptor encryptor = new BasicTextEncryptor();
Properties props = new EncryptableProperties(encryptor);
props.load(new FileInputStream(pathToPropertyFile));
....
}
I got the following error: System can't find the specified path
The path is: com/myproject/properties/conf.properties
What am I doing wrong?
Solved,
This is what i Used:
The path the method receives is something like this: /sv/com/myproject/configuration/file.properties,
This method will search with relative path
public String decryptVar(String var,String PathPropertyFile) throws Exception{
try {
BasicTextEncryptor encryptor = new BasicTextEncryptor();
Properties props = new EncryptableProperties(encryptor);
InputStream fis = this.getClass().getResourceAsStream(PathPropertyFile);
props.load(fis);
encryptor.setPassword(props.getProperty("PROPERTY_IN_FILE"));
return props.getProperty(var);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
Implementing: JASYPTH