How to configure properties in XML? - java

I am planing to Maven develop a module that actually needs to read configuration data something like below, where tag <path> will be repeated multiple times with different path name and can be same <pathtype> and different URL and parameters and then attempt to access those URLs and paths in Java classes.
In Java I should be able to read all <pathurl> tags and its parameters for given type. then I will process them in Java one by one.
What is best way to configure this data and read in Java? Should it be normal properties file loading process by Java or there is any new best practice using spring or any other utility.
Basically I want to know is there any way of configuring data other than in this XML format and then parsing it? Since the data is static in that XML, my client don't want to use database.
<path>
<pathname>mypath</pathname>
<pathtype>httpfile</pathtype>
<pathurl>http://acdsds:8380/gis/</pathurl>
<params>
<user>sad</user>
<password>spwd</password>
<httprescd>100</httprescd>
<mexist>DROD_MEF.gif</mexist>
</params>
</path>

When it comes to configuring software using certain properties such as URL's, passwords and unique keys in spring PropertyPlaceHolderConfigurer is your best bet.
From spring document:
You use the PropertyPlaceholderConfigurer to externalize property values from a bean definition in a separate file using the standard Java Properties format. Doing so enables the person deploying an application to customize environment-specific properties such as database URLs and passwords, without the complexity or risk of modifying the main XML definition file or files for the container.
What you will do is, put all your configuration data in a properties file:
##JDBC related properties start here##
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseURL=jdbc:mysql://localhost:3306/databaseName
jdbc.userName=root
jdbc.password=root
##JDBC related properties end here##
## path Configuration start here##
path.name=mypath
path.type=httpfile
path.url=http://acdsds:8380/gis/
## path Configuration ends here##
Then, configure spring to access external properties file(assuming your properties file is named settings.properties):
<!--settings for accessing external property files-->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/yourPathToPropertiesFile/settings.properties</value>
</list>
</property>
</bean>
After you have configured PropertyPlaceholderConfigurer, access your properties by simple using #value annotation, wherever you want.
#Value("${path.name}")
String pathName;
You can even use properties file to configure you data source and many other stuff:
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.databaseURL}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

You should probably start by reading some basic tutorials on XML processing in Java. I'm biased, but my standard recommendation is still the material at IBM's DeveloperWorks XML site

You can use json configuration file and Google's Gson(https://code.google.com/p/google-gson/) to parse the json file. Refer to this thread Parse a nested JSON using gson on how to use Gson library & sample json format.

Related

Get Spring Environment as Properties

I wonder if there is a way to extract properties from Spring Environment (e.g. obtained from ApplicationContext) in the form of Properties instance? Or, at least, is there a way to enumerate the properties in Spring Environment, or get them all as a map, or any other way I can turn a [initially unknown] set of properties into a Properties object?
I need this in order to create a jclouds Context by calling org.jclouds.ContextBuilder.newBuilder() and .overrides(Properties). The idea is to configure the actual cloud provider solely by means of .properties file, and I don't want to couple application logic with provider-specific properties.
[UPDATE]
The .properties files to be used are configured using <context:property-placeholder>, and it actually specifies a list of paths, like this:
< context:property-placeholder location=
"classpath:/jdbc.properties,
file:${jboss.server.config.dir}/jdbc.properties,
file:${catalina.home}/conf/jdbc.properties"
ignore-resource-not-found="true"/>
which suggests that the .properties file is searched in the mentioned list of locations in order. I would like to achieve the following:
keep the list of .properties files and their possible locations in this XML definition file only;
allow to place jclouds related properties in any of the .properties files mentioned in the XML;
access the properties, resolved and loaded by Spring, in the form of Properties object so I am able to feed that to jclouds ContextBuilder.
Please let me know if all of this is feasible. Thank you in advance!
-Vlad
If you wan't to use properties in your Spring configuration then you can simply use:
<context:property-placeholder location="classpath:foo.properties" />
To get the properties in your code later you can simply read this file from the classpath into a Properties object:
props.load(MyClass.class.getClassLoader().getResourceAsStream("foo.properties"));
Alternatively you can have a look at PropertyPlaceholderConfigurer.
UPDATE
Updated after Deinum's remark but only if you are getting the properties from a Spring managed bean:
<util:properties id="myProps"
location="classpath:foo.properties"/>
<context:property-placeholder properties-ref="myProps" />
Now you can inject myProps into Spring managed beans (no need to load them again from the classpath).
You could use PropertiesFactoryBean and do something like this:
<bean id="jcloudsProps"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>your/props/file.properties</value>
</property>
</bean>
You can then use jcloudsProps as you would any other Spring bean.

