read project directory to get properties file in java web application - java

Am trying to ready properties file which is presented in my project directory src/test/resources/properties/api/. But this way is not working and its give me file not found exception.
Please find my code below :
public Properties extractProperties() throws IOException {
InputStream configReader= null;
String env = getProperty("tuf.environment");
try {
configReader = new FileInputStream(new File("src/test/resources/properties/api/"+env+".properties")); // throwing exception
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
prop.load(configReader);
return prop;
}

I would do it the following way. Please note that the extractProperties() method will return an empty Properties object if the file was not found. Please also note the try-with-resources statement which will auto-close the InputStream.
public Properties extractProperties() throws IOException {
String env = getProperty("tuf.environment");
Properties prop = new Properties();
try (InputStream in = this.getClass().getResourceAsStream("/properties/api/" + env + ".properties")) {
prop.load(in);
} catch (Exception e) {
e.printStackTrace();
}
return prop;
}

Judging from your path you are using either Maven or Gradle as it looks like the default structure used by them. Which means src/test/resources points to the root of the classpath, so there is no src/test/resources. (The same applies to src/main/resources as well!).
So if you want to load it yuo would need to remove the src/test/resources part of the loading.
Next if this is run from a packaged application loading a File won't work as it isn't a File. The File needs to be a physical file on the filesystem and not inside an archive.
Taking all that into account you should be able to load the properties using the following
public Properties extractProperties() throws IOException {
String env = getProperty("tuf.environment");
String resource = "/properties/api/"+env+".properties";
try (InputStream in = getClass().getResourceAsStream(resource)) {
prop.load(in);
return prop;
}
}

Try something like below
public Properties extractProperties() throws IOException {
Properties prop=new Properties();
String env = getProperty("tuf.environment");
String mappingFileName = "/properties/api/" + env+ ".properties";
Resource resource = resourceLoader.getResource("classpath:" + mappingFileName);
try (InputStream inputStream = resource.getInputStream();
BufferedReader bufferedInputStream = new BufferedReader(new InputStreamReader(inputStream))) {
prop.load(bufferedInputStream);
} catch IOException ie) {
//handle exception
}
return prop;
}

Probably env is not what you think it is. Why not list all files in that directory?
You can print with https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/file/Files.html#list(java.nio.file.Path)
With the relevant directory:
Path apiDir = Paths.get("src/test/resources/properties/api/");

Related

Reading and Writing to file in resource folder Maven

I am writing code for reading and writing file which is present in src/main/resources folder of Maven project, but code is reading and writing to file present in "project/target/classes/config.properties", but what I need to read/write the file present in "project/src/main/resources/config.properties". Below is a piece of code, I written:
public class PropertyFileReader {
private static final Logger LOGGER = LoggerFactory
.getLogger(PropertyFileReader.class);
private static Properties prop;
static {
prop = new Properties();
}
public static void main(String[] args) {
String property = read("config.properties", "number");
System.out.println(property);
write("config.properties", "number", "6");
}
public static String read(final String fileName, final String propertyName) {
File file = getpropertyFile(fileName);
try (InputStream input = new FileInputStream(file)) {
prop.load(input);
} catch (IOException ex) {
LOGGER.error("Error occurred while reading property from file : ",
ex);
}
return prop.getProperty(propertyName);
}
public static void write(final String fileName, final String propertName,
String propertyValue) {
File file = getpropertyFile(fileName);
try (OutputStream output = new FileOutputStream(file)) {
prop.setProperty(propertName, propertyValue);
prop.store(output, null);
} catch (IOException io) {
LOGGER.error("Error occurred while writing property to file : ",
io);
}
}
private static File getpropertyFile(final String fileName) {
ClassLoader classLoader = PropertyFileReader.class.getClassLoader();
return new File(classLoader.getResource(fileName).getFile());
}
}
I also read various posts related to it, which suggest to make some changes in pom.xml with adding <RESOURCE_PATH>${project.basedir}/src/main/resources</RESOURCE_PATH>. But I am not understaning how should I do it.
Can you please guide me in implementing the same.
Thanks.
You can't edit files within a jar file. Instead you can create temporary files from files within a jar file.
static File stream2file(InputStream in) throws IOException {
File tempFile = File.createTempFile("stringOfYourChoice", ".tmp");
tempFile.deleteOnExit();
Files.copy(in, tempFile.toPath(), REPLACE_EXISTING)
return tempFile;
}

How to write to a file in WebContent directory from a class in WEB-INF/classes directory

