updating a properties file in a web application - java

I have a properties file (under rsources folder) in which I'm stocking a variable (key=value),
I need to update it when a user insert a new value or update the older one , so can I do it?
I have doubts because it's a web application so it' simply a war deployed in the server. So how it is possible to access the .properties file and change it directly from the code?
If it's not possible, is there another solution?

Perhaps the user could provide an overriding properties file in the filesystem, whose values would override the packaged default properties file.
Check out Apache Commons Configuration, which permits this capability.
Often you want to provide a base set of configuration values, but
allow the user to easily override them for their specific environment.
Well one way is to hard code the default values into your code, and
have then provide a property file that overrides this. However, this
is a very rigid way of doing things. Instead, with the
CompositeConfiguration you can provide many different ways of setting
up a configuration.

Instead of modifying a properties file, you can create a new table in your database (e.g T_PROPERTIES) and add/modify rows in the table.
Define the table with 2 column, key and value and change the records accordingly.

You can let the user write to a properties file, but I don't think it's very clean to do.
There is a class called "Properties" in the java.util package, you can use this class to load a representation of a physical properties file from your webapplication.
for example to load a properties file you could use following code:
public void loadProps(File pfile) throws IOException {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(propsFile);
props.load(fis);
fis.close();
}
Now you can just use built in commands to manipulate the file:
-setProperty(String key, String value);
-get(Object key);
After you're done with it you can just call the save method on the properties Object.
You will need an OutputStream for that.

Related

ResourceBundle file outside jar

I have a spring boot application with /resources/application.properties, when deployed there is a application.properties next to the jar (and the one inside it).
Somewhere in the code I use ResourceBundle.getBundle("application").getString("x") but that always return the value defined in the properties inside the jar.
My objective is to get the value from the external file if it exists, if not then I need to get the value from inside the jar. Just like the default springs behavior but I'm not able to achieve this.
edit:
You can either use the solution in the correct answer below or you can rely on springs Environment by autowiring it and using getProperty()
ResourceBundle.getBundle(String baseName) relies on the classloader and not directly the file system to find the resource.
This is equivalent to invoke the overloaded one :
getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader()),
So your result is expected.
What you look for is PropertyResourceBundle.
To create an instance of you need either a Reader or an InputStream.
You could load both external and internal files.
ResourceBundle internalProps = ResourceBundle.getBundle("application");
ResourceBundle externalProps = new PropertyResourceBundle(Files.newInputStream(Paths.get("application.properties"));
You could so use the external ResourceBundle in first intention and the second one as fallback.

How to Mock the Property File in Junit

I am creating a Unit test case using Junit . Now My application is Maven Based with many profile Also I am using the Values from configuration file (Property File ) which Varies from one profile to other. I want that Unit Test run will have specified properties only not the profile one when it is running the test cases.
These can be done in 2 ways
1) Either i Mock the Property File for Unit Test .( which i dont know How) .
2) Or during run time i change the property file parameter values.(Again difficult to answer) . Any help will be appreciated .
One option: use dependency injection in order to acquire a java.util.Properties object for example.
Meaning: your production code simply holds a Properties object; like:
class Foo {
private final Properties properties;
public Foo(Properties) {
this.properties = properties;
At runtime, when the class that creates Foo objects reads property files from disk, turns them into a Properties object and gives it to the Foo constructor.
In your unit test, your test code creates a Properties object and adds whatever values you require upon creating a Foo object.
The less elegant detour: make sure that your production code reads its properties from a location that gets defined at runtime. That would allow you to create custom property files in some temp directory, and then you instruct your code under test to work with those files.
Did not got your question exactly - In one side, you are saying: you don't want to use profile related values and other side you are saying: you'll need to run with specific values (do you mean runtime values or test specific values).
Now, To answer your 1st question:
1) Either i Mock the Property File for Unit Test:
you can instantiate and load a property file(test specific) and keep the required values there in that file.
2) Or during run time i change the property file parameter values:
you can mock specific property keys with values. like below:
public void shouldBuyBread() throws Exception {
//given
given(mypropertyUtil.getProperty("NUMBER_OF_BREADS")).willReturn(10);
//when
Goods goods = shop.buyBread();
//then
assertThat(goods, containBread());
}

Which type of resource file to use to store constants

