中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Java > Java与XML
Managing Environment-Specific Properties @ JDJ
作者:未知 时间:2005-08-10 18:37 出处:Java频道 责编:chinaitpower
              摘要:Managing Environment-Specific Properties @ JDJ

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
In a perfect world, groups within an organization would map nicely to the roles and responsibilities defined by J2EE. In reality, a disproportionate amount of the responsibilities fall within the realm of development. We find this especially true for property files where Operations' only responsibility may be to change a password, and development creates and maintains all of the remaining properties.

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
We have seen environment-specific properties managed in a number of ways; many of them are outlined in Table 1.

How to Load Them?
At Build Time Using Ant

There are two common strategies for replacing environment-specific information at build time; (1) replacing the entire file with files marked for each environment, or (2) replacing tokens in all property files from an environment-specific name/value pair. Both of these techniques can easily be done using Ant.

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
@@USER_NAME@@=devuser

sample.properties:

connect.url=@@SERVER_NAME@@
connect.username=@@USER_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
Java provides a simple, out-of-the-box solution which can be exploited to easily load the correct files dynamically at runtime. By setting a "variant" on the WebSphere Application Server instance, the ResourceBundle class will load the appropriate property file with no additional configuration necessary short of naming your property files correctly. The ResourceBundle class should load the correct property file as long as the language and locale on your servers matches what you have named the file.

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
JNDI can also be used to store environment-specific information, and can be referenced by your application through local references just as EJBs or DataSources are. These bindings can be used to provide specific string values, or URL references to property files containing environment-specific information located on the server (see Figure 2).

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
Writing your own custom code to load environment-specific properties has some advantages, such as the ability to include logging or dynamic reloading on file change, but there are a few things to keep in mind if you roll your own:

  • Beware of classpath isolations. Chances are you are going to want to read in those property files off the classpath, and not directly off the filesystem. Because of the way WebSphere 5.x uses multiple classloaders for different parts of your application, it is important that you use the correct classloader for the job. If you place this property manager code in a utility JAR, you probably don't want to use the classloader that loaded the property manager. Instead, you would want to use the classloader of the component that called the property manager. A good way to do this is to use the context classloader:

    
    Thread.currentThread().getCon
        textClassLoader().getResour
        ceAsStream();
    

    WebSphere ensures that the context classloader is set appropriately before each call into your application.

  • Consider building hierarchical property file searches (like ResourceBundle). Instead of just appending a single environment token on to the end of any property file searches, consider building your search to navigate up a sequence of extensions, ending with no extensions. This will allow developers to scope their property files as necessary. A simple example would be if your custom property manager is asked to load "myprops.properties" while running in the production environment, it first looks for "myprops.properties.prod" and then "myprops.properties." In a clustered environment, you may want to indicate a specific server in a cluster, along with the environment type itself, such as "myprops.properties.prod.pdserver1."

    Where to Put Them
    A common problem in J2EE applications is deciding on where to place properties files. There are three main options, which will be discussed briefly here. Once one of these options is chosen, then an appropriate access method will need to be selected (see Table 2).

    External to the EAR File
    Most early J2EE applications accessed property files that were external to the EAR. This was mainly due to ease of implementation.

    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
    If you are not worried about easily editing the property files on the WebSphere servers themselves after deployment, the easiest way to bundle property files on the classpath is to create a properties JAR file and add it to your application's EAR.

    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
    Some WebSphere shops have the requirement that properties be packaged in the EAR, yet also be accessible without having to extract them from a JAR. They do this to allow for easy checking or changing of the properties. This solution relies on the classloader's ability to search through non-JAR resources in 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.

    1. Create a directory named "properties" in the root of the EAR project. This directory will be even with the META-INF directory.
    2. Place all properties files in this "properties" directory.
    3. Write code to access the properties file. This would normally be done with

      
      Thread.currentThread().getContext
        ClassLoader().getResourceAs
          Stream(propFileName);
      

      This code should normally be placed in a utility JAR that can be referenced by all other modules of the enterprise application.

    4. For each module that will access the properties file, make the following changes to the MANIFEST.MF file:

      
               Manifest-Version: 1.0
               Class-Path:../<NameOfEarProject/
          properties properties
      
    WSAD will show errors on the EAR project due to the entries in the manifest, but the errors can be ignored. There are two entries in the manifest file because WSAD loads code from the workspace differently than WebSphere Application Server loads it at runtime.

    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
    Not all property file locations will work with all methods to load properties. Table 3 indicates which methods can work together.

    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.

  • 关闭本页
     
    首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
    Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有