dev2dev 首页 > 资源中心 > 专家Blog > 专家Blog文章
使导出的Workshop build脚本自动可移植
如果由于某种原因,Workshop应用程序需要由后台进程或从命令行编译,那么您可以选择Workshop中的选项,将其导出到一个build脚本。借助于该选项,您可以从命令行编译应用程序。但是,如果您在一个源代码控制系统中签入(check in)该应用程序,然后让其他人在另一个位置、另一个环境签出(check out)它,然后试着编译它,那么可能会编译失败。这是因为默认的exported_build.xml文件硬编码了到WebLogic发行版的根目录的绝对路径,更糟糕的是,它硬编码了到应用程序的根目录的绝对路径。除非您指定“策略”,规定所有人都必须将WebLogic安装到同一个驱动路径下,并且所有人都使用同一路径签出该应用程序,否则编译就不会成功。本文我将介绍一种增强这一自动编译过程的方法,以透明地“修复”这个问题。
如果进入该应用程序的属性(在Application导航树中右击该应用程序名,选择Properties),选择左侧的Build文件夹,可以看到Export to Ant file按钮。单击它,将会创建一个可用于编译应用程序的Ant脚本,exported_build.xml文件(除非该文件名已经被使用了,那样的话,文件名会稍微有所变化)。创建该文件后,可以从DOS提示符运行ant -f exported_build.xml,可以看到它构建了应用程序EAR文件。所以,只需将该文件签入到源代码管理系统,然后其他人就可以签出整个应用程序,并运行同样的命令行来编译应用程序。
错了。您确实需要将该文件存储到源代码管理系统中(幸运的是,它无需经常更改),但是在常规环境下,其他签出该应用程序的人将不能使用相同的命令行编译应用程序,除非他们修改build脚本,或者在如何使用源代码管理系统方面做出重大妥协。
问题是exported_build.xml Ant脚本有两个本不应该是硬编码的硬编码路径引用。它硬编码了WebLogic home目录的位置,更糟糕的是,它硬编码了创建应用程序的初始目录位置。
硬编码WebLogic home目录的位置还不是太糟糕。大部分人总是将WebLogic安装在C:\bea下,使得WebLogic home目录为C:\bea\weblogic81。如果不将它安装到那里,编译不会成功。如果您打算在实际的几个平台上编译跨平台的Java应用程序,那么同理,这也不会成功。
但是,假设存储应用程序的目录位置肯定不是一个好的假设。许多源代码管理系统会基于用户名导出应用程序到目录。任何区别都可能导致失败。
模拟问题
为了说明这个问题的存在,可以在另一台计算机上,或者将BEA安装到另外一个位置,或者使用源代码控制系统将应用程序签出到另一个目录下,但是通过模拟可以更容易地说明该问题。
如果编辑exported_build.xml文件,可以看到weblogic.home和app.dir的两个硬编码的属性值。为了说明该问题,首先从带ant -f exported_build.xml的命令行运行编译。这将运行良好(除非应用程序有问题)。现在,将weblogic.home属性的值更改为一个不存在的路径,然后返回编译。这将很快就会失败,因为找不到WlwBuildTask类。现在,将值再改回去,然后将app.dir值改为一个不存在的路径,然后返回编译。这也会失败,因为找不到.work文件。
如何解决?
幸运的是,有一个解决这一问题的可行策略。
该策略分为两部分。第一部分策略用于为两个属性确定正确的值,第二部分策略用于使脚本使用这些正确值,而不是它所正在使用的。
获得weblogic.home的正确值意味着引用BEA_HOME环境变量,并使用该值。
app.dir的正确值则有些奇特。不要试图弄清楚应用程序的绝对路径,可以假定编译从当前目录运行,所以一个非常好的正确值就是“.”。
解决方案机制
既然已经知道了如何获取正确值,那么如何使exported_build.xml脚本使用正确的值,而不是错误的值呢?答案是使用XSLT样式表进行转换,并使用转换后的文件取代原始文件。幸运的是,Workshop将导出的文件创建为exported_build.xml,而不是build.xml。这使我们可以使用自定义的build.xml(该文件在不同的常规Workshop应用程序之间很少改变),它对exported_build.xml文件运行一个自定义的样式表,生成一个transformed_build.xml文件,然后对transformed_build.xml文件运行“build”(或“clean”)目标。
自定义的build脚本可能如下:
<?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>
注意“build”和“clean”目标是如何依赖于transform.buildscript目标的。该目标使用xslt任务执行转换,生成transformed_build.xml文件。
自定义的样式表可能如下:
<?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>
<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>
关键之处在于两个模板,它们的Xpath值指定了weblogic.home和app.dir属性,并代之以正确的值。
做了这些更改后,不仅编译可以生效,还可以运行ant取代ant -f exported_build.xml。
原文出处:
http://dev2dev.bea.com/blog/dkarr/archive/2005/09/making_the_expo_1.html
作者其它文章
|