|
|
YOUR FEEDBACK
SOA World Conference
Virtualization Conference $200 Savings Expire May 16, 2008... – Register Today! Did you read today's front page stories & breaking news?
SYS-CON.TV |
TOP THREE LINKS YOU MUST CLICK ON Application Management
Managing Environment-Specific Properties
Proven solutions for software promotion
By: Jason Newman; Dave Jones
Digg This!
WebSphere applications often rely on property files to contain environment-specific values. These files usually contain any settings that change between environments, and the files can be in a variety of formats Java properties (key/value pairs), XML, or a custom format. Many values can be kept the same throughout the environments, but values such as host names, user IDs and passwords, database schema names, and URLs usually change in each. We see many of our customers struggling with the problem of how to manage the changes in application property files as the application gets promoted through a number of different environments, such as development, testing, and production. This article will outline some of the more common and proven solutions. While none of these solutions will always be the best for all situations, it is likely that one of the solutions presented here will fit your needs. Roles and Responsibilities Previously many customers tended to manage all of the property files externally to the application, often deploying and updating these files by hand. Now it's more common for development teams to create property files for each environment and package them all into the EAR file building their applications to use a cue from each runtime environment to indicate which properties are to be used in that environment. We have found that roles and responsibilities generally have the largest impact on which of these solutions work best within an individual organization. Options How to Load Them? The following copy task shows how you can use Ant to replace all property files that end in a specific extension (such as ".dev", or ".stage") to another directory while removing the extension. The extension to replace is specified by the property ${env}, and could be passed into Ant when the build is invoked. The <mapper> element is the key to the copy command to perform the replacement. This method is useful when your property files vary greatly between different environments, such as log4j.property files, which generally contain entirely different logging strategies and configurations in production than development.
<copy todir="${destdir}"
overwrite="true">
<fileset dir="${srcdir}"
includes="**/*.${env}"/>
<mapper type="glob"
from="*.${env}" to="*"/>
</copy>
You may also want to first copy all files except those ending in any of the environment-specific endings, so that any property files that don't require an environment-specific ending are picked up.
<copy todir="${destdir}">
<fileset dir="${srcdir}">
<exclude name="**/*.
dev"/>
<exclude name="**/*.
stage"/>
<exclude name="**/*.
prod"/>
</fileset>
</copy>
An alternate method is to replace tokens among all property files that would specify environment-specific values. This method is more useful if you have just a few substitutions to make in many different files. The <replace> task accepts a file (replacefilterfile) which contains a lists of tokens and the values to substitute. Again, if the ${env} property is set to "DEV" when invoking Ant, the following example would replace the tokens specified in the replace.properties.DEV in all of the .property and .xml files, such as "sample.properties". build.xml:
<replace dir="${build.dir}/properties"
replacefilterfile="replace.properties.${env}">
<include name="**/*.properties"/>
<include name="**/*.xml"/>
</replace>
replace.properties.DEV: @@SERVER_NAME@@=mydevserver sample.properties: connect.url=@@SERVER_NAME@@ These two techniques could be used together if your application contains property files that fit into both categories. In this case, the file copy method should be used first to move the files into a build directory, and then the replace task applied to substitute tokens within those files. The disadvantage of this process is that unique EAR files need to be built for each environment. This could conflict with your organization's policies on configuration management, which likely require the EAR file to be locked after successful testing. Alternatively, since some organizations build fresh for each environment from frozen source, this technique might work well. At Runtime Using Resource Bundles The variant is set by passing the "-Duser.variant" property on the JVM command line. This can be set on a server instance from the WebSphere admin console. The argument is added on the Application Server's -> <servername> -> Process Definition page under the field labeled Generic JVM arguments (see Figure 1). Once set for a server, the following code can be used to load an environment specific property file.
ResourceBundle rb =
ResourceBundle.getBundle("myproperties");
String url =
rb.getString("connect.url");
On a server installed on a machine set to the use the English language and US locale, the ResourceBundle will first look for a file named: myproperties_en_US_dev.properties and will then move up the filename, until it will finally try to load a file called: myproperties.properties The downside to this approach is that it can be confusing to mix language/location strategies with environment determinations. It can also potentially conflict with third-party utilities that use the variant to further delineate the locale of the runtime environment. At Runtime Using JNDI Resource Environment References These references are referred to as Resource Environment References, and are specified with the <resource-env-ref> tag in the Web or EJB deployment descriptors. If you wish to use these references with the WSAD test environment, a WebSphere binding must be specified in the Deployment Descriptor wizard, and the appropriate binding defined in your local test server. Unfortunately, there is no place in the WSAD Test Server Configuration wizard to set these references. You must use the administration console to create the namespace bindings for both WAS and the WSAD test environment. The binding can be set from Environment >Naming >Name Space Bindings page (see Figure 3). Be aware of the scope on which you set the environment references. Although you may want to set a reference on a cell basis, to cover all the machines in a cluster you will need to point the binding to the correct place (namely, "cells/persistent/<x>"), whereas server-scoped namespace bindings will appear right in the root. Looking up the references is no differen t than looking up any local environment reference:
Context ctx = new
InitialContext();
String propFile = (String)ctx.
lookup("java:comp/env/url/
properties");
If you want to comply with the J2EE specifications, once you have obtained the reference it should be read via the java.net.URL class instead using direct file IO.
URL propFileURL = new
URL(propFile);
InputStream in = propFileURL.open
Stream();
At Runtime Using a Custom Property Manager
Thread.currentThread().getCon
textClassLoader().getResour
ceAsStream();
WebSphere ensures that the context classloader is set appropriately before each call into your application. Where to Put Them External to the EAR File The major disadvantage of having any application resources external to the EAR is that there will be additional packaging and deployment steps since all assets are not a part of the EAR. On the other hand, in environments where environment-specific values are closely managed and guarded by Operations this approach could be beneficial. The development team would define what the property file should look like, as well as how it should be accessed (e.g., direct file system access or via classpath), and the Operations group would create and place the file accordingly. This method works best with the JNDI Resource References, as the administrators can bind the location of the files at deployment time while the application code can utilize J2EE compliant loading by using the URL class instead of direct java.io package loading. Using a Properties JAR File An important step to remember is to add the property JAR to the manifest classpath of any component that will be accessing the properties. This approach accomplishes two common major goals of having the EAR self-contained and being a fully J2EE-compliant implementation. Properties Files in Root of the EAR This solution could be considered "not fully J2EE compliant." It relies on a feature that is recommended, but not mandated by J2EE. The following excerpt from section 8.1.1.2 of the J2EE 1.3 specification explains this recommendation: J2EE products need not support this mechanism for reference to classes or resources that are not in .jar files included in the .ear file. However, support for such usage is encouraged. Applications are encouraged to make use of such support only when necessary and where available, although currently such usage is non-portable. WebSphere has implemented this functionality since version 4.0.x, however, since J2EE has not mandated it, IBM could withdraw this functionality at any time.
The "../<NameOfEarProject/properties" entry is for execution within the WSAD test environment. If you not using the WSAD test environment, this entry in the manifest can be excluded. This tells the classloader to look up one directory (to the workspace root) and in the <NameOfEarProject> directory (the folder for the EAR project). This has to be done because WSAD treats all projects/modules as being at the same level in the hierarchy. In other words, WSAD does not treat the modules and JARs as though the EAR project contains them. The "properties" entry is for runtime in WebSphere Application Server. In WAS, the EAR is the top level with respect to the modules' classpaths, and each module is one level deeper. The modules are extracted to the disk in the same hierarchy in which they are stored within the EAR file. There should be no adverse effect of having both entries in the classpath permanently. A conflict could occur in WSAD if there were a "properties" directory in the module itself (unlikely). A conflict in WebSphere Application Server would occur if "../<NameOfEarProject/etc" existed relative to the installed location of the EAR (extremely unlikely). Either of these scenarios would only occur if it were created intentionally. As you may have observed, problems may occur when reusing the component with the reference to the properties directory. In WSAD, the manifest will reference a directory name that contains the name of the EAR project. This will be a problem when the module needs to be reused in multiple EARs. Pick Your Location Carefully As you can see, there is a variety of approaches for managing environment-specific properties. Most of the companies that use WebSphere are using one of the options mentioned in this article, or a slight variation of one of them. It is nearly impossible to say that one method is always desirable over the others; hopefully this article presented the information in such a way that you can choose the approach that works best for your organization.
WEBSPHERE LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING WEBSPHERE NEWS
|
||||||||||||||||||||||||||||||||||||||