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>
Related
I am writing a Spring Jar (Without Spring boot) which connects to database. Almost all the tutorials which I saw connects to Database using the spring XML and the password is hard coded in the XML file.
This is in no way allowed in production environment and way out of standards in terms of security.
Can someone please help me if there is a way to inject password from a method call which inturn retrieves the password from a secured vault and provides the password to datasource object in runtime.
something like below.
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="username" value="postgres" />
<property name="password" value=getPasswordfromSecureVault("username") />
<property name="suppressClose" value="true" />
<jdbc:initialize-database >
<jdbc:script location="create-tables.sql"/>
</jdbc:initialize-database>
Based on the spring boot tag that you have, I'll assume that you're using spring boot for your project. With spring boot, it is very easy to externalize configuration for your application. It also auto-configures your datasource with a connection pool if you use the starters they provide.
In your case, you could benefit from moving to using spring boot's Externalized Configuration.
What that would allow you to do is to use an environment variable to configure your spring application. For example, to configure your password, use the environment variable SPRING_DATASOURCE_PASSWORD. You could also use the Java option -Dspring.datasource.password=[password] when starting the application, for example:
java -jar -Dspring.datasource.password=password app.jar
If using docker containers, the environment variable way is generally my go to as it's very straight forward for people to understand.
If you really want to configure the password from a method call, you can do that too using java configuration. Create a bean of type DataSource and Spring should pick it up and use it.
#Configuration
class AppConfiguration {
#Bean
public DataSource dataSource() {
String password = // Get your password
return DataSourceBuilder.create().password(password).build();
}
}
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.
I am using Spring 3.0.x to get a WorkManager from an application server and use it to run scheduled jobs that need database access. The problem is, is that this application could be deployed to different Java application servers - in this case, to Websphere 7.0 and GlassFish 3.1 OSE. (Crazy combo, I know...)
The problem I am having is that before deploying to either, I have to change the bean to reference the appropriate TaskExecutor class used for each server. I have Spring load up an applicationContext.xml with these beans in it.
For Websphere, I have to pull the WorkManager externally and use the following bean:
<bean id="myTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
<property name="resourceRef" value="true"/>
</bean>
and the web.xml has something like this:
<resource-ref>
<description>WorkManager</description>
<res-ref-name>wm/default</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
For GlassFish, I can just use the bean:
<bean id="myTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
</bean>
Can I somehow dynamically change which TaskExecutor implementation is used on the fly?
I could easily check for the Websphere resource to determine if I am on Websphere, then fall back to GlassFish. But how to load a class like that with Spring (using Annotations or otherwise) is baffling me.
Any help is appreciated. Thanks!
P.S. I am not worried about being J2EE compliant for GlassFish - it's just that Websphere forces you to be so (hence pulling an external WorkManager)
You can easily use a custom VM argument to determine what environment you are running in, and use that to load the appropriate context file.
One file for each supported environment, all of which define the same bean.
task-exec-was.xml
task-exec-glassfish.xml
Add a required VM argument.
-Dapp.server=was
Then, wherever you actually load the bean you include the appropriate file based on a PropertyPlaceholderConfigurer.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<import resource="task-exec-${app.server}.xml" />
Edits based on information in the comments.
You can override for the environment you do have control over in this case.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="location" value="classpath:spring/was.properties/>
</bean>
<import resource="task-exec-${app.server}.xml" />
Now you have a file called spring/was.properties that defines a property app.server=was, which is read by default. In Glassfish, you supply the same property as a VM argument, which will now override the property read from the file.
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
I am new to openJPA.
I have a scenario where, depending upon the server where my application is running, I need to change the settings to persistance.xml.
For eg. if its running on Server A, then it should use different database(different url), different password etc. and if the application is running on Server B then it should use different information.
And could you also tell me, which way should it be done, using datasource or simply putting properties under persistence-unit.
FYI I am using WS app. server 7 and RAD 7.5
Any type of help would be highly appreciated.
You're using an application server so you don't need to set database connection settings in the persistence.xml file. You should be able to create a JNDI data source in your appserver and then use that. EAch server could have the data source have the same JNDI name and then there'll be no need for any persistence.xml differences.
Workshop, JPA, and DataSources seems particularly relevant to you. As does Setting up a JNDI data source in WebSphere 6.0/6.1 and WebSphere + JNDI + Spring Framework + Hibernate.
Are you using Spring? If so, then the problem is easy to solve: you don't put the data source information in your persistence.xml, you put it in your application context and that'll have different configuration on each server.
For example:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.class}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
and each server could have a different database.properties file on each server (where each is in the classpath somewhere in this example):
database.username=scratch
database.password=scratch
database.class=oracle.jdbc.OracleDriver
database.url=jdbc:oracle:thin:#localhost:1521:XE
Changing persistence.xml at runtime is going to be problematic as that's not really how JPA is designed.
Of course, you can use JNDI data sources with Spring also.