metrics-spring configuration via .properties file

I'm trying to configure metrics-spring via configuration file
In my spring.xml I've added
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>
classpath:metrics.properties
</value>
</list>
</property>
<property name="systemPropertiesModeName"
value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="searchSystemEnvironment" value="true"/>
</bean>
filled with something like
metrics.reporter.type=console
and then I'm setting it in the spring config accessing that property via ${metrics.reporter.type}
<metrics:reporter metric-registry="metrics" type="${metrics.reporter.type}" period="1m"/>
During the startup of the web application, spring throws a BeanDefinitionParsingException due to the unresolved variable above
Configuration problem: No ReporterElementParser found for reporter type '${metrics.reporter.type}'
I'm using this configuration method (via properties file) for mongo host and port and it works like a charm.
I'm running in Tomcat7, Spring 4.0.5.RELEASE, metrics framework 3.1.0-SNAPSHOT (I need jersey 2 support) and metrics-spring 3.0.1. I also tried with a self-compiled metrics-spring 3.1.0-SNAPSHOT but doesn't solve my problem.
[EDIT]
Found this issue which explain that SpEL is not supported by the ElementParser.
I'm afraid it isn't possible to use a property placeholder in the type attribute. Spring does not resolve property placeholders or SpEL until the phase after metrics-spring reads the type attribute and parses the reporter element (which is necessary to allow placeholders and bean references to be used in all the other attributes).
A possible solution would be to configure all the reporters you might want to use, and use a placeholder in the enabled attribute:
<metrics:reporter metric-registry="metrics" type="console" period="1m"
enabled="${metrics.reporter.console.enabled}" />
<metrics:reporter metric-registry="metrics" type="slf4j" period="1m"
enabled="${metrics.reporter.slf4j.enabled}" />
And the properties file:
metrics.reporter.console.enabled=true
metrics.reporter.slf4j.enabled=false
I hope this makes sense, I've had a very long week!

property not found with multiple context:property-placeholder

I am using spring 3.1 with spring profiles to load the beans. In my app context file, I load the properties like :
<context:property-placeholder order="1" location="classpath*:META-INF/spring/*_${spring.profiles.active}.properties" ignore-unresolvable="true"/>
And then I use the property value to load the data source bean like
<property name="driverClassName" value="${database.driverClassName}"/>
It works fine.
The problem starts when I add a couple of more property placeholders so that properties from some database tables can be loaded.
This uses a properties reference loaded by
<bean id="configFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="globalSystemConfiguration"/>
</bean>
To add to the details, this configFactoryBean uses the datasource to load the properties from the database.
When I do this, I have the following exception:
java.lang.ClassNotFoundException: ${database.driverClassName}
My analysis is that its trying to load the datasource before resolving the property from the first context property placeholder. I may be wrong. Or maybe spring profile variable is not resolved properly.
Can anyone please help me to fix this.
Thanks
Akki
This bug about multiple property placeholders might relate to your problem: https://jira.spring.io/browse/SPR-9989
When using multiple PropertyPlaceholderConfigurer in conjunction with
#Value annotation and default value for placeholders syntax (ie
${key:defaultValue}), only the first PropertyPlaceholderConfigurer is
used. If this configurer does not contain the desired value, it falls
back to #Value default even if the second
PropertyPlaceholderConfigurer contains the value.
Affects Version/s: 3.1.3
Each <context:property-placeholder> creates a new instance of PropertyPlaceholderConfigurer - it gets messy easily. You should have one such thing per application and on application level, not on libraries' one - that makes maintenance much easier.
For more details and a suggestion how to cope with it look here:
http://rostislav-matl.blogspot.cz/2013/06/resolving-properties-with-spring.html
In my application I am using property-placeholder configurer in following way and it works very well. You can try that.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
</list>
</property>
</bean>
I think this should resolve your problem. :)
Since you have suggested hardcoding the path to the configuration file works, try using the profiles attribute on the tag to selectively include the configuration.
<beans profile="profileName">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
<beans profile="profileName2">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
See this article explaining profiles: http://java.dzone.com/articles/using-spring-profiles-xml

