Java Web Application Configuration Templates

Are there any templates or guidelines that can be used to simplify changing configuration profiles for Java web applications in different environments. e.g. JDBC URLs, SOAP endpoints, etc.

As a little background to help clarify my question, I work with several large Java web applications that move in 6 different environments during any given release cycle; development, integration, QA, performance, and ultimately deployed across multiple production servers. In each environment, a configuration change is required. Currently, most configuration changes for each deployment are manual, which is both time-consuming and error-prone.
Is there any way to accept manual intervention from this process?

+58
java design-patterns web-applications configuration
Oct. 14 '09 at 21:02
source share
10 answers

I have been working with .NET more often lately, so my Java is pretty rusty. I am sure that this will work in any language with a little customization.

We use the extension of the .NET configuration system, which allows us to use the settings of the environment and / or applications in combination with a more global configuration. The configuration system uses a global setting for each machine, which identifies it as dev, beta or production (default). A set of files loaded in order, and the parameter from the last file overrides any parameters defined in the previously loaded file. Files are downloaded in the following order:

  • Global settings
  • Application Specific Parameters
  • overrides the application environment.

All files are in the source control, and since the environment is defined on the computer, the application works; since it will not gain access to the beta configuration, if the machine’s configuration does not identify it as beta, we can promote all configuration files without fear of unintentionally pointing our production application to the dev database.

+14
Oct 26 '09 at 22:06
source share

I am surprised that no one has quoted the Japarta Commons Configuration API ( http://commons.apache.org/configuration/ ) to answer this question. This allows you to have a hierarchy of files (or other configuration sources such as XML, JNDI, JDBC, etc.). This is what Jeremy Segi was talking about, and it gives you a good way to have both defaults and local overrides.

The best part is that this is a proven working solution, so you do not need to do something yourself.

+31
Oct 28 '09 at 18:22
source share

Here are some possible practices that I have used or encountered. Their combination is usually necessary in practice.

Substituting variable values ​​in conffiles when building

Here is an example of how this can be done with Apache Ant. Ant properties ( ${var.name} ) can be controlled using 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> 

It's good that you get great control over the various configurations during build. The bad news is that the system tends to grow very difficult and difficult to maintain if you use this method extensively for a large number of different configurations. In addition, the need to create conffiles also means slower development cycles.

Variable substitution from conf inside war when launching webapp

This is what I usually do when using the Spring Framework, even if there is only one configuration to consider, taking advantage of the separation of concerns. With Spring, you can replace conf values ​​with PlaceholderPropertyConfigurer inside the Spring context when running webapp. In this case, you should at any time choose the correct configuration that you can configure, for example, during assembly.

Compared to replacing build time, it is easier to temporarily manipulate values ​​in uncompressed webapp if necessary. Of course, webapp needs to be reloaded if you change something, and manual changes will not be saved when the webapp is redistributed. Spring is also limited by the Spring context, so this does not work, for example. in web.xml (but with variables in web.xml, probably should be avoided due to its limitations).

Reading local conf from a predefined file

This approach is probably the easiest to configure: just come up with a path to the configuration file, for example. $HOME/mywebapp/conf.properties and make your webapp somehow read at startup.

Good thing you don't have to worry about conf when creating / deploying webapp. In any case, you should have reasonable conf settings, which can then be overridden by local conf.

The presence of conf in the database

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

Of course, you cannot configure the JDBC connection URLs in the database table, but this is a good solution for plain text / numeric conf, which affects the operation of webapp after the db connection has been configured. To avoid a performance penalty, make sure you cache the config in some way, if it is often available.

Additional practices

As indicated by kgiannakakis, it also helps to customize the configuration page for your application.

+11
Oct 26 '09 at 12:05
source share

It depends on what options the web application servers provide you with. We have several environments for JBoss with different JDBC URLs, the JNDI name remains unchanged on all servers, only the configuration of local changes to the instance, so nothing comes from the assembly for the assembly.

I assume the short answer is that it is best practice to externalize the configurations and keep a good file with the correct settings for each server, and the web application should read this configuration. The exact nature of externalization and reading will depend on the specific configuration and application server.

EDIT: These configurations do not exist as part of the war (rumor in our case), so they are not overwritten.

+6
Oct 14 '09 at 21:23
source share

First you have all the configuration settings that often change in one place. This is very difficult if you need to configure JNDI, edit the database values ​​and modify the properties files, all at the same time to complete the setup. Prefer the environment that is easiest to edit and also the easiest to verify that everything is configured correctly. I would say that property files are the best solution. You can easily edit them, and you only need to quickly look through them to see that everything is in order. If you select property files, carefully select a standard location for them and assign an environment variable for the path.

It also helps if you have a simple test that checks that everything is configured correctly. For example, you might have a test page that displays configuration settings and performs some basic tests, such as trying to connect to a database or remote servers.

+2
Oct 26 '09 at 9:08
source share

A good example of what you want is used in Seam or Grails (borrowed from Rails). There are profiles, three by default: prod, dev, test, but you can define more if you want.

In the assembly of the Seam project, the Ant file is executed. An Eeach file whose contents may change is defined for each profile, for example. datasource, sql scripts or property files.

import-dev.sql
import-prod.sql
import-test.sql

When the Ant file is launched with the selected profile, the corresponding file is executed, and the profile name is truncated from this file name.

Below is a snippet of code that you can place for your purposes.

 <copy tofile="${war.dir}/WEB-INF/classes/import.sql" file="${basedir}/resources/import-${profile}.sql"/> 

JDBC URL, driver names can be externalized in property files (of course, with profile names as suffixes)

 <filterset id="persistence"> <filter token="transactionManagerLookupClass" value="${transactionManagerLookupClass}"/> <copy tofile="${war.dir}/WEB-INF/classes/META-INF/persistence.xml" file="${basedir}/resources/META-INF/persistence-${profile}.xml"> <filterset refid="persistence"/> </copy> 

or property values ​​that you can pass to Ant to invoke the assembly from the command line. This is a short example of what is done at Seam.

Another option is to use Maven . In the maven way, this is done by properties and profiles , but you can also use separate modules to separate the configuration and create other modules with the main functionality. Typical examples of using maven properties and profiles are performed for several databases, deployment servers, etc. Even harder if you want to create a configuration for different providers, but for Maven this is not a problem :)