I am developing an application that tests web Services, and I use JUnit parameterized tests. I want to read parameters from a resources file.
I am wondering which is the best way to store these parameters.
In a .properties file ?
test1.inputPath= C:\\Path
test1.expectedOutputPath= C:\\Path
test2.inputPath= C:\\Path2
test2.expectedOutputPath= C:\\Path2
In an xml file?
<test>
<inputPath> C:\Path <\inputPath>
<expectedOutputPath> C:\Path <\expectedOutputPath>
<\test>
<test>
<inputPath> C:\Path2 <\inputPath>
<expectedOutputPath> C:\Path2 <\expectedOutputPath>
<\test>
Other way to do this?
Thanks.
Do not try to make your life more complicated ;) You can easily read property files in this way:
Properties prop = new Properties();
InputStream input = new FileInputStream(fileName);
prop.load(input);
String s = prop.getProperty("test1.inputPath");
and import:
import java.util.Properties;
is it still complicated for you?
The best solution that I found for my problem is to use PropertiesConfiguration of Apache Commons Configuration. It is very simple to use:
In my .properties file :
test1= Path1,Path2
test2= Path3,Path4
Then I read the .properties file automatically and I retrieve paths as a String array for each test.
#Parameters
public static Collection<Object[]> readPropertiesFile(){
ArrayList<Object[]> result= new ArrayList<Object[]>();
try {
Configuration config = new PropertiesConfiguration("testPaths.properties");
Iterator<String> keys=config.getKeys();
while(keys.hasNext()){
String[] paths= config.getStringArray(keys.next());
result.add(paths);
}
} catch (ConfigurationException e) {
e.printStackTrace();
}
return result;
}
The answer is, of course, there are MANY ways of doing it.
First ask yourself: do these properties will change? Are they parameters or are they constants?
For example, the number of the states, what are the chances they will change? In this case you need a constant, not a parameter.
Now, if you are looking for something that can changed at runtime then you should look into properties and resource bundles.
If all you need are constants, then you can do something like:
public interface Constants
{
public char NUMBER_ONE = '1';
public long A_LONG_TIME_AGO = 1321322;
public String CANT_BREAK_WITH_IRON_PICKAXE= "OBSIDIAN";
}
There are many advantages in using interfaces: they don't need to be instantiated, won't slow down your system with IO access, and all attributes are static final.
However, if you need to load the values during runtime, then use properties files. Although all answers here are good, the only one I consider good enough is Spring's #Configuration and #ImportResource, which are injected, allow for nice mocking, and integrate nicely with the rest of the Spring framework, and can be easily overridden with -D from the command line.
Example on how to load properties files using a mix of xml and properties files: Spring-Boot: How do I reference application.properties in an #ImportResource

How to implement dynamic referenced configuration in Java?

I have a configuration (config.properties) something like
app.rootDir=
app.reportDir=${app.rootDir}/report
The app.rootDir is not a fixed parameter and it must be initialized by external module. I need keep the ${app.reportDir} keep dynamic reference to ${app.rootDir}.
Use pseudo code to illustrate the problem:
// Init the root dir as '/usr/app'
config.setValue('app.rootDir','/usr/app');
// I need the reportDir to be '/usr/app/report'
String reportDir = config.getValue('app.reportDir');
I can write some codes to get this feature but I'd like to know if there is any existing library do this?
I can use properties, yaml, or json as configuration file type, according to the library availability.

How can I create an auto-generated enum from a resource file?

I want to create an auto-generated resource file similar to R from android. I know how to do the parsing and creation of the file and essentially creating a new class file. What I don't know how to do is start this auto-generation process.
So, using eclipse (although if there is a way to make this happen in an agnostic fashion, I would prefer it), how can I trigger an auto-generation session to read a properties file and create a .java file holding static variables and the "keys" from this parsed file, that I can then reference from my code?
A few examples of how to generate java source files have already been provided. It should be relatively easy to read the properties file and invoke one of these APIs.
To trigger the code generation process, you need to add a custom build step. With Ant, just add a custom task. And then hook it up to an Eclipse Builder: project Properties -> Builders -> New.
Subsequently, Eclipse should find and refresh this file on its own. If it doesn't, then check your configs: Preferences -> General -> Workspace -> find "Refresh using native hooks or polling" and similar ones and check them. (Note that I'm not 100% sure that this last part will work.)
The path of least resistance is to run this build step separately. If your properties file is not changing that often, then it shouldn't be that big a deal. This is similar to what you'd do if you use Protocol Buffers, JAXB, wsdl2java, etc. If you want everything to work magically like R.java does, then you probably have to do something a little more complicated:
 - Try to use Eclipse Builder options to control when the Ant task is executed
- If you can't figure that out, then I'd check out how Eclipse hooks up to the above projects (that is, to Protocol Buffers, JAXB, wsdl2java, etc.)
- Look at the ADT custom PreCompilerBuilder class
- Check out the build-helper-plugin
It is common to use a ResourceBundle to create an object that allows you to lookup properties by key. You can learn about the ResourceBundle on the Java Trail.
The basic idea is that you have a text file with a .properties extension. You point the ResourceBundle object to that file. You can then use the getString() or getObject() method passing in the key to the property you want. That is all there is to it. You just need to load the ResourceBundle when you start your program (or sometime before you need it).
If you create you own class that has a ResourceBundle as a member value, you can use a simple bit of code like this to have a simple get() method to get the property value:
public String get(String aString)
{
String sVal = null;
try
{
sVal = (String)myProperties.getObject(aString);
}
catch (MissingResourceException e)
{
log.debug("Missing Property Value: "+aString);
}
return sVal;
}
I hope that is useful.

Categories

Resources