Working with properties files outside war with Spring - java

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"/>

Related

how to add a parameter to spring project before <projectname>/login and after <localhost>:<portnumber> without hardcode?

I'm working on a Spring MVC project. When I run the application the URL is:
http://localhost:8080/insureYou/login
but I want:
http://localhost:8080/contextroot/insureYou/login
Is there any way of doing it without hardcoding?
In a spring-boot project you can set the context-root by specifying the following property in the application.properties file:
server.servlet.context-path=/yourcontextroot
Without spring-boot, it depends on the webserver and Tomcat offers a number of options.
I would personally opt for a META-INF/context.xml file in your war file containing the necessary information but you can also include the information in the server.xml file or in a ROOT.xml file.
See the following links for further guidance:
How to set the context path of a web application in Tomcat 7.0
https://tomcat.apache.org/tomcat-8.0-doc/config/context.html
https://www.baeldung.com/tomcat-root-application
This type of deployment however sometimes is handled separately, through an Apache server reverse-proxy or through URL rewriting.
I recommend you ascertain whether this type of need is already taken care of by your company's deployment procedures, as you may not need to deal with it at all.

Store properties in database, but override locally

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.

How to load properties using zookeeper as the data source for a spring based web application?

I have a web application which is initialised using spring and built using maven.
The various properties are loaded using properties files which are statically present. Since various environments require different values for the same properties, i use maven profiles to load different properties files depending upon the environment at build time.
Ex:- dev.properties for dev environment and prod.properties for production environment.
Now i want to make the build independent of the properties files,
The value of the properties will be fetched from some datasource(zookeeper) during context initialisation.
How to load the properties before the context is initialised?
Spring Cloud Config Zookeeper offers a way to do that. I posted a brief example of use here
Properties is just one of Java class and that Apache Configuration project exactly provides such an abstraction. I just showed you a sample for JDBC, but there is really many other stuff there. Here is a sample how I load properties from DB StoredProcedure:
<jee:jndi-lookup id="dataSource" jndi-name="DS"/>
<bean id="storedProcedureConfiguration" class="com.my.proj.config.StoredProcedureConfiguration"
p:dataSource-ref="dataSource"
p:sqlQuery="pki_props.getProperties"/>
<bean id="propertiesFromDB" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:staticMethod="org.apache.commons.configuration.ConfigurationConverter.getProperties"
p:arguments-ref="storedProcedureConfiguration"/>
<context:property-placeholder properties-ref="propertiesFromDB"/>
So, you can implement your own AbstractConfiguration to load Properties from Zookeeper and inject it to the <context:property-placeholder>.
In the java constructor, simply set a connection to the Zookeeper server and get the needed data using the zookeeper client methods. You can find examples here: http://zookeeper.apache.org/doc/trunk/javaExample.html
It would look like this (but you would have to elaborate this)
public YourConstructor() {
Zookeeper zk = new ZooKeeper(host,...);
zk.getData(...);
}

How to implement environment-specific init parameters in my tomcat application

I'd like to be able to implement a configuration-less deployment for my java application (tomcat7, spring-mvc). For example, right now we are considering creating one context.xml file for each environment (prod, stage, dev) we deploy to:
context_prod.xml
context_stage.xml
context_dev.xml
context.xml (for localhost)
On each of our servers we would have a symlink context.xml which would point to the appropriate context file (e.g. context_prod.xml). So when we deploy, we don't have to worry about changing database references, keys, etc.
I feel like there's probably a better way to do this; perhaps one that is built into spring?
Spring has recently added the functionality to handle environment configuration:
http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
This still seems a little bit complicated for me and I have done exactly what you are asking in my own Spring MVC applications for our logging. In my DispatcherServlet configuation I have this line:
<context:property-placeholder location="classpath*:/system.properties"/>
<util:properties id="mySystemProperties" location="classpath:/logging/log4j-${system.runMode}.properties" />
system.runMode is just an env variable that we created and is set in CATALINA.SH at startup like this: Setting environment variable TESSDATA_PREFIX in Tomcat
I then use Spring EL to reference any values I want and it works per environment. As you can see I did this for our logging and have a different logging configuration file per environment.
You could use Spring #Profile introduced in Spring 3.1. In your case you could use profiles like dev, stage, prod etc.
This profile value could be initialized run time. So when your application started, Spring could fetch appropriate profile based on configuration.
You could setup profile from environment variable, via deployment descriptor (web.xml) etc. This Spring source tutorial could be interesting for you.
I personally using Maven build to replace the profile value during build time in the web.xml. In the build time I passed profile value as build argument.

db.properties vs persistence.xml which one is better?

Recently I started a maven project to build an application for integrating
Spring, JPA, JSF
But in the automatically generated folder structure I can see one file named as
db.properties
and also I have one
persistence.xml
Now my question is that Database connection can be defined in either of these files, Can anybody tell me
1. Which way is better and why ?
2. Why there is db.properties file automatically generated while I already have persistence.xml ?
db.properties file is like messages.properties which is used to define key value pair. And after that we will use keys in expression language. So configurations will only be done in
persistence.xml or dataSource.xml
whichever is preferred choice but the values we will take from db.properties in the form of expression language eg.
driverClassName=com.mysql.jdbc.Driver
this is an entry in your db.properties. and you will use it in persistence.xml as follows.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}" />
I assume, from the fact that you mention JSF, that you are building a web application for deployment to an application server. I also caveat this question in that I don't know about db.properties or where it comes from.
When deploying to an application server, it is always best to configure your database connections in the container and expose them to the application via JNDI. This allows the container to manage connection pooling and credentials and keeps this information out of your WAR/EAR files. It also ensures that your WAR/EAR files are agnostic to the particular database instance, so can be deployed to a container in any environment without modification.
Therefore, I recommend against configuring your datasource in persistence.xml.
See also Difference between configuring data source in persistence.xml and in spring configuration files which is a similar question- the accepted answer there expresses the solution in more detail.

Categories

Resources