I have a Java Class UpdateStats in WEB-INF/Classes directory of a dynamic web application.This class has a function writeLog() which writes some logs to a text file.I want this text file to be in webcontent directory.Thus everytime the function is called updates stats are written in that text file.
The problem is how to give the path of that text file in webcontent directory from within that function,which resides in WEB-INF/Classes directory.
You can get your webapp root directory from ServletContext:
String path = getServletContext().getRealPath("WEB-INF/../");
File file = new File(path);
String fullPathToYourWebappRoot = file.getCanonicalPath();
Hope this helps.
You can do something like below in your servlet,
When you do getServletContext().getRealPath() and put some string argument the file will see at your webcontent location.
If you want something into WEB-INF, you can give fileName like "WEB-INF/my_updates.txt".
File update_log = null;
final String fileName = "my_updates.txt";
#Override
public void init() throws ServletException {
super.init();
String file_path = getServletContext().getRealPath(fileName);
update_log = new File(file_path);
if (!update_log.exists()) {
try {
update_log.createNewFile();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error while creating file : " + fileName);
}
}
}
public synchronized void update_to_file(String userName,String query) {
if (update_log != null && update_log.exists()) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(update_log, true);
fos.write((getCurrentFormattedTime()+" "+userName+" "+query+"\n").getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
To write a file you need to know absolute path of your web content directory on server as file class require absolute path.
File f = new File("/usr/local/tomcat/webapps/abc/yourlogfile.txt");
FileOutputStream out = new FileOutputStream(f);
out.writeLog("Data");
Assumption : abc is your project name
WebContent is not any directory when you deploy application. All files under web content goes directly under project name.

JAVA .properties file

having a lil issue, i have create a properties file :
config.properties located in ../resource/config.properties
this is the file currently :
destinationPDF=D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/
destination="D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/
fileList =D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/Directory Files/directoryFiles.txt
have i done the properties file ok ?
also i want to access this file and load the variables into a class
i have tried
public void loadProp() {
try {
prop.load(new FileInputStream("../resources/config.properties"));
System.out.println(prop.getProperty("destinationPDF"));
System.out.println(prop.getProperty("destination"));
System.out.println(prop.getProperty("fileList"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
but now the class will not compile becuase it can not find variable destination for example, so how do i load the variables from the file, and do i still need to declear the variable in the class ?
sorry if these are silly questions, first time using properties !
i do not get this error if i put in the variables normally like
private String destinationPDF = "D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/"; //USE ON TORNADO//"D:/My Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/";//USE ON PREDATOR
EDIT:
have now
private Properties configProp = new Properties();
public void loadProps() {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("../resources/config.properties");
try {
configProp.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
EDIT 2:
public void loadProp() {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("../resources/config.properties");
try {
prop.load(in);
System.out.println(prop.getProperty("destinationPDF"));
System.out.println(prop.getProperty("destination"));
System.out.println(prop.getProperty("fileList"));
} catch (IOException e) {
e.printStackTrace();
}
}
Properties prop = new Properties();
private String destinationPDF = prop.getProperty("destinationPDF");
public String destination = prop.getProperty("destination");
it is working, no erors etc but destination and destinationPDF are passing null values
You seem to misunderstand what properties files are. They're just data. They don't contain Java code, and aren't used to declare variables. To get the value associated to the key destinationPDF in the properties file, you need to call
String destinationPDF = prop.getProperty("destinationPDF");
after having initialized the prop variable and loaded the file using prop.load(new FileInputStream(...)). And then you'll have a variable initialized with the value of the key.
Side note: please respect the Java naming conventions: variables start with a lower-case letter.
Problem is here:
// destination = "D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/"; // main location for uploads (CHANGE THIS WHEN USING PREDATOR)
File theFile = new File(destination + "/" + username);
theFile.mkdirs();// will create a sub folder for each user (currently does not work, below hopefully is a solution) (DOES NOW WORK)
System.out.println("Completed Creation of folder");
NewDestination = destination + username + "/";
You have commented the destination variable and you are using here:
NewDestination = destination + username + "/";
I wonder whats the issue...I tested your code and it works fine...are you getting compilation error or runtime error?
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Test1 {
/**
* #param args
*/
public static void main(String[] args) {
new Test1().loadProp();
}
Properties prop = new Properties();
public void loadProp() {
try {
prop.load(new FileInputStream("c:/Test/Computer.txt"));
System.out.println(prop.getProperty("destinationPDF"));
System.out.println(prop.getProperty("destination"));
System.out.println(prop.getProperty("fileList"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Output:
D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/
D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/
D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/Directory Files/directoryFiles.txt

How a JAR file can read an external properties file

We have a connection pooling component (JAR file) for one of our application. As of now the application connection details are bundled with-in the JAR file (in .properties file).
Can we make it more generic? Can we have the client tell the properties file details (both the path and the file name) and use the JAR to get the connection?
Does it make sense to have something like this in the client code:
XyzConnection con = connectionIF.getConnection(uname, pwd);
Along with this, the client will specify (somehow???) the properties file details that has the URLs to connect, timeout etc.
Simplest way, use the -D switch to define a system property on a java command line.
That system property may contain a path to your properties file.
E.g
java -cp ... -Dmy.app.properties=/path/to/my.app.properties my.package.App
Then, in your code you can do ( exception handling is not shown for brevity ):
String propPath = System.getProperty( "my.app.properties" );
final Properties myProps;
if ( propPath != null )
{
final FileInputStream in = new FileInputStream( propPath );
try
{
myProps = Properties.load( in );
}
finally
{
in.close( );
}
}
else
{
// Do defaults initialization here or throw an exception telling
// that environment is not set
...
}
http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html
multiple approaches are available, the article above provides more details
ClassLoader.getResourceAsStream ("some/pkg/resource.properties");
Class.getResourceAsStream ("/some/pkg/resource.properties");
ResourceBundle.getBundle ("some.pkg.resource");
Just load the properties from file, something like
Properties properties = new Properties();
InputStreamReader in = null;
try {
in = new InputStreamReader(new FileInputStream("propertiesfilepathandname"), "UTF-8");
properties.load(in);
} finally {
if (null != in) {
try {
in.close();
} catch (IOException ex) {}
}
}
Note how the encoding is explicitly specified as UTF-8 above. It could also be left out if you accept the default ISO8859-1 encoding, but beware with any special characters then.
This is my solution. First looking for app.properties in startup folder, if does not exists try to load from your JAR package:
File external = new File("app.properties");
if (external.exists())
properties.load(new FileInputStream(external));
else
properties.load(Main.class.getClassLoader().getResourceAsStream("app.properties"));
Simplest way is below. It will load application.properties from cfg folder outside of the jar file.
Directory Structure
|-cfg<Folder>-->application.properties
|-somerunnable.jar
Code:
Properties mainProperties = new Properties();
mainProperties.load(new FileInputStream("./cfg/application.properties"));
System.out.println(mainProperties.getProperty("error.message"));
In netbeans I needed to load application.properties from conf/ folder outside of the jar file.
Therefore I wrote :
public static String getProperty(String FileName, String Prop)
{
try {
FIS = new FileInputStream( "./../conf/"+FileName);
Properties properties;
(properties = new Properties()).load(FIS);
for(Enumeration propKeys = properties.propertyNames();
propKeys.hasMoreElements();){
String tmpKey = (String) propKeys.nextElement();
String tmpValue = properties.getProperty(tmpKey);
tmpValue = tmpValue.trim();
if (tmpKey.equals(Prop)){
//System.out.println(tmpKey +"="+tmpValue);
properties.put(tmpKey, tmpValue);
Value = properties.getProperty(Prop);
break;
}
}
if (Value==null){
throw new Exception("La Propiedad : "+Prop+" no Se encuentra en el Archivo de Configuracion");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return Value;
}
For Eclipse apply the following:
FIS = new FileInputStream( "../conf/"+FileName);
public static String getPropertiesValue(String propValue) {
Properties props = new Properties();
fileType = PCLLoaderLQIOrder.class.getClassLoader().getResourceAsStream(propFileName);
if (fileType != null) {
try {
props.load(fileType);
} catch (IOException e) {
logger.error(e);
}
} else {
try {
throw new FileNotFoundException("Property file" + propFileName + " not found in the class path");
} catch (FileNotFoundException e) {
logger.error(e);
}
}
String propertiesValue = props.getProperty(propValue);
return propertiesValue;
}
above methods works for me, just store your property file into directory from where to run your jar and provide that name in place of propFileName, when you want any value from property just call getPropertyValue("name").

Load java properties inside static initializer block

I have a static util class that does some string manipulation on a bit sensitive data.
Prior to use of this class I need to initialize certain static variables with values, such as usernames/password, that I prefer to store in a .properties file.
I am not very familiar with how loading of .properties file work in Java, especially outside of *Spring DI *container.
Anyone can give me a hand/insight on how this can be done?
Thank you!
Addition: .properties file precise location is unknown, but it will be on the classpath. Sorta like classpath:/my/folder/name/myproperties.propeties
First, obtain an InputStream from which the properties are to be loaded. This can come from a number of locations, including some of the most likely:
A FileInputStream, created with a file name that is hard-coded or specified via a system property. The name could be relative (to the current working directory of the Java process) or absolute.
A resource file (a file on the classpath), obtained through a call to getResourceAsStream on the Class (relative to the class file) or ClassLoader (relative to the root of the class path). Note that these methods return null if the resource is missing, instead of raising an exception.
A URL, which, like a file name, could be hard-coded or specified via a system property.
Then create a new Properties object, and pass the InputStream to its load() method. Be sure to close the stream, regardless of any exceptions.
In a class initializer, checked exceptions like IOException must be handled. An unchecked exception can be thrown, which will prevent the class from being initialized. That, in turn, will usually prevent your application from running at all. In many applications, it might be desirable to use default properties instead, or fallback to another source of configuration, such as prompting a use in an interactive context.
Altogether, it might look something like this:
private static final String NAME = "my.properties";
private static final Properties config;
static {
Properties fallback = new Properties();
fallback.put("key", "default");
config = new Properties(fallback);
URL res = MyClass.getResource(NAME);
if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
URI uri;
try { uri = res.toURI(); }
catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); }
try (InputStream is = Files.newInputStream(Paths.get(uri))) { config.load(is); }
catch (IOException ex) { throw new UncheckedIOException("Failed to load resource", ex); }
}
Check out java.util.Properties.
You can use a static initializer. So on the top of the class you can do:
static {
Properties props = new Properties();
InputStream steam = ...; // open the file
props.load(stream);
// process properties content
String username = props.getProperty("username");
}
Use either:
CurrentClassName.class.getResourceAsStream
new FileInputStream(File)
to get the input stream depending on if the class is in or out of the classpath. Then use
Properties.load
to load the properties.
It's been a while, but if I remember correctly you just do something like this:
Properties prop = new Properties();
prop.load(new FileInputStream(filename));
//For each property you need.
blah = prop.getProperty(propertyname);
Well with static Properties it would make sense to initialize them as a Singleton which will be loaded once in a class. Here's an example:
class Example
{
public final static String PROPSFILE = "test.properties";
private static Properties props;
protected static Properties getProperties()
{
if(props == null)
{
props = new Properties();
props.load(new FileInputStream(new File(PROPSFILE));
}
return props;
}
public static User getUser()
{
String username = getProperties().getProperty("username");
return new User(username);
}
}
If you use relative Pathnames you should make sure, that your classpath is setup righ.
for me MyClass.class.getClassLoader().getResourceAsStream(..) did the trick:
private static final Properties properties;
static {
Properties fallback = new Properties();
fallback.put(PROP_KEY, FALLBACK_VALUE);
properties = new Properties(fallback);
try {
try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) {
properties.load(stream);
}
} catch (IOException ex) {
// handle error
}
}
I agree with #Daff, maybe better to use singleton class...this what i have on my project for similar requirement, maybe it may help:
clients of the class can use it like this:
ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");
System.out.format("source dir %s %n", configsLoader.getSourceDir());
and then the class:
public class ConfigsLoader {
private String sourceDir;
private String destination;
private String activeMqUrl;
private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());
private static ConfigsLoader instance = null;
private ConfigsLoader(String configFileName) {
log.info("loading configs");
Properties configs = new Properties();
try {
configs.loadFromXML(new FileInputStream(configFileName));
sourceDir = configs.getProperty("source.dir");
destination = configs.getProperty("destination");
activeMqUrl = configs.getProperty("activemqconnectionurl");
configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");
} catch (InvalidPropertiesFormatException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (IOException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
}
}
public static ConfigsLoader getInstance(String configFileName) {
if(instance ==null) {
instance = new ConfigsLoader(configFileName);
}
return instance;
}
public String getSourceDir() {
return sourceDir;
}
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getActiveMqUrl() {
return activeMqUrl;
}
public void setActiveMqUrl(String activeMqUrl) {
this.activeMqUrl = activeMqUrl;
}
}
I did this finally using getResourceAsStream() fuction associated with the class in which the static code block is being written.
//associate Property and ImputStream imports
public class A {
static Properties p;
static {
p = new Properties();
try {
InputStream in = A.class.getResourceAsStream("filename.properties");
p.load(in);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException");
e.printStackTrace();
}
}
.
.
.
}

Categories

Resources