Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Web Application Configuration Patterns

Are there any patterns or best practices that can be used to simplify changing configuration profiles for java web applications across multiple environments. e.g. JDBC URLs, SOAP end-points, etc.

As a bit of background to help clarify my question, I work with several large java web applications that during any given release cycle move through 6 different environments; development, integration, QA, performance and eventually get deployed to multiple production servers. In each environment, configuration needs to change. Right now, most configuration changes for each deployment are done manually which is both time consuming and open to errors.
Is there any way to take the manual intervention out of this process?

like image 548
Dónal Boyle Avatar asked Oct 14 '09 21:10

Dónal Boyle


People also ask

What is the structure of web application in Java?

Web applications have a directory structure, which is fully accessible from a mapping to the application's document root (for example, /hello). The document root contains JSP files, HTML files, and static files such as image files. A WAR file (web archive file) contains a complete web application in compressed form.

What is web application configuration?

A configuration file (web. config) is used to manage various settings that define a website. The settings are stored in XML files that are separate from your application code. In this way you can configure settings independently from your code.

What is the deployment format for a Java web application?

Java web applications use a deployment descriptor file to determine how URLs map to servlets, which URLs require authentication, and other information. This file is named web. xml , and resides in the app's WAR under the WEB-INF/ directory.

What is web config in Java?

web. config file is an XML-based configuration file used in ASP. NET-based applications to manage various settings that are concerned with the configuration of our website. In this way, we can separate our application logic from configuration logic.


3 Answers

I'm surprised that no one cited the Jakarta Commons Configuration API (http://commons.apache.org/configuration/) to answer this question. It allows you to have a hierarchy of files (or other configuration sources like XML, JNDI, JDBC, etc.). That's what Jeremy Seghi was talking about and it gives you a good way to have both defaults and local overrides as well.

The best part is that it is a tested working solution so you don't have to go craft something yourself.

like image 198
John Munsch Avatar answered Oct 17 '22 15:10

John Munsch


I tend to work more with .NET lately, so my Java is fairly rusty. I'm pretty sure this would work in any language with a little tweaking.

We use an extension of the .NET configuration system that allows us to use environment and/or application specific settings in conjunction with a more global configuration. The configuration system uses a Global setting to each machine identifies it as dev, beta, or production (the default). A set of files loaded in order, and the setting from the last file overrides any setting that was defined in a previously loaded file. Files are loaded in the following order:

  1. Global settings
  2. Application specific settings
  3. Application specific environment overrides

All the files are in source control, and since the environment is defined on the machine the application is running on; since it won't access the "beta" configuration unless the machine configuration identifies it as "beta", we can promote all of the configuration files without fear of inadvertently pointing our production application to a dev database.

like image 15
Jeremy S Avatar answered Oct 17 '22 14:10

Jeremy S


Here are some possible practices I've used or encountered. Combining these is usually needed in practice.

Substituting the variable values in conffiles when building

Here's an example of how this can be done with Apache Ant. Ant properties (${var.name}) can be controlled with the build configuration files:

<filterset id="variables.to.replace">
    <filter token="APPNAME" value="${app.name}"/>
    <filter token="WEBAPP-PATH" value="${webapp.path}"/>
    <filter token="ENCRYPT-ALGORITHM" value="${encrypt.algorithm}"/>
    <filter token="ERROR-MAILTO" value="${error.mailTo}"/>
    <!--...-->
</filterset>

<!-- Then, when building & copying the conf, replace the variables: -->
<copy todir="${properties.target.dir}">
    <!-- env specific conf files -->
    <fileset dir="${basedir}/env/${run.env}/webapp/WEB-INF/classes" />
    <filterset refid="variables.to.replace"/>
</copy>

The good thing is that you get a fine control over the different configurations at build time. What is bad is that the system tends to grow very complex and hard to maintain if you use this method extensively for a large number of different configurations. Also, having to build the conffiles, too, means slower development cycles.

Substituting the variables from conf inside war at webapp startup

This is what I usually do when using Spring Framework, even if there is just one possble configuration, getting the benefits of the separation of concerns. With Spring, you can have the conf values replaced with PlaceholderPropertyConfigurer inside Spring context at webapp startup. In this case, you have to anyway pick the right configuration, which can be configured for example on build time.

Compared to the build time replacing, it's easier to temporarily manipulate the values in an uncompressed webapp, if needed. Of course, the webapp needs to be rebooted if you change anything, and the manual changes won't persist across webapp redeployments. Spring is also limited to the Spring context, so this doesnt' work e.g. in web.xml (but having variables in web.xml should probably be avoided anyway because of its limitations).

Reading the local conf from a pre-defined file

This approach is probably the easiest one to set up: just invent a configuration file path, e.g. $HOME/mywebapp/conf.properties and make your webapp somehow read it at startup.

The good thing here is that you don't have to care about the conf when building/deploying the webapp. Anyway, you should have some sensible conf defaults that can then be overridden by the local conf.

Having the conf in a database

This is the most flexible solution for overriding conf parameters, but can also get complicated in some cases. Having the conf in a table with name and value columns should work for the most cases.

Of course, you can't configure the JDBC connection urls in a database table, but this is a good solution for simple textual/numerical conf that affects the webapp's operation after the db connection has been set up. To avoid a performance penalty, make sure you cache the conf somehow if it will be frequently accessed.

Extra practices

As pointed out by kgiannakakis, it also helps to set up a configuration diagnosis page of some kind for your app.

like image 11
Eemeli Kantola Avatar answered Oct 17 '22 13:10

Eemeli Kantola