Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

JVM Languages

Configuring J2EE Deployment Descriptors


Tip #3: Modify the Development Version of the EAR or WAR File

The final suggestion for assembling your EARs and WARs starts with the developer's version of the EAR or WAR along with an exported spreadsheet. You need to write a script that unJARs the EAR or WAR, taking out the files you need to modify, update them based on the spreadsheet data, and put them back by reassembling the EAR or WAR file.

You can extract individual files from the WAR or EAR files with a command-line JAR program or the Ant unJAR task. Remember, you can't extract a file inside of an archive that is inside another archive. For example, you can't directly extract a web.xml file inside a WAR file that is archived in an EAR file. First, you will extract all of the contents of the EAR file and then operate on each archive in turn. The ZIP file analogy was oversimplified: You are actually operating on ZIP files within ZIP files.

File types that often need to be updated for each environment include:

  • XML files. Many tools are available for manipulating XML. XPath lets you target elements and attributes to change without the need for parameterizing the XML by adding tokens. There are excellent Ant tasks (XMLTask) and Perl modules (XML:XPath) that provide this functionality; see Listing One.
  • Properties files. These common files are defined by the java.util.Properties class and are basically simple lists of name-value pairs in a file. Ant is great for reading properties files, but has limited facility for regenerating them. The standard Ant tasks prefer the files to be parameterized ahead of time. You can also write a simple Java program for more sophistication, or if you are comfortable with Perl, it can be as easy as processing a simple hash, or sophistication can be added using Perl's powerful regular expressions.
  • Other text files. As much as we try for standardization, some radical open-source group or upstart company is bound to throw in some oddly formatted files you can't do without. You may have to parameterize these files so that Ant can filter them or use Perl regular expressions.
  • Gotcha files. There may be files that simply can't be processed and must be used as is. These can be binary or license files required by third-party components. For Ant, the typical way to handle them is to set a property value indicating the location of the file to use for the current instance that you are building. For build tools such as Openmake, you simply set the search path to point to the file to use.

Listing One, update_deployment.pl, is Perl code that calls to the Ant XMLTask Replace and Insert tasks used to perform the updating of your deployment descriptors. Listing Two is a CSV input file that is similar to your spreadsheet export. Listing Three (available electronically; see "Resource Center," page 5) is a deployment descriptor that's updated by running update_deployment.pl. Listing Four (also available electronically) is the result of the deployment descriptor after executing the update_deployment.pl script. This example code does not include extracting or rearchiving the deployment descriptor files from the WAR or EAR. I've given you the hard code, extracting using JAR or unZIP is the easy step.


# This sample code shows how to use a CSV file to update deployment descriptor 
# configuration data. It generates an Ant build.xml file that uses the xmltask
# replace and xmltask insert to perform the updating of the configuration data
# within the deployment descriptors. 
#Usage: update_deployment.pl <CSV File> <Deployment Descriptor XML File>
#Author: Steve Taylor, Catalyst Systems Corporation 

################################
# Read the CSV file into a list
################################
open(FP,$ARGV[0]);
@lines = <FP>;
close(FP);

################################
# Remove Header Line
################################
shift @lines; 

#############################################################
# Initialize output list with xmltask input and output files
#############################################################
push @xmltask,"<xmltask source=\"$ARGV[1]\" dest=\"updated_$ARGV[1]\" 
                                                  preserveType=\"true\">\n";

#########################################
# Loop through the lines in the CSV file
#########################################
foreach $line (@lines)
{
 $line =~ s/\n//g;

 ###############################
 # Split the CVS into parts
 ###############################
 ($env,$instance,$archive,$file,$xpath,$value) = split(/,/,$line);
 
 ($action,@x) = split(/ /,$xpath);
 $xpath = join(" ",@x);
 
######################### ###############################
 # Write ANT Xml for xmltask insert based up on CSV data 
 ########################################################
 if ($action =~ /Insert/i)
 {
  push @xmltask, '       <insert  path="' . $xpath . '" 
                                                 position="after"' . ">\n";
  push @xmltask, '          <![CDATA[' . $value . "]]>\n";
  push @xmltask, "       </insert>\n";
 }
 
 #########################################################
 # Write ANT Xml for xmltask replace based up on CSV data 
 #########################################################
 if ($action =~ /Replace/i)
 {
  push @xmltask, '       <replace path="' . $xpath . '" 
                                            withText="' . $value . "\"/>\n";
 }
}

###############################
# Close xmltask tag 
###############################
push @xmltask, "     </xmltask>";

###############################
# Fill Out build.xml
###############################
$build_xml =<<ENDXML;

<project name="Deployment Update" default="update" basedir=".">
 <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
   <target name="update">
     @xmltask
   </target>
</project>
ENDXML

#############################################
# Write out the actual build.xml to the file 
#############################################
open(FP,">build.xml");
print FP $build_xml;
close(FP);

###############################
# Run Ant
###############################
print `perl -S runant.pl 2>&1`;
Listing One


Env,Instance,Archive,File,Xpath,Value
Production,DB1,Minibank.war,application.xml,
    Replace /application/module/web/context-root/text(),banking/MinibankWEB
Production,DB1,Minibank.war,application.xml,
    Insert /application/module/web,<description>Production 
                                  context root for MinibankWEB</description>
Listing Three
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE 
  // Application 1.2//EN" "http://java.sun.com/j2ee/dtds/application_1_2.dtd">
<application id="Application_ID">
      <display-name>MinibankEAR</display-name>
      <description>Minibank Example Enterprise Application</description>
      <module id="EjbModule_1">
        <ejb>MinibankEJB.jar</ejb>
      </module>
      <module id="WebModule_1">
        <web>
            <web-uri>MinibankWEB.war</web-uri>
            <context-root>MinibankWEB</context-root>
</web>
      </module>
   </application>
Listing Four
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE 
  // Application 1.2//EN" "http://java.sun.com/j2ee/dtds/application_1_2.dtd">
<application id="Application_ID">
      <display-name>MinibankEAR</display-name>
      <description>Minibank Example Enterprise Application</description>
      <module id="EjbModule_1">
        <ejb>MinibankEJB.jar</ejb>
      </module>
      <module id="WebModule_1">
        <web>
            <web-uri>MinibankWEB.war</web-uri>
            <context-root>banking/MinibankWEB</context-root>
</web>
<description>Prodution context root for MinibankWEB</description>
      </module>
   </application>
Listing Two

Now that you've extracted and modified the files, the last step is to put them back in the EAR or WAR. Be extremely organized about which files are source files and which are the modified files. It is important to clearly separate files that are used as source and files that are modified for rearchiving. After rearchiving the new EAR or WAR file, you are ready to repeat the process for the next one.

Conclusion

Don't procrastinate when defining your process for configuring your deployment descriptors—it only causes more problems. If you follow the guidelines I've presented and review your server architecture early on, you will save yourself from deploying a perfectly good EAR or WAR to production, when they were configured for development. And remember, don't start parameterizing everything early on. This may look like the easiest road, but it becomes the hardest road as your application matures and moves to different environments. J2EE development will take you where you need to go. Just make sure you don't put up any road blocks that will prevent your J2EE application from all it can be.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.