A great example of using maven profiles is this Carlos Sanchez blog post form.

To summarize, I highly recommend looking for Ant / Seam an Maven parametrization (profiles). These solutions have one more advantage: Ant or maven script can be executed on a CI server (for example, Hudson ) and run / check all your profiles at the same time.

+1
Oct 28 '09 at 9:24
source share

You can use the component configuration template in your language of choice

This is described in POSA books (I think in volume 4)

(in java you can use commons-configuration component).

+1
May 01 '13 at 19:27
source share

There are several possible ways to approach this:

  • use properties files like you, but add the “meta properties” file, which is used to select the properties file used to define the map between the environment value (for example, localhost hostname) in the name of the load property file.

  • put your properties in the database and define the connection of the database to the property tables on the application server as the resource that is picked up by your web application.

  • do not put property files in your .war or .ear, but create properties-deploymenthost.jar archives containing property files on the target host. attach the corresponding .jar file to the deployed web application by adding it to the class path (for example, through shared libraries in the application server configuration for each web application.)

Only the first of them does not require additional manual steps during deployment due to the need to update the configuration source and create new deployment files when renaming target systems.

I am sure that many options for these and your approaches are possible, the best choice depends on your situation.

0
Oct 26 '09 at 21:27
source share

What we do works very well.

At startup, our programs read the configuration file in a hard-coded path. So to speak:

 /config/fun_prog/config.xml 

Each program has a different hard coded path (FunProgram is in fun_prog, Super Server is in sup_serv, whatever), so we don’t need to worry that they go one above the other.

XML files are read by the small configuration library we created. An XML file contains information about connecting to the database, usually the configuration data of the mail server, email addresses for sending notifications, whether it should work in test mode, URLs of external services, etc.

So, when we need to make changes, we will copy the configuration file, edit what we want, and restart the program. Since we have a standard server setup, any program can be deployed to any server simply by copying these files (and the required httpd.conf interception).

This is not a fantasy, but it works very well. It is very easy to understand, add new configuration options, back up and edit. It works on all platforms (unix is ​​obvious, Windows translates paths starting from / to c: \, so it works without editing there either).

Our workstations basically run the same software as the server, with only minor changes to this configuration file.

0
Oct 26 '09 at 21:39
source share

Please take a look at this URL: http://issues.apache.org/jira/browse/CONFIGURATION-394

The configuration structure we are looking for is something on top of the Apache Commons configuration and should support Concurrency problems, JMX problems, and most stores (for example, the .properties file, .xml files, or PreferencesAPI).

What the weblogic team offers in the Administration Console, through which you can receive transactional (atomic) updates in configurations so that registered registered listeners are notified.

The Apache guys insist that this project is beyond the scope of the Commons Configuration, perhaps!

I attached a simple configuration structure, please see.

0
Sep 10 '10 at 20:35
source share



All Articles