I have this in my config.properties file.
DBServerName=SomeServer
DBUserId=myId
I know how to create a Configuration java class so that this works
Configuration.get("DBServerName");
However, I am trying to create a Configuration file where I can make the following call.
Configuration.getDBServerName() ;
I do not actually want to write the getDBServerName() method. I want to Configuration class to read the properties file and create the corresponding getXXX() methods automagically.
Please help.
Before anyone points out, I have read the following, and I am looking for answers beyond what have been mentioned here.
create java classes based on values defined in .properties file
Update 1
The lombok folks seem to have solved this. Trying out http://notatube.blogspot.in/2010/12/project-lombok-creating-custom.html
I think you should read properties file as text file and push data into array
Example
public class ReadPropertiesFile {
public static void main(String[] args) {
try {
File file = new File("test.properties");
FileInputStream fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInput);
fileInput.close();
Enumeration enuKeys = properties.keys();
while (enuKeys.hasMoreElements()) {
String key = (String) enuKeys.nextElement();
String value = properties.getProperty(key);
System.out.println(key + ": " + value);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Related
I have a problem in a class I wrote. The purpose of the class is to add/remove/update for the applicationResource.properties files which the <spring:message code="key" /> uses to provide bilingual support to the website. Manually interacting with the properties files works fine, but I had a greater need and so I built in a way to allow changes to be done from the database. This has given me a very dynamic and flexible system that I can work from.
However, there is a problem. At some point after even a single change using this, the French characters end up getting changed. Such as Déconnexion becoming Déconnexion. When looked at in notepad++ its first Déconnexion and then corrupted to D\u00C3\u00A9connexion. This example was part of the original properties file.
The original (not temp) properties files have the text file encoding set to other: UTF-8. The Project properties text file encoding is set to inherited from container (Cp1252). I tried changing to Other: UTF-8 with no change.
So my question(s) is, what is causing the corruption to my French characters and how can I fix it? I have provided the complete class below.
Update: After the assistance from StephaneM in her answer I was able to track down exactly what is causing the corruption, but have not fixed it yet. The loadProperties() function in the AR Class. As soon as the temp AP files are loaded the French characters are corrupted. This makes me suspect the original process which creates the temp AP files is using a different encoding. So I will have to track it down.
package pojo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
/*
* Purpose of this class is to handle all the ApplicationResource(_fr).properties interactions
* so that there is one unified location handling this, instead of code duplication.
*/
public class AR{
public final String en_path = "/ApplicationResources.properties";
public final String fr_path = "/ApplicationResources_fr.properties";
private Properties en_prop = null;
private Properties fr_prop = null;
public AR()
{
loadProperties();
}
private void loadProperties()
{
InputStream en_is = null;
InputStream fr_is = null;
try {
this.en_prop = new Properties();
this.fr_prop = new Properties();
en_is = this.getClass().getResourceAsStream(en_path);
fr_is = this.getClass().getResourceAsStream(fr_path);
en_prop.load(en_is);
fr_prop.load(fr_is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean keyExist(String mykey, String mypath) //deprecated due to better code/method
{
Properties test_prop = null;
InputStream is = null;
try {
test_prop = new Properties();
is = this.getClass().getResourceAsStream(mypath);
test_prop.load(is);
Set<Object> keys = test_prop.keySet();
for(Object k:keys) {
String key = (String)k;
//System.out.print(key + " ");
if(key.equals(mykey))
{
return true;
}
}
//System.out.println(" ");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public boolean en_keyExist(String mykey)
{
//searches english file
loadProperties();
return en_prop.containsKey(mykey);
//return keyExist(mykey, en_path); //original method
}
public boolean fr_keyExist(String mykey)
{
//searches french file
loadProperties();
return fr_prop.containsKey(mykey);
//return keyExist(mykey, fr_path); //original method
}
public boolean en_fr_keyExist(String mykey)
{
//searches both english and french files
loadProperties();
return (en_prop.containsKey(mykey) && fr_prop.containsKey(mykey));
//return (keyExist(mykey, en_path) && keyExist(mykey, fr_path)); //original method
}
public String en_returnProperty(String mykey)
{
//returns null if key does not exist
loadProperties();
return this.en_prop.getProperty(mykey);
}
public String fr_returnProperty(String mykey)
{
//returns null if key does not exist
loadProperties();
return this.fr_prop.getProperty(mykey);
}
public void appendProperty(Properties new_en_prop,Properties new_fr_prop)
{
//note: during a test, setProperty (used in populating the properties) does not allow duplicates, it overwrites.
//So, load the existing properties, and for each new property add it
loadProperties();
for(Object key : new_en_prop.keySet())
{
en_prop.setProperty((String)key, new_en_prop.getProperty((String)key));
}
try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
{
en_prop.store(en_os, null);
} catch (IOException e) {
e.printStackTrace();
}
for(Object key : new_fr_prop.keySet())
{
fr_prop.setProperty((String)key, new_fr_prop.getProperty((String)key));
}
try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
{
fr_prop.store(fr_os, null);
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean appendProperty(String mykey, String en_val, String fr_val) //appears to have timing error due to only saving last value
//due to timing error this function is only suitable for single additions
//due to the timing error, tried returning boolean to have it finished but was not successful
//setting the class variables to static did not solve the timing issue
{
loadProperties();
en_prop.setProperty(mykey, en_val);
try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
{
en_prop.store(en_os, null);
} catch (IOException e) {
e.printStackTrace();
}
fr_prop.setProperty(mykey, fr_val);
try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
{
fr_prop.store(fr_os, null);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public void en_setProperty(String mykey, String en_val)
//suspected timing issue, use only for singular changes
{
loadProperties();
en_prop.setProperty(mykey, en_val);
try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
{
en_prop.store(en_os, null);
} catch (IOException e) {
e.printStackTrace();
}
}
public void fr_setProperty(String mykey, String fr_val)
//suspected timing issue, use only for singular changes
{
loadProperties();
fr_prop.setProperty(mykey, fr_val);
try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
{
fr_prop.store(fr_os, null);
} catch (IOException e) {
e.printStackTrace();
}
}
public void compareResources()
{
Properties new_en = new Properties();
Properties new_fr = new Properties();
for(Object key : en_prop.keySet())
{
new_en.setProperty((String)key, en_prop.getProperty((String)key));
}
for(Object key : fr_prop.keySet())
{
new_fr.setProperty((String)key, fr_prop.getProperty((String)key));
}
Properties temp = (Properties) new_en.clone();
for(Object key : temp.keySet())
{
if(new_fr.containsKey((String) key))
{
new_fr.remove(key);
new_en.remove(key);
}
}
for(Object key : new_en.keySet())
{
System.out.println("English only key: " + ((String)key));
}
for(Object key : new_fr.keySet())
{
System.out.println("French only key: " + ((String)key));
}
}
}
Sample use case for the class, taken directly from application, but with some editing so only the relevant parts are here
AR testing = new AR();
Properties en_prop = new Properties();
Properties fr_prop = new Properties();
final String test_prod_cur = "{call BILINGUAL_VALUES(?)}";
ResultSet rs = null;
try (
Connection connection = jdbcTemplate.getDataSource().getConnection();
CallableStatement callableStatement = connection.prepareCall(test_prod_cur);
)
{
callableStatement.registerOutParameter(1, OracleTypes.CURSOR);
callableStatement.executeUpdate();
rs = (ResultSet) callableStatement.getObject(1);
while (rs.next())
{
String thead = rs.getString(1);
en_prop.setProperty(keyheader+thead, rs.getString(2));
fr_prop.setProperty(keyheader+thead, rs.getString(3));
//testing.appendProperty(keyheader+thead, rs.getString(2), rs.getString(3)); //has a timing issue, ends up only appending final value
}
}
catch (SQLException e)
{
System.out.println("SQLException - bilingual values");
System.out.println(e.getMessage());
}
testing.appendProperty(en_prop, fr_prop);
Regarding this question: "what is causing the corruption to my French characters and how can I fix it?", the answer is in the documentation ( Properties.store() ):
public void store(OutputStream out,
String comments)
throws IOException
Writes this property list (key and element pairs) in this Properties
table to the output stream in a format suitable for loading into a
Properties table using the load(InputStream) method.
Properties from the defaults table of this Properties table (if any)
are not written out by this method.
This method outputs the comments, properties keys and values in the
same format as specified in store(Writer), with the following
differences:
The stream is written using the ISO 8859-1 character encoding.
Characters not in Latin-1 in the comments are written as \uxxxx for their appropriate unicode hexadecimal value xxxx.
Characters less than \u0020 and characters greater than \u007E in property keys or values are written as \uxxxx for the appropriate hexadecimal value xxxx.
I am not the only person who has faced this issue, I managed to find another question and it was one of the answers that lead me to my solution. I have to thank another site for letting me know what to include.
There are only four added or changed lines, I will list them, and then give a complete function.
import java.io.Reader;
Reader reader = new InputStreamReader(fr_is, "UTF-8");
fr_prop.load(reader); //instead of fr_prop.load(fr_is);
reader.close();
The complete function
import java.io.Reader;
private void loadProperties()
{
InputStream en_is = null;
InputStream fr_is = null;
try {
this.en_prop = new Properties();
this.fr_prop = new Properties();
en_is = this.getClass().getResourceAsStream(en_path);
fr_is = this.getClass().getResourceAsStream(fr_path);
Reader reader = new InputStreamReader(fr_is, "UTF-8");
en_prop.load(en_is);
fr_prop.load(reader);
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
By introducing the reader and using that, it has cleared up French character corruption.
I should mention that I changed every file property I could find over to UTF-8 before I did the above changes and got it working. This site gives you the changes I made. This was a nice page that helped me confirm the encodings.
I have to write a different class to read a file of different kind. Now project is deployed on client side. And we have to give support to new files. so we have to create a new class and also modify in service class to create a new object of newly added class. Writing a new class for new type of class is fine. But I do not want to change service class each time. Is there any solution for this kind of problem? Thanks in advance.
Update 1: here is code of service class
#Service("StockistServiceImpl")
public class StockistServiceImpl implements StockistService {
#Override
#Transactional(propagation = Propagation.REQUIRED,rollbackFor=Exception.class)
public JSONArray saveStockistOrder(Integer stockistId,
MultipartFile[] orderFile, String orderNumber, String orderDate,
String partyCode,String order,Integer userId)
{
List<Pair<String, Integer>> charList = new ArrayList<Pair<String, Integer>>();
Properties code1 = new Properties();
try {
code.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("categoryOfFile.properties"));
}
catch (IOException e) {
//System.out.println("error in loading divisionNamePdfCode.properties");
e.printStackTrace();
}
String readDuelListedTxtFile = code.getProperty("readDuelListedTxtFile");
String readStartLineLengthForOrderTxtFile = code.getProperty("readStartLineLengthForOrderTxtFile");
String ReadFileWithNoStartLineTxtFile = code.getProperty("ReadFileWithNoStartLineTxtFile");
String ReadStartLineLengthForQtySingleListTxtFile = code.getProperty("ReadStartLineLengthForQtySingleListTxtFile");
if (readDuelListedTxtFile.contains(partyCode
.trim())) {
charList.addAll(dualListText
.readDuelListedTxtFile(
fileName, codeDetails));
}
else if (readStartLineLengthForOrderTxtFile.contains(partyCode
.trim())) {
charList.addAll(lineLength
.readStartLineLengthForOrderTxtFile(
fileName, codeDetails));
}
else if (ReadFileWithNoStartLineTxtFile.contains(partyCode
.trim())) {
T_FileWithNoStartLine noStartLine = new T_FileWithNoStartLine();
charList.addAll(noStartLine
.readFileWithNoStartLineTxtFile(
fileName, codeDetails));
}
else if (ReadStartLineLengthForQtySingleListTxtFile.contains(partyCode
.trim())) {
T_StartLineLengthForQtySingleList noStartLine = new T_StartLineLengthForQtySingleList();
charList.addAll(noStartLine
.readStartLineLengthForQtySingleListTxtFile(
fileName, codeDetails));
}
}
Update 2: here is property file from where we know that what is file type for a stockist.
#fileType,stockistCode
fileType1=ST001,ST009
fileType2=ST002,ST005,ST006
fileType3=ST003,ST007
fileType4=ST004,ST008
and i want to add a new property file like this to map a file type with class name so if a new class is added and then we will not have to edit service class.
#fileType,fullyqualifiedclassName
fileType1=FullyQualifiedClassName1
fileType2=FullyQualifiedclassName2
fileType3=FullyQualifiedClassName3
fileType4=FullyQualifiedclassName4
Separate the creation of the file readers objects and the service class.
public class BuildFileReader() {
FileReader getReader(String xyz) {
FileReader reader;
...
your logic
reader = new WhatEverReaderYouWant();
...
return reader;
}
}
The service class simply asks the BuildFileReader which FileReader to use and doesn't need to change anymore.
public class StockistServiceImpl {
...
BuildFileReader bfr = new BuildFileReader();
FileReader fileReader = bfr.getReader(xyz);
fileReader.readFile(fileName, codeDetails);
...
}
If you need only one type of file reader per client, you could configure your BuildFileReader for each client.
If you need more than one type of file reader per client, define an interface for each type an add a getReaderXYZ() function for each needed type in BuildFileReader.
Instance can be created at runtime using reflection in java, please have a look at below post:
Creating an instance using the class name and calling constructor
Finally after doing some code changes and adding property file for mapping class names with property of file here is the code and working fine.
#Service("StockistServiceImpl")
public class StockistServiceImpl implements StockistService {
List<Pair<String, Integer>> charList = new ArrayList<Pair<String, Integer>>();
Map<String,String> mapTxtFile = new HashMap<String, String>();
Properties fileTypeProperties = new Properties();
Properties matchClassNameProperties = new Properties();
try {
fileTypeProperties.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("fileTypeProperties.properties"));
}
catch (IOException e) {
//e.printStackTrace();
}
try {
matchClassNameProperties.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("matchClassNameProperties.properties"));
}
catch (IOException e) {
//e.printStackTrace();
}
for (String key : fileTypeProperties.stringPropertyNames()) {
String value = fileTypeProperties.getProperty(key);
mapTxtFile.put(key, value);
if(value.contains(partyCode.trim())){
String className = matchClassNameProperties.getProperty(key);
try {
Class clazz = Class.forName(className);
try {
TxtFile objToReadTxtFile = (TxtFile) clazz.newInstance();
charList= objToReadTxtFile.readTxtFile(fileName, codeDetails);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
//read normally else block
}
}
}
Now it is working fine.But for that i created an interface for reading txt file which has readTxtFile method. and all other classes now implement this interface.
I wrote a code in java to run some scripts which can return different result depending on the environment setup. I would like to store the result of every execution. I try with properties file but every time it executes, it overwrites the previous result in config.properties. I did a research but not find any most likely example. This is my code to return properties file. The value which will be different are TCpassed and TCfailed on every execution.
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
public class ExecutionProperties {
public void setConfigProperties(int tcPassed, int tcFailed){
Properties prop = new Properties();
OutputStream output = null;
try {
output = new FileOutputStream("config.properties");
// set the properties value
prop.setProperty("TCpassed", ""+ tcPassed);
prop.setProperty("TCfailed", ""+ tcFailed);
// save properties to project root folder
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Is it possible to get the execution time and store it in config.properties in order to differentiate with the previous result?
Thanks before
You can use append mode using constructor FileOutputStream("config.properties", true)
Sample properties file after couple of execution
#Mon May 04 13:03:29 IST 2015
TCpassed=1
TCfailed=1
#Mon May 04 13:04:03 IST 2015
TCpassed=1
TCfailed=1
Property file are usually key value pairs, e.g.
TCpassed=9
TCfailed=1
So if you want to store the result of every execution, you need a different key for every execution.
And if you want to append to the property file, you can:
Load the property file as Properties object;
Add new entry to the Properties object;
Write the Properties Object back to the file;
Here is an example:
public static void appendTestResult(File propertyFile, int tcPassed, int tcFailed) {
try {
Properties properties = loadProperties(propertyFile);
String testId = getTestID();
properties.setProperty("TCpassed_" + testId, String.valueOf(tcPassed));
properties.setProperty("TCfailed_" + testId, String.valueOf(tcFailed));
saveProperties(propertyFile, properties);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void saveProperties(File propertyFile, Properties properties) throws IOException {
OutputStream outputStream = null;
try {
outputStream = FileUtils.openOutputStream(propertyFile);
properties.store(outputStream, "new test");
} finally {
IOUtils.closeQuietly(outputStream);
}
}
public static Properties loadProperties(File propertyFile) throws IOException {
InputStream inputStream = null;
try {
inputStream = FileUtils.openInputStream(propertyFile);
Properties properties = new Properties();
properties.load(inputStream);
return properties;
} finally {
IOUtils.closeQuietly(inputStream);
}
}
public static String getTestID() {
return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}
I have a config file containing server information such as FTP URL's and their credentials. I am trying to, on deployment of my web app, reference the config.properties file to assign the stored values to local variables but for whatever reason cannot find the file.
I have a getConfigProperties class:
public class getConfigProperties {
public Properties getConfig(String fileName) {
// load config file
Properties prop = new Properties();
InputStream input = null;
try {
// grab config file from destination
input = getConfigProperties.class.getClass().getResourceAsStream(
fileName);
// check if input is null
if (input == null) {
System.out.println("Sorry, unable to find "
+ "config.properties");
return null;
}
// load content
prop.load(input);
// start to declare variables
// Prod vars
System.out.println(prop.getProperty("prismUrlProd"));
System.out.println(prop.getProperty("prismUserProd"));
System.out.println(prop.getProperty("prismPassProd"));
System.out.println(prop.getProperty("cardUrlProd"));
System.out.println(prop.getProperty("cardUserProd"));
System.out.println(prop.getProperty("cardPassProd"));
System.out.println(prop.getProperty("pwcProd"));
System.out.println(prop.getProperty("esdSignInProd"));
System.out.println(prop.getProperty("emailProd"));
// used to catch possible errors
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return prop;
}
public static void main(String[] args) {
getConfigProperties a = new getConfigProperties();
a.getConfig("/config/config.properties");
}
}
And I use this in another class to assign the variables. Inside my method, I set a Properties object to what is returned from getConfig(String filename):
public static void initialize() {
// load config file
getConfigProperties config = new getConfigProperties();
Properties prop = config.getConfig("/config/config.properties");
}
It's explained in properties file in web app that on deplyoment, our location of the config.properties changes, but when trying "/WEB-INF/classes/config/config.properties", I can't find the file. Using the main in my getConfigProperties class, I am able to find config.properties no problem and reference the text in my config file by printing it to console. Any possible suggestions as to where this file may be on deployment? Do I have to reference it a certain way? Any help would much be appreciated.
I got this to work by putting config.properties in my src folder and referencing it by "config.properties".
I need to delete files from within a java program and have written this code. It fails to delete the file and I can't figure why. The File is not in use and not write protected.
public static void delfile(String filetodel) {
try {
File file = new File("filetodel");
if (file.delete()) {
System.out.println(file.getName() + " is deleted!");
} else {
System.out.println("Delete operation is failed." + filetodel);
}
} catch (Exception e) {
e.printStackTrace();
}
}
I guess the issue is this:
File file = new File("filetodel");
This should possibly be (inferred from the parameter filetodel passed in the method):
File file = new File(filetodel);
Everything else seems fine, and is working on my machine.
If you just want to delete the file, there is no need for loading it.
java.nio.file.Files.deleteIfExists(filetodel); (where filetodel contains the path to the file)
Returns true if the file was deleted, so you can even put it in your if-clause.
hey buddy you should use a path as parameter in delete
static void delete(Path path)
Deletes a file.
static boolean deleteIfExists(Path path)
Deletes a file if it exists.
search here: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html
so in your case
File file = new File("c://user//filetodel");
file.delete();
or use getAbsolutePath(filename) and use it in file path
Here is my code to delete file.
public class deletef
{
public static void main(String[] args)
{
try{
File file = new File("/home/rahul/Downloads/ou.txt");
if(file.delete()){
System.out.println(file.getName() + " is deleted!");
}else{
System.out.println("Delete operation is failed.");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
your code is also right but you have to put extension also in your file
File file = new File("filetodel");
here add extension also of file other wise your code will not delete file