Arch2Arch Tab BEA.com
Syndicate this blog (XML)

Making the exported Workshop build script automatically portable

Bookmark Blog Post

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit

David Karr's Blog | September 10, 2005   7:42 PM | Comments (1)


If your Workshop application needs to be built by a background process, or from the command line, for some reason, then you can select the option in Workshop to export to a build script (which is a little hidden in the application options). With this, you can then build your application from the command line. However, if you check this application into a source-code control system and then have someone else check it out to a different location and a different environment, and then try to build it, your application may fail to build. This is because the default "exported_build.xml" file hardcodes the absolute path to the root of the WebLogic distribution, and even worse, it hardcodes an absolute path to the root directory of your application. Unless you specify "policies" that say everyone has to install WebLogic in the same drive path, and everyone uses the same path to check out applications to, then this just won't work. I will describe here how you can augment the automated build process to transparently "fix" this problem.

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".


Comments

Comments are listed in date ascending order (oldest first) | Post Comment

  • Translets "are precompiled XSL documents that are optimized and converted into simple Java classes. When you compile your application Java files, you compile your XSL files into Java class files. During runtime, you can load translets like any regular Java class and perform XSL transformations over and over again. The syntax checking and parsing of XSL documents are done when the XSL files are compiled. The transformation therefore takes only as long as the compiled code takes to execute, which improves performance multiple folds. The downside to using XSL is that "it can take a considerable amount of time and reduce performance. The time needed to parse XML and XSL documents is directly proportional to the size of the documents. Each transformation requires the XML and XSL documents to be loaded, syntax checked, and parsed." I recommends using translets for the following reasons. I had written an application (SimplyGites) using standard XSL / XML transformation and experienced some very slow server-side transformation on the very complex screens with large amounts of xml. Timings showed these problem screens took 2-3 seconds to transform, which was totally unacceptable non-functional requirements. I considered rewriting these screens as JSP or PHP, then I discovered Translets. And wow what a discovery the timings for these pages now compiled as Translets(java classes) are amazing in comparison to the original timings ? I now have them transforming in 500ms (all now under 1 second). I would recommend anyone using XSL/XML transformation to use Translets, these have now been running tried and tested on the SimplyGites for the past 6months. Technolgies used: Weblogic 8.1 SP5 Java 1.4.2 Required Jars xsltc.jar runtime.jar BCEL.jar JLex.jar java_cup.jar regexp.jar xml-dtm.jar For more information see http://xml.apache.org/xalan-j/xsltc_usage.html I hope this helps anyone that has XML/XSLT performance issues. Mark MB Computer Ltd www.simplygites.com

    Posted by: mbuttle on August 15, 2007 at 4:42 AM



Only logged in users may post comments. Login Here.

Powered by
Movable Type 3.31