Can I use a single war file in multiple environments? Do I need to?

I have a Java web application at my work, and I would like to simplify how we deploy our DEV, QA, and PROD environments.

The application launches a number of properties at startup, and the properties files are different for dev, qa, and prod. Whenever I want to deploy to a specific environment, I drop the environment-specific properties file into my application folder, build a war and then deploy it to one of the three tomcat 5.5 servers.

What I would like to do is to have one .war that has properties for all environments, and ask the application to poll the web server during the init process to find out which environment the application is in, and therefore which properties to load . Is there an easy way (or, if not, a standard way) to do this?

+27
java java-ee jsp
Oct 28 '09 at 0:13
source share
7 answers

It really depends on what you use these properties for.

Some (for example, a data source, for example) can be configured in the container itself ( Tomcat 5.5. JNDI resources , see the JDBC sources section as a).

The other (application-specific) may indeed be properties. In this case, your options are:

  • Package properties in the WAR file and loading the corresponding subset based on some external switch (either an environment variable or a JVM property).
  • Configure the deployment process on each of the servers on which the war is unpacked, and the properties file (located in a predefined location on this server and specific to this server) is copied to WEB-INF/classes (or another suitable place).

As far as "this is the desired goal" goes - yes, I think so. Having one WAR for testing in a QA / statement and then deploying to production reduces the intermediate step and thus leaves less chance of errors.

Update (based on comment):

Point # 1 above refers to the actual environment variable (for example, something that you set via SET ENV_NAME=QA on Windows or ENV_NAME=QA; export ENV_NAME on Linux). You can read its value from your code using System.getenv() and load the appropriate properties file:

 String targetEnvironment = System.getenv("TARGET_ENV"); String resourceFileName = "/WEB-INF/configuration-" + targetEnvironment + ".properties"; InputStream is = getServletContext().getResourceAsStream(resourceFileName); Properties configuration = new Properties(); configuration.load(is); 

But yes, you can instead define a scalar value via JNDI ( see Environment Records in the Tomcat Document ):

 <Context ...> <Environment name="TARGET_ENV" value="DEV" type="java.lang.String" override="false"/> </Context> 

and read it in your application through

 Context context = (Context) InitialContext().lookup("java:comp/env"); String targetEnvironment = (String) context.lookup("TARGET_ENV"); // the rest is the same as above 

The fact is that if you still use JNDI, you can also abandon your properties files and configure everything through JNDI. Your data sources will be available to you, since the actual resources and basic properties will remain scalars (although they will be type safe).

Ultimately, you decide which path is best for your specific needs; both have pros and cons.

+17
Oct 28 '09 at 0:34
source share

What you are doing is an accident that must happen ... One day, the DEV war will end on the PROD server, and according to a law that exceeds all the laws of nature, the problem will be detected on 2AM. I can’t explain why this is so, but someday it will happen. Therefore, one war, in my opinion, is definitely a good idea.

You can set the system property in the corresponding JVM (-Dcom.yourdomain.configpath = / where / you / store / configfiles) and retrieve this property using

 String value = System.getProperty("com.yourdomain.configpath", "defaultvalue_if_any"); 

The default value may indicate what is inside the war (WEB-INF / ...), or if there is no default value, you can use it to make some recording noise during boot a warning about incorrect configuration). Also note that this method is platform independent, so you can be a Windows machine and a Linux server, it can handle both. Usually we create a subdir for each application in this configpath, since several applications use this system on the server, and we want to keep things in order.

As an added bonus, you do not run the risk of manually uploading manually modified property files to the PROD server. Just remember to specify the path where the files are stored in the backup script.

+6
Oct 28 '09 at 0:35
source share

I think one war file is a good way, because it's nice to have confidence that the binary you tested in DEV is exactly the same as in Production. As we do this, we save the configurations in a separate property file outside of the war, but on the way to the application server.

If you want to save all the properties inside the war (which simplifies the deployment, because then you do not need to deploy the property file as well), you can save one property file in the class path that identifies the server as the medium type and use this for key values ​​in the property file in your .war file. An external properties file can also be a good way, perhaps for some high-level configurations that change little and are used in many military files.

+4
Oct 28 '09 at 0:35
source share

Probably the easiest way would be to set an environment variable that is different between the application services and use it to determine the property file to read.

Another possibility is to save the properties in the database and use a data source that exists under the standard name JNDI, but points to a different place in different environments.

+1
Oct 28 '09 at 0:35
source share

I prefer one EAR approach or one WAR. There is something that is once again confirmed and often required from a security point of view to accept the same EAR that has just been tested and transfer it directly to the next state (test> Production).

There are also many options besides the properties files provided by the container. Often a container has a good user interface to support these values ​​and resources when you are dead and gone.

There are many examples of using the ResourceBundle database.

For example, there are several mechanisms in the Spring framework to do this effortlessly. Starting with PropertyPlaceholderConfigurer

+1
Oct 28 '09 at 0:41
source share

Set Systemproperty at startup, which points to the location of your properties file, and then insert this property in your application and load your settings. Another thing is that I have two properties files, for example, default.properties and external.properties. They contain the same properties, but default.properties contains a default value (most time settings work), this file goes into war. Then, if you deploy to env. you are looking for external .properties, if found, which is used, if not, then you roll back the default.properties file. This provides a good way to override properties if necessary, but also has a default setting. This works in many of my deployments, but may not be in your scenario.

+1
Oct 28 '09 at 1:26
source share

Absolutely one WAR is the best way to go. Define resources using the same JNDI names in each environment, and if you need to determine which environment you work for business logic in, use the System property when starting Tomcat.

0
Oct 28 '09 at 0:39
source share



All Articles