Currently, we store our application's environment properties in a .properties file in the WEB-INF. We want to move them to a database table. But we still want to specify the jndi name, and when running in our test environment locally, we want to be able to override certain properties just for our workspace for test and development.
Apache commons' DatabaseConfigurator seemed nice, but wouldn't play nice with the jndi name being defined as a property in the file. Nothing I did to ask it to look at the property file first worked.
I decided to subclass apache commons' AbstractConfiguration to try to create a single configurator that would check the file and database as I wished, but again, it didn't really work. Spring wants that jndi name absolutely first, probably because the data source has to be passed into the configurator as a parameter.
How can I get what I am after here? Mostly properties in the database, but those that are in the file override them. And jndi name for the datasource should not have to be hardcoded in the spring config.
Why don't you write a ApplicationContext listener that will read the configuration from your DB and inject them in the JNDI? Then you can override the configuration in the JNDI with a context.xml file that will be placed in the src/local/webapp/META-INF/.
This is how we get this working in our webapp.
Related
I have a config.properties file which contains configurable properties e.g. database connection details in a webapp deployed on tomcat. e.g.
local.driver: com.mysql.jdbc.Driver
local.username:myuser
local.password:mypass
dev.driver: com.mysql.jdbc.Driver
dev.username:mydevuser
dev.password:mydevpass
I can retrieve the values from config.properties using spring Environment object or #Value.
My question is how do you make Spring's environment object pick local properties when running on local and dev properties when running on dev? Also it doesn't sound right to save sensitive data e.g. production database connection
details in properties file which will float around in code base. So how do you add production detail when in production environment? Ideally I would want to change them as and when I like and not have to redeploy the app. Am I going the right direction?
Note - All the answers I have seen on SO discuss changing these properties within java code. I don't want to do that I want to be able to configure these values independent of the application code.
Thanks
You can have a look at spring profiles to load a specific file for a specific environment.
Alternatively, you can also parameterize the file from where the properties are loaded in the application context using a JNDI property or an environment property set in the container.
Example:
<context:property-placeholder ignore-unresolvable="true" location="${env.config.file:classpath*:META-INF/spring/profiles/dev/dev.properties}" />
The env.config.file can be set at the container level (say Tomcat) using -Denv.config.file= when starting it. By doing this, Spring automagically finds the property in the system props and replaces it. If you don't set it explicitly (for example, in dev where you might use some other container, such as jetty), it would use the given default value (in this example, dev.properties).
By putting the properties files outside the war / ear, they can be changed at will, and only the context needs to be restarted. Alternatively, you could look into re-loadable property placeholders. This also helps if you don't want passwords stored in the war in clear.
For encrypting information in the property files, if you're using Spring 3, you can also check: http://www.jasypt.org/spring3.html.
for picking env specific values you have couple of options
If you can create multiple properties file based on env then you can use Spring profile feature (i.e spring.profiles.active), this will allow to control properties file to loaded via JVM parameter.
If you still want to keep all the stuff in single fle then you can override PropertyPlaceholderConfigurer to take env details from JVM parameter or default to some value
On security question , one the approach is to store encrypted password in prop file.
In my project I have 2 modules, a ejb and a war module. In the war module i have a properties file that is processed when I start the web application (by a listener). For each property in this properties file, i add it to the servlet context.
So, my question is: is it possible to access this properties, in the servlet context, from a enterprise java bean in the ejb module? I want to do something like this, but in a ejb:
ServletContext sc = myservlet.getServletContext();
String xpto = sc.getAttribute("my-attr");
If this is not possible, what is the alternative?
Thanks!
P.S I'm using netbeans and glassfish.
ServletContext is always loaded ahead in the Servlet lifecycle loading. Ref to this link. As you see the Listeners are loaded after the ServletContext is loaded when application starts. You can have your code in the listener class that extends ServletContextListener. Ensure you are extending correct Listener as given in the link.
In your situation, One of the alternative is to have a Singleton class load all the properties from the properties file. for ex: ApplicationPropertiesLoader class can have a Properties map attribute to store the key value pairs of that property file. This class can have a getProperty method that always refer to its internal Properties.
In your servlet class refer to this singleton class to load the properties as required.
Speaking of alternatives, it might be worth a thought to use configuration stored in database, at least if you already have a database connection in your application and have control over the database schema.
We use this technique in all our web applications, mainly for two reasons:
Changes to a property can be done during runtime without monitoring file changes, they can be done by the application itself and one does not need to know a path outside of the deployed application.
Properties can have additional information, such as a type (e.g. number, date, string), a default value, a comment or a user who changed it.
For implementing it, you'll create an application-scoped component which accesses the database properties for the rest of the application.
I am working on a web application, developed using spring mvc and server is tomcat. Now one of the requirement is that admin can upload a spring related service configuration file(which is different from the spring service configuration file residing in src code) with some changes because we want to make it configurable. Now server will be restarted to get the modified changes.
Now I am confused about one thing, where I should upload this file(file system?) so that when server is started then configured listener will pick up new configuration file.
Pls suggest solution considering it as enterprose aplication.
Find out the reasonable place to keep your system files, other than in webapps/.
(I had kept next to log folder.)
Use Spring's PropertyPlaceholderConfigurer to read file locations from properties file.
Use same locations and Create ApplicationContext object, in a factory method (You can pass any number of files).
Use getBean on applicationContext object to use beans.
I have several Spring based apps - web, web services
For my web services project, in my ws-config.xml file, I specify the location of the wsdl. This has been set to localhost in the past, but I now need to have this as a configurable value in a properties file if I can.
<ws:dynamic-wsdl id="ServiceDefinition"
portTypeName="Test" locationUri="http://localhost/Test/webservice">
<ws:xsd location="/WEB-INF/schemas/my-test.xsd" />
</ws:dynamic-wsdl>
I need to be able to reference the locationUri as a property, but I dont know how to do it?
Can anyone help?
Check out the PropertyPlaceHolderConfigurer. You can use this to specify properties in your Spring configs, and specify which properties sources to populate this property from. You can specify a hierarchy of sources, such that (say) you have a file of default properties, and then some overridden values in a per-user config.
Here's a trivial example.
I am working on a Spring 3.0.5 web application that accesses LDAP and two databases. I have a properties with configuration information for the LDAP server and that databases, in applicationContext-security.xml and dispatcher-servlet.xml, but I would like to make it so each server can have different data properties without changing a file in the WAR. Can I somehow put a file somewhere else on the server and still access it from within my application?
Add this to your context
<context:property-placeholder location="${envfile}"/>
This will load the properties file located at ${envfile}, a variable you can set with Java's startup paramater like this
-Denvfile="file:/var/server/environment.properties"
Or maybe in Tomcat's startup script
CATALINA_OPTS=" -Denvfile=file:/var/server/environment.properties"
Values can be retrieved in your controllers using Springs Value annotation like this:
#Values("${myvalue}")
private String myValue;
Please note that these features require Spring 3.1, more information here
Good luck!
Try
<util:properties id="props" location="file:///path/to/server.properties"/>