I have properties file app.properties and it has 50 different properties.
I am accessing those in my java class using
Properties prop = new Properties();
prop.load("app.properties");
System.out.prinltn(prop.getProperty("APPNAME"));
Actually, I want to get rid of accessing property like prop.getProperty("APPNAME"). Is there any best way in java to access properties.
I can declare all variables as static in java class.
static String appName = prop.getProperty("APPNAME");
Any other best way available?
I can suggest two approaches:
1. Define a utility method which will take String as parameter and return value from properties.
For Example:
public static String GetValue(String key) {
return properties.getProperty(key);
}
And now you can use this function on callers
String value = GetValue("key"); // properties.getProperty("key");
Define above method and in addition create one class Called Constants(or something suitable). Define all your Keys here as Static final variable.
public class Constants
{
public static final String KEY = "key";
public static final String KEY2 = "key2";
}
and now make call for getting value using these variable instead of string:
String value = GetValue(KEY); //GetValue("key");
If you do only option 1, your code is becoming more readable. But I will recommend 2nd option, which is making your code readable as well as maintainable.
You can easily do following operation :
Update property name
No need to worry about mistyping key etc.
You may use "resourceBundle" package as
First import the resourceBundle API:
import java.util.ResourceBundle;
Create an instance of your property file:
private static ResourceBundle resource = ResourceBundle.getBundle("app");
Now you can get the value of the property:
String appName = resource.getString("APPNAME");
IMO, your approach of using static variables to hold the values is the best. The following structure was what I was using in a project for the same functionality.
package snippet;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class Constants {
public static final String APPNAME;
public static final String VERSION;
public static final int DEFAULT_TIMEOUT;
static {
Properties p = new Properties();
try {
p.load(new FileInputStream("constants.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
APPNAME = p.getProperty("APPNAME");
VERSION = p.getProperty("VERSION");
DEFAULT_TIMEOUT = Integer.parseInt(p.getProperty("DEFAULT_TIMEOUT"));
}
}
Of course, there were checks for NumberFormatException etc.
Related
I have a complex enum class in my spring boot application which holds different status values for different systems.
package com.foo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public enum Status {
FOO_STATUS("Status1" ,"status_1", "STATUS_1", "stat1"),
BAR_STATUS("Status2" ,"status_2", "STATUS_2", "stat2" ),
FOO1_STATUS("Status3" ,"status_3", "STATUS_3", "stat3" ),
BAR1_STATUS("Status4" ,"status_4", "STATUS_4", "stat4" ),
....
....
....
private final String system1Status;
private final String system2Status;
private final String system3Status;
private final String system4Status;
private static Map<String, String> statusMap;
Status(String system1Status, String system2Status, String system3Status, String system4Status) {
this.system1Status = system1Status;
this.system2Status = system2Status;
this.system3Status = system3Status;
this.system4Status = system4Status;
}
public String getSystem1Status() {
return system1Status;
}
public String getSystem2Status() {
return system2Status;
}
public String getSystem3Status() {
return system3Status;
}
public String getSystem4Status() {
return system4Status;
}
private static void initializeMapping() {
statusMap = new HashMap<>();
for (Status map : Status.values()) {
statusMap.put(map.getSystem1Status(), map.getSystem2Status());
}
}
public static String getSystem2StatusForSytem1Status(String status) {
if (statusMap == null) {
initializeMapping();
}
if (statusMap.containsKey(status)) {
return statusMap.get(status);
}
return null;
}
public static String getSystem3StatusForSytem1Status(String status) {
....
}
public static String getSystem4StatusForSytem2Status(String status) {
....
}
public static String getSystem3StatusForSytem2Status(String status) {
....
}
....
....
}
The enum holds status string mapping for various systems. It also has methods to get different system status by supplying the current system status.
Ex: We can get System1 status by sending the System 2 status value.
As the enum is getting more complex , is there any alternate way to hold this static data?
PS: I know this can be moved to a reference table in DB, But I am looking for any alternate within the code (like loading from yaml file).
The concern about the enum getting more and more complex is only valid if that complexity is accidental, not inherent. Otherwise, switching to a different approach would just move that complexity elsewhere (which kind of seems to be the case in your example). I think it makes sense to keep the enum (even if it grows complex) iif the following conditions are met:
There is no reasonable scenario in which you would want/need to account for new statuses or new mappings (or drop existing ones) without changing the code.
You rely on at least some enum features available out of the box, so you would have to reimplement those by hand. E.g. values() listed in a determinate order, valueOf() used with canonical String labels, ordinal() to infer position, compareTo(), name(), serialization, etc.
You use the enum constants polymorphically (and maybe you need to alter the behavior for some of them without a full-fledged class hierarchy) or you want to leverage the compiler check for exhaustive case branches in switch expressions (with newer java versions).
I'm working on a Java project that uses a big class of constants like:
public final class Settings {
public static final int PORT_1 = 8888;
public static final int PORT_2 = 8889;
...
}
Now, some of the value of those constants are not available at compile time anymore so I need a way to "initialize" them at application starts (e.g. from the args[]). Once initialized there should be no way to change them. I'm not very skilled in java, how do I do this in an acceptable way?
I thought of using a singleton with something like a "one shot" set method that throws an exception if called more than one time but it seams too hacky...
You can use a static initializer like this:
public final class Settings {
public static final int PORT_1;
public static final int PORT_2;
...
static {
// create the value for PORT_1:
PORT_1 = ...;
// create the value for PORT_2:
PORT_2 = ...;
}
}
The static initializer is executed during class loading. The final keywords on PORT_1 and PORT_2 protects them to be changed afterwards.
Well, using system properties is a way of doing it unless there is a huge amount of constants.
private static final String CONSTANT1 = System.getProperty("my.system.property");
private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));
System properties are passed on the command line when starting the application using the -D flag.
If there are too many variables a static initializer can be used where a property file or similar can be read that holds the properties:
public class Constants {
private static final String CONSTANT1 = System.getProperty("my.system.property");
private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));
private static final String CONSTANT3;
private static final String CONSTANT4;
static {
try {
final Properties props = new Properties();
props.load(
new FileInputStream(
System.getProperty("app.properties.url", "app.properties")));
CONSTANT3 = props.getProperty("my.constant.3");
CONSTANT4 = props.getProperty("my.constant.3");
} catch (IOException e) {
throw new IllegalStateException("Unable to initialize constants", e);
}
}
}
Note that if you are using some external framework such as Spring Framework or similar there is usually a built-in mechanism for this. E.g. - Spring Framework can inject properties from a property file via the #Value annotation.
There is no simple way to do this in Java. One way to simulate this is to use a builder which returns an internal type (so it can write the private fields) but the internal type only has getters.
See this answer: https://stackoverflow.com/a/1953567/34088
I am using SimpleXml 2.6.1 in my android app. Eventhough the documentation (http://simple.sourceforge.net/download/stream/doc/javadoc/index.html?org/simpleframework/xml/Order.html) says the order of the elements in the xml are same as the way they have defined in the class file, I am always getting the order to be random in the xml. If I add few more variables, the order of the elements again changes.
Adding #Order notation works, but since the class is complex with 100s of variables, I do not want to add order. Is this a known bug for android versions? It works fine in java console programs.
p.s: I opened the .class file disassembled and found the variables declared in the same order as java file, so I don't think it's a class file issue.
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Order;
#Order(elements = {"name", "isTrue"})
public class SimpleXml {
public static final String NAME = "$NAME$";
public static final String IS_TRUE = "$IS_TRUE$";
#Element
private String name;
#Element
private Boolean isTrue;
...
Since there is no answer, I'll try to save precious time to anyone who gets here.
I found no cause, and since I don't have time to analyze Simple libraries, I came up with a "workaroud". It's more of an advice, actually - don't use it for (marshaling)creating xml if you have a large xml definition and the order matters(a rule more than an exception). The order is mostly used for marshaling anyway so just save yourself some time and do it manually.
The template:
<document>
<name>$NAME$</name>
<isTrue>$IS_TRUE$</isTrue>
</document>
The class:
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
/**
* User: ksaric
*/
public class SimpleXml {
public static final String NAME = "$NAME$";
public static final String IS_TRUE = "$IS_TRUE$";
private String name;
private Boolean isTrue;
public SimpleXml() {
}
public Boolean getTrue() {
return isTrue;
}
public void setTrue(Boolean aTrue) {
isTrue = aTrue;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
String template = null;
try {
template = getTemplate();
} catch (IOException e) {
e.printStackTrace();
}
/* GUAVA - checkNotNull() */
if (null == template) return null;
template = template.replace(NAME, getName());
/* OR CONVERT IN THE GETTER METHOD */
template = template.replace(IS_TRUE, getTrue().toString());
return template;
}
/* SINGLETON? Performance(IO) loss... */
public String getTemplate() throws IOException {
InputStream templateStream = getClass().getResourceAsStream("/template.xml");
/* APACHE IO COMMONS */
/*
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
*/
final String stringTemplate = IOUtils.toString(templateStream);
return stringTemplate;
}
}
The test:
import org.junit.Test;
import static junit.framework.Assert.*;
/**
* User: ksaric
*/
public class SimpleXmlTest {
#Test
public void test() throws Exception {
//Before
/* Use standard instantiation, factory method recommended for immutability */
SimpleXml simpleXml = new SimpleXml();
simpleXml.setName("This is a name");
simpleXml.setTrue(false);
//When
String result = simpleXml.toString();
//Then
assertNotNull(result);
System.out.println(result);
}
}
Not really an answer, but save yourself some time and don't use Simple(which is a great library) on Android...
Simple Xml doesn't preserve Order on Android. Based on pfh's answer, here is my recommendation:
I would prefer to use JAXB in the case where you want the order to be preserved than manual string/template parsing. JAXB is slightly complex to use than SimpleXml but comes with similar set of annotations based xml serialization and deserialization.
I inherited an application which uses a java properties file to define configuration parameters such as database name.
There is a class called MyAppProps that looks like this:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected static Properties myAppProps = null;
public static final String DATABASE_NAME = "database_name";
public static final String DATABASE_USER = "database_user";
// etc...
protected static void init() throws MyAppException {
try {
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(PROP_FILENAME);
myAppProps = new Properties();
myAppProps.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
protected static String getProperty(String name) throws MyAppException {
if (props==null) {
throw new MyAppException("Properties was not initialized properly.");
}
return props.getProperty(name);
}
}
Other classes which need to get property values contain code such as:
String dbname = MyAppProps.getProperty(MyAppProps.DATABASE_NAME);
Of course, before the first call to MyAppProps.getProperty, MyAppProps needs to be initialized like this:
MyAppProps.init();
I don't like the fact that init() needs to be called. Shouldn't the initialization take place in a static initialization block or in a private constructor?
Besides for that, something else seems wrong with the code, and I can't quite put my finger on it. Are properties instances typically wrapped in a customized class? Is there anything else here that is wrong?
If I make my own wrapper class like this; I always prefer to make strongly typed getters for the values, instead of exposing all the inner workings through the static final variables.
private static final String DATABASE_NAME = "database_name"
private static final String DATABASE_USER = "database_user"
public String getDatabaseName(){
return getProperty(MyAppProps.DATABASE_NAME);
}
public String getDatabaseUser(){
return getProperty(MyAppProps.DATABASE_USER);
}
A static initializer looks like this;
static {
init();
}
This being said, I will readily say that I am no big fan of static initializers.
You may consider looking into dependency injection (DI) frameworks like spring or guice, these will let you inject the appropriate value directly into the places you need to use them, instead of going through the indirection of the additional class. A lot of people find that using these frameworks reduces focus on this kind of plumbing code - but only after you've finished the learning curve of the framework. (DI frameworks are quick to learn but take quite some time to master, so this may be a bigger hammer than you really want)
Reasons to use static initializer:
Can't forget to call it
Reasons to use an init() function:
You can pass parameters to it
Easier to handle errors
I've created property wrappers in the past to good effect. For a class like the example, the important thing to ensure is that the properties are truly global, i.e. a singleton really makes sense. With that in mind a custom property class can have type-safe getters. You can also do cool things like variable expansion in your custom getters, e.g.:
myapp.data.path=${myapp.home}/data
Furthermore, in your initializer, you can take advantage of property file overloading:
Load in "myapp.properties" from the classpath
Load in "myapp.user.properties" from the current directory using the Properties override constructor
Finally, load System.getProperties() as a final override
The "user" properties file doesn't go in version control, which is nice. It avoids the problem of people customizing the properties file and accidentally checking it in with hard-coded paths, etc.
Good times.
You can use either, a static block or a constructor. The only advice I have is to use ResourceBundle, instead. That might better suit your requirement. For more please follow the link below.
Edit:
ResourceBundles vs Properties
The problem with static methods and classes is that you can't override them for test doubles. That makes unit testing much harder. I have all variables declared final and initialized in the constructor. Whatever is needed is passed in as parameters to the constructor (dependency injection). That way you can substitute test doubles for some of the parameters during unit tests.
For example:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected Properties props = null;
public String DATABASE_NAME = "database_name";
public String DATABASE_USER = "database_user";
// etc...
public MyAppProps(InputStream is) throws MyAppException {
try {
props = new Properties();
props.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
public String getProperty(String name) {
return props.getProperty(name);
}
// Need this function static so
// client objects can load the
// file before an instance of this class is created.
public static String getFileName() {
return PROP_FILENAME;
}
}
Now, call it from production code like this:
String fileName = MyAppProps.getFileName();
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(fileName);
MyAppProps p = new MyAppProps(is);
The dependency injection is when you include the input stream in the constructor parameters. While this is slightly more of a pain than just using the static class / Singleton, things go from impossible to simple when doing unit tests.
For unit testing, it might go something like:
#Test
public void testStuff() {
// Setup
InputStringTestDouble isTD = new InputStreamTestDouble();
MyAppProps instance = new MyAppProps(isTD);
// Exercise
int actualNum = instance.getProperty("foo");
// Verify
int expectedNum = 42;
assertEquals("MyAppProps didn't get the right number!", expectedNum, actualNum);
}
The dependency injection made it really easy to substitute a test double for the input stream. Now, just load whatever stuff you want into the test double before giving it to the MyAppProps constructor. This way you can test how the properties are loaded very easily.
Consider this sample class,
class TargetClass {
private static String SENSITIVE_DATA = "sw0rdfish";
private static String getSensitiveData() {
return SENSITIVE_DATA;
}
}
When I do this,
import java.lang.reflect.Method;
public class ClassPiercing {
public static void main(String... args) throws Exception {
Class targetClass = Class.forName("TargetClass");
Method[] methods = targetClass.getDeclaredMethods();
methods[0].setAccessible(true);
String sensitiveData = (String)methods[0].invoke(null, null);
System.out.println("Sensitive Data: " + sensitiveData);
}
}
The output is,
Sensitive Data: sw0rdfish
This is dangerous. How do I prevent this from happening?
Well, use a SecurityManager.
http://java.sun.com/javase/6/docs/api/java/lang/SecurityManager.html
http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html#ReflectPermission
disabling ReflectPermission should do the trick.
The point of access control is not to prevent someone from hacking in to your code; It's a matter of signalling intend to other programmers (eg. api design). If you don't trust the other program, you should run use different measures. For example, you could encrypt the data somehow.