If you dig into the application properties (right-click on the application name in the Application navigation tree and select "Properties") and select the "Build" folder on the left side, you'll then see the "Export to Ant file" button. When you click this, it will create an "exported_build.xml" (unless that name is already used, in which case it will change the name slightly) Ant script that can be used to build the application. After you create this file, you can run "ant -f exported_build.xml" from a DOS prompt, in that directory, and you'll see it will build the application EAR file. So, all you have to do is check this file into your source-code management system and someone else can later check out the entire application and run the same command line to build the application.
Wrong. You do need to store this file in your source-code management system (fortunately it doesn't need to be changed very often), but under normal circumstances, someone else who checks out this application will not be able to build the application with the same command line, unless they either modify the build script, or they make some severe compromises with how the source-code management system is used.
The problem is that the "exported_build.xml" Ant script has two hardcoded path references that should not have been hardcoded. It hardcodes the location of the "WebLogic home" directory, and even worse, it hardcodes the original directory location the application was created in.
Hardcoding the location of "WebLogic home" isn't quite so bad. Most people always install WebLogic in "C:\bea", leaving "WebLogic home" to be "C:\bea\weblogic81". If you didn't install it there, the build won't work. There is, of course, Unix, of course. If you had any intention of building cross-platform Java applications on actual "cross platforms", then this wouldn't work for this reason, either.
Assuming the directory location where the application is stored, however, is definitely a bad assumption. Many source-code management systems will export applications to directories with names based on the user name. Any difference at all will make this fail.
Simulating the problem
To demonstrate that this problem exists, you could set up a second computer, either installing BEA in a different location, or using your source-code control system to check out the application to a different directory, but it's really easier to demonstrate this by simulating it.
If you edit the "exported_build.xml" file, you'll see the two hardcoded property values for "weblogic.home" and "app.dir". To demonstrate this problem, first run the build from a command line with "ant -f exported_build.xml". This should work fine (unless there's something wrong with your application). Now, just change the value of the "weblogic.home" property to a path that doesn't exist, and then rerun the build. This will fail quickly, because it can't find the "WlwBuildTask" class. Now change that value back, and then change the "app.dir" value to a path that doesn't exist, and then rerun the build. This will fail, because it can't find the ".work" file.
What's the solution?
Fortunately, there is a workable strategy to deal with this.
There's really two parts to this. You first have to determine a reasonable strategy to determine good values for those two properties, and then you have to build a strategy to make the script use those good values, instead of what it's using.
Getting a good value for "weblogic.home" simply means referencing the "BEA_HOME" environment variable and using that value.
The good value for "app.dir" is sort of funny. Instead of trying to figure out what the absolute path is for the application, you can just assume the build will be run from the current directory, so a perfectly good value is just ".".
The mechanics of the solution
Now that we know how to get the correct values, what's the best way to make the "exported_build.xml" script use the correct values, instead of the wrong values? The answer is just to use an XSLT stylesheet to do the conversion, and use the converted file instead of the original file. It's fortunate that Workshop creates the exported file as "exported_build.xml", and not "build.xml". This makes it easy for us to build a custom "build.xml" (that would rarely change at all between different normal Workshop applications) that runs a custom stylesheet against the "exported_build.xml" file, generating a "transformed_build.xml", and then runs the "build" (or "clean") targets against the "transformed_build.xml" file.
The custom build script would look something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<project name="workshopapp" default="build">
<property environment="env"/>
<property file="local.properties"/>
<property file="build.properties"/>
<property file="../local.properties"/>
<property file="../build.properties"/>
<!-- This task requires the environment variable "BEA_HOME" to be
set to point to the root of the BEA distribution. This is used to
fix the value of the "weblogic.home" property created in the exported
build file. -->
<target name="transform.buildscript">
<fail unless="env.BEA_HOME"
message="Your environment does not have the BEA_HOME variable
set, which is required."/>
<xslt in="exported_build.xml" out="transformed_build.xml"
extension="xml"
style="${transformExportedBuild.xsl}" force="true">
<param name="beaHome" expression="${env.BEA_HOME}"/>
</xslt>
</target>
<target name="build" depends="transform.buildscript">
<ant antfile="transformed_build.xml" target="build"/>
</target>
<target name="clean" depends="transform.buildscript">
<ant antfile="transformed_build.xml" target="clean"/>
<delete file="transformed_build.xml"/>
</target>
</project>
See how the "build" and "clean" targets depend on the "transform.buildscript" target. This target uses the "xslt" task to run the transformation, generating the "transformed_build.xml" file.
The custom stylesheet looks something like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- Parameter for BEA_HOME. This is used to compute the value of
the "weblogic.home" property. -->
<xsl:param name="beaHome">.</xsl:param>
<!-- Everything that isn't specifically matched should pass through. -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/project">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>
</xsl:text>
<property file="local.properties"/>
<property file="build.properties"/>
<property file="../local.properties"/>
<property file="../build.properties"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- This fixes the value of the "weblogic.home" property, which
was hardcoded to the value used when the build file was exported,
which may not be the same for another developer. The new value is
based on the input xsl parameter, which should be the value of the
BEA_HOME environment variable. -->
<xsl:template match="//property[@name='weblogic.home']">
<xsl:copy>
<xsl:attribute name="name">weblogic.home</xsl:attribute>
<!-- We have to make sure the resulting value uses all
forward slashes, so we pass the value through a "translate" call. -->
<xsl:attribute name="value"><xsl:value-of
select="translate($beaHome, '\', '/')"/>/weblogic81</xsl:attribute>
</xsl:copy>
</xsl:template>
<!-- This fixes the value of the "app.dir" property, which was
hardcoded to the absolute path of the project when the build file was
exported, which may not be the same for another developer. In any
case, the value really only needs to be set to ".", as the build
will be run from this directory. -->
<xsl:template match="//property[@name='app.dir']">
<xsl:copy>
<xsl:attribute name="name">app.dir</xsl:attribute>
<xsl:attribute name="value">.</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The key is the two templates whose XPath values specify the "weblogic.home" and "app.dir" properties, and replaces the values with the correct values.
With these changes, not only does the build work, but you can instead run "ant" instead of "ant -f exported_build.xml".