Using configurable properties in Java web applications

I have a java based web application deployed on Tomcat 6. I need to make some properties as configurable. Currently i have created a config.properties file and load that file in a static Properties object.
I want to know if there is any other efficient method or framework to use configurable properties in Java web applications?
Try this sample;
This is sample Resource.properties file that place in com.package;
name=John
email=john#company.com
description=John is a Java software developer
And access likes this;
private static final String PROPERTIES_FILE = "com/package/Resource.properties";
Properties properties = new Properties();
properties.load(this.getClass().getResourceAsStream(PROPERTIES_FILE));
String name = props.getProperty("name");
String email = props.getProperty("email");
String description = props.getProperty("description");
The other framework to use configurable properties is JSF.This sample is the usages of properties in JSF.
Another option you might have would be to have one class with all your constants of your projects defined in it. This will provide you with a centralized way in which you can configure your application effectively and efficiently.
That being said however, I think that using the configuration files is the best option since (I do not think) that you would have to recompile your code each time after changing.
EDIT: Seeing some of the comments above, what you could make would be to have a separate table in your database in which you would be able to store all your constants. You can then make this table available to system administrators and other support personnel through a back end web interface.
The enterprise level answer would be to load your configuration through an integration framework like Spring. If your application is fairly small I wouldn't necessarily recommend it, though.
Loading properties with Spring Framework:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:configuration.properties"></property>
</bean>
<!-- Here is configutaion for connection pool -->
<!-- Those ${} properties are from the configuration.properties file -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
</beans>

What is the best practice to deploy database config (username/password) with Java web-app (web.xml)?

I have a Java web-app using standard web.xml and servlets. At the moment, I'm using the <context-param> tags in web.xml to define the database configuration (JDBC url, username, password, etc.). These are picked up by a servlet in its init() method.
But I'd like to not include database username/password in my source repository.
For testing, I'm using jetty-maven-plugin. With that, I specify an option overrideDescriptor with a supplementary web.xml that is applied after the primary web.xml. I put my testing database configuration in this supplementary file, and everything works great.
For deployment, my host is using Tomcat. I'm not sure how to apply a database config here. Is there a similar way to specify a supplementary web.xml file? If not, what is the best practice to do this? Read the configuration from a separate properties file (or similar) included as a resource?
You should be using connection pools and JNDI. You keep the credentials on the server that way. Users only need the JNDI lookup name (e.g., "jdbc/FooDataSource") to access the connection pool.
"Read the configuration from a separate properties file (or similar) included as a resource?"
Yes.
There are lots of ways to do THAT, too. My current project uses Spring's PropertyPlaceholderConfigurer to read the appropriate properties files and allow any of the values to be used in a context file using the usual ${whatever} notation.
Addition:
Incidentally, we use a custom subclass of PropertyPlaceholderConfigurer to set the locations of the files. We use a "global" properties file that applies to all environments (dev, test, uat, prod) and then one file for each environment that overrides the global settings.
The files themselves are deployed in a jar, but we don't need the flexibility of changing the values on the fly.
You could always store the configuration in an external .properties file, change your servlet to read from this instead (perhaps having web.xml point at the path to the file), and thus keep the file only on the server and out of source control.
In your application-context.xml , you can use the place holders and point the location of the placeholder's parameters to external properties file.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/database-config.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
In your database-config.properties file. You can provide the placeholder's parameters. In this case database settings.
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.password=root

Categories

Resources