In my JAVA+cucumber framework I have the flexibility to change the base URL by passing the parameter -Dwebdriver.base.url= in CLI. I want similar flexibility to set #DefaultUrl also.
To achieve this - I will be using a properties file, if this property file is present use it else use default ones.
But question is: How to pass URL from properties file in #DefaultUrl annotation? Page class which is extending base class doesnt understand the properties variable.
I wanted to do it like :
#DefaultUrl(properties.getProperty("homepage"))
public class homePage extends BasePage {
// TO DO
}
E.g.
#DefaultUrl("http://jira.mycompany.org")
#NamedUrls(
{
#NamedUrl(name = "open.issue", url = "http://jira.mycompany.org/issues/{1}")
}
)
public class JiraIssuePage extends PageObject {
...
}
I have below function in base class to read properties file:
public static String value(String propKey) {
if (prop == null) {
prop = new Properties();
try {
FileInputStream fis = new FileInputStream(
System.getProperty("user.dir") + "properties.properties");
properties.load(fis);
} catch (Exception e) {
e.printStackTrace();
}
}
String pvalue = properties.getProperty(propKey);
if (properties.containsKey(propKey) == false) {
logger("key not correct")
} else {
return pvalue ;
}
return pvalue;
}
Related
How to avoid enum values being formatted (./gradlew format) to a single line by spring-javaformat. The existing code defines each value in a single line and I would like to retain that as it is
public enum Color {
- YELLOW("Yellow"),
- WHITE("White");
+
+ YELLOW("Yellow"), WHITE("White");
We use the spring-javaformat-gradle-plugin
id 'checkstyle'
dependencies {
classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.28")
}
The spring-javaformat plugins do not provide configuration options to control this setting. Looking at the code, it is only possible to specify whether tabs or spaces should be used for indentation: PropertiesJavaFormatConfig.java:
class PropertiesJavaFormatConfig implements JavaFormatConfig {
private final Properties properties;
PropertiesJavaFormatConfig(Properties properties) {
this.properties = properties;
}
#Override
public IndentationStyle getIndentationStyle() {
Object value = this.properties.get("indentation-style");
return (value != null) ? IndentationStyle.valueOf(value.toString().toUpperCase().trim())
: DEFAULT.getIndentationStyle();
}
static JavaFormatConfig load(File file) throws IOException {
try (InputStream inputStream = new FileInputStream(file)) {
return load(inputStream);
}
}
static JavaFormatConfig load(InputStream inputStream) throws IOException {
Properties properties = new Properties();
properties.load(inputStream);
return new PropertiesJavaFormatConfig(properties);
}
}
I have an Email class which is abstract. It has several children: AuthenticationEmail, MarketingEmail, etc. I want to initialize value of a field (which is final static) with a string stored in an external file.
At first I though I could use Spring's #Value but it turned out that the class needs to be a component. Then I tried the following code (static initialization and etc.):
public abstract class UserAccountAuthenticationEmail extends Email implements Serializable {
#Value("${email.address.from.authentication}")
private final static String SENDER_EMAIL_ADDRESS;
static {
Properties prop = new Properties();
String propFileName = "config.properties";
InputStream inputStream;
if (inputStream != null) {
prop.load(inputStream);
inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
}
#Override
public String getSender() {
return SENDER_EMAIL_ADDRESS;
}
}
It doesn't work either, as getClass is a non-static method and cannot be instantiated inside the static block.
How can I initialize the value of this variable from a file? and preferably only one time. Is there any standard method to do that? something like #Value, instead of manually reading from IO?
Hope it can help you. A static final variable can't be changed after the first initialization.
public class UserAccountAuthenticationEmail implements Serializable {
private final static String SENDER_EMAIL_ADDRESS =getVal();
public static String getVal() {
try {
Properties prop = new Properties();
String propFileName = "C:\\SMS\\config.properties";
InputStream inputStream;
inputStream = new FileInputStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
return prop.getProperty("email");
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
}
catch (Exception e){
e.printStackTrace();
}
return "";
}
public static void main(String[] args) {
System.out.println(SENDER_EMAIL_ADDRESS);
}
}
Fixed it this way:
private final static String DEFAULT_SENDER_EMAIL_ADDRESS;
static {
String value = "";
try {
Properties prop = new Properties();
String propFileName = "application.properties";
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
value = prop.getProperty("email.authentication.sender");
}
}
catch (Exception e){
e.printStackTrace();
}
DEFAULT_SENDER_EMAIL_ADDRESS = value;
}
public String getSender() {
return DEFAULT_SENDER_EMAIL_ADDRESS;
}
I have int, float, boolean and string from Properties file. Everything has loaded in Properties. Currently, I am parsing values as I know expected value for particular key.
Boolean.parseBoolean("false");
Integer.parseInt("3")
What is better way of setting these constants values, If I don't know what could be primitive value datatype for a key.
public class Messages {
Properties appProperties = null;
FileInputStream file = null;
public void initialization() throws Exception {
appProperties = new Properties();
try {
loadPropertiesFile();
} catch (Exception e) {
throw new Exception(e.getMessage(), e);
}
}
public void loadPropertiesFile() throws IOException {
String path = "./cfg/message.properties";
file = new FileInputStream(path);
appProperties.load(file);
file.close();
}
}
Properties File.
messassge.properties
SSO_URL = https://example.com/connect/token
SSO_API_USERNAME = test
SSO_API_PASSWORD = Uo88YmMpKUp
SSO_API_SCOPE = intraday_api
SSO_IS_PROXY_ENABLED = false
SSO_MAX_RETRY_COUNT = 3
SSO_FLOAT_VALUE = 3.0
Constant.java
public class Constants {
public static String SSO_URL = null;
public static String SSO_API_USERNAME = null;
public static String SSO_API_PASSWORD = null;
public static String SSO_API_SCOPE = null;
public static boolean SSO_IS_PROXY_ENABLED = false;
public static int SSO_MAX_RETRY_COUNT = 0;
public static float SSO_FLOAT_VALUE = 0;
}
If you have a class of configuration values, like your Constants class, and you want to load all values from a configuration (properties) file, you can create a little helper class and use reflection:
public class ConfigLoader {
public static void load(Class<?> configClass, String file) {
try {
Properties props = new Properties();
try (FileInputStream propStream = new FileInputStream(file)) {
props.load(propStream);
}
for (Field field : configClass.getDeclaredFields())
if (Modifier.isStatic(field.getModifiers()))
field.set(null, getValue(props, field.getName(), field.getType()));
} catch (Exception e) {
throw new RuntimeException("Error loading configuration: " + e, e);
}
}
private static Object getValue(Properties props, String name, Class<?> type) {
String value = props.getProperty(name);
if (value == null)
throw new IllegalArgumentException("Missing configuration value: " + name);
if (type == String.class)
return value;
if (type == boolean.class)
return Boolean.parseBoolean(value);
if (type == int.class)
return Integer.parseInt(value);
if (type == float.class)
return Float.parseFloat(value);
throw new IllegalArgumentException("Unknown configuration value type: " + type.getName());
}
}
Then you call it like this:
ConfigLoader.load(Constants.class, "/path/to/constants.properties");
You can extend the code to handle more types. You can also change it to ignore missing properties, instead of failing like it does now, such that assignments in the field declaration will remain unchanged, i.e. be the default.
If you know the type of constant, you can use Apache Commons Collections.
For example, you can use some utilities method based on type of your constant.
booelan SSO_IS_PROXY_ENABLED = MapUtils.getBooleanValue(appProperties, "SSO_IS_PROXY_ENABLED", false);
String SSO_URL = MapUtils.getString(appProperties, "SSO_URL", "https://example.com/connect/token");
You can even use default values to avoid errors.
Dambros is right, every thing you store inside a Properties file is as a String value.
You can track your different primitive data types after retrieving properties value as below like ref. -
Java Properties File: How to Read config.properties Values in Java?
package crunchify.com.tutorial;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
/**
* #author Crunchify.com
*
*/
public class CrunchifyGetPropertyValues {
String result = "";
InputStream inputStream;
public String getPropValues() throws IOException {
try {
Properties prop = new Properties();
String propFileName = "config.properties";
inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
Date time = new Date(System.currentTimeMillis());
// get the property value and print it out
String user = prop.getProperty("user");
String company1 = prop.getProperty("company1");
String company2 = prop.getProperty("company2");
String company3 = prop.getProperty("company3");
result = "Company List = " + company1 + ", " + company2 + ", " + company3;
System.out.println(result + "\nProgram Ran on " + time + " by user=" + user);
} catch (Exception e) {
System.out.println("Exception: " + e);
} finally {
inputStream.close();
}
return result;
}
}
and later convert to primitive -
How to convert String to primitive type value?
I suggest you to track your data types value by putting the key values inside String type switch statement and later retrieve the related data type value by using key name cases.
String type switch case is possible after Java 7.
Not entirely sure whether I exactly understand the problem but a possibility could be to include the type of the property value in the (String) value. So for example the properties you showed would become something like:
SSO_URL = URL:https://example.com/connect/token
SSO_API_USERNAME = STRING:test
SSO_API_PASSWORD = STRING:Uo88YmMpKUp
SSO_API_SCOPE = STRING:intraday_api
SSO_IS_PROXY_ENABLED = BOOLEAN:false
SSO_MAX_RETRY_COUNT = INTEGER:3
SSO_FLOAT_VALUE = FLOAT:3.0
During the parsing of the property values you first determine the type of the property by looking at the part before : and use the part after for the actual parsing.
private static Object getValue(Properties props, String name) {
String propertyValue = props.getProperty(name);
if (propertyValue == null) {
throw new IllegalArgumentException("Missing configuration value: " + name);
} else {
String[] parts = string.split(":");
switch(parts[0]) {
case "STRING":
return parts[1];
case "BOOLEAN":
return Boolean.parseBoolean(parts[1]);
....
default:
throw new IllegalArgumentException("Unknown configuration value type: " + parts[0]);
}
}
}
Follow the dropwizard configuration pattern where you define your constants using YAML instead of Properties and use Jackson to deserialize it into your Class. Other than type safety, dropwizard's configuration pattern goes one step further by allowing Hibernate Validator annotations to validate that the values fall into your expected ranges.
For dropwizard's example...
http://www.dropwizard.io/0.9.2/docs/getting-started.html#creating-a-configuration-class
For more information about the technology involved...
github.com/FasterXML/jackson-dataformat-yaml
hibernate.org/validator/
Spring Boot has ready to use and feature reach solution for type-safe configuration properties.
Definitely, use of the Spring just for this task is overkill but Spring has a lot of cool features and this one can attract you to right side ;)
You can define your configurable parameters as 'static' in your class of choice, and from a static init call a method that loads the parameter values from a properties file.
For example:
public class MyAppConfig {
final static String propertiesPath="/home/workspace/MyApp/src/config.properties";
static String strParam;
static boolean boolParam;
static int intParam;
static double dblParam;
static {
// Other static initialization tasks...
loadParams();
}
private static void loadParams(){
Properties prop = new Properties();
try (InputStream propStream=new FileInputStream(propertiesPath)){
// Load parameters from config file
prop.load(propStream);
// Second param is default value in case key-pair is missing
strParam=prop.getProperty("StrParam", "foo");
boolParam=Boolean.parseBoolean(prop.getProperty("boolParam", "false"));
intParam= Integer.parseInt(prop.getProperty("intParam", "1"));
dblParam=Double.parseDouble(prop.getProperty("dblParam", "0.05"));
} catch (IOException e) {
logger.severe(e.getMessage());
e.printStackTrace();
}
}
}
This might help:
props.getProperty("name", Integer.class);
Hi I have a class ReadProperty which has a method ReadPropertyFile of return type Myclass which read the parameter values from a property file and return Myclass object. I need help to test the ReadPropertyFile method with JUnit, if possible with mock files and mock object.
Here is my code.
import java.io.FileInputStream;
import java.util.Properties;
public class ReadProperty {
public Myclass ReadPropertyFile(String fileName) {
Myclass myclass = null;
String testparam = null;
FileInputStream fis = null;
Properties prop = new Properties();
try {
fis = new FileInputStream(fileName);
try {
prop.load(fis);
System.out.println("Load Property file : Success !");
} catch (Exception ex) {
System.out.println("Load Property file : Exception : " + ex.toString());
}
/*
* loading the properties
*/
try {
testparam = prop.getProperty("testparam");
System.out.println("testparam Type : " + testparam);
} catch (Exception ex) {
System.out.println("testparam Type : " + ex.toString());
}
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Property file read fail : " + ex.toString());
System.exit(1);
}
Myclass = new Myclass(testparam);
return Myclass;
} }
I don't think that you really need to mock anything here. You want to test if your property reader is able to access and read a file as you expect, so test exactly that. For regular properties it can go like this:
#Test
public void shouldReadPropFileFromSingleString() {
final Properties p = PropertiesLoader
.loadProperties("propfile");
assertNotNull(p);
assertFalse(p.isEmpty());
for (final Entry<Object, Object> e : p.entrySet()) {
assertEquals(expectedProperties.get(e.getKey()), e.getValue());
}
}
For your case, you can adapt it:
#Test
public void shouldReadCorrectProp() {
final MyClass p = ReadProperty
.readPropertyFile("propfile");
assertNotNull(p);
assertEquals(expectedProperty, p);
}
You may also want to test the sad path - what happens if the property file is not found, are any fallback properties available etc.
BTW, I would advise changing the method name, since reading a property file is not the primary concern of your method - retrieving a property is. Better yet, decompose the method into a getProperty and a readPropertyFile method, where the first method calls the second. So you will have a cleaner design according to Separaton of Concerns
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();
}
}
.
.
.
}