【问题标题】:How to programmatically add Ant library dependencies for mail task如何以编程方式为邮件任务添加 Ant 库依赖项
【发布时间】:2012-02-07 15:21:40
【问题描述】:

我的任务是为我们的 Ant 构建脚本创建自动通知。这样当有人推出部署时,我们的团队可以自动收到一封有关它的电子邮件。

显而易见的选择是使用 Ant 预定义的 Ant's mail task

<target name="notify" description="notify team">
    <mail subject="latest deployment">
        <from address="me@gmail.com" />
        <to address="jimmy@yahoo.com" />
        <message>A new build has been pushed out to prod</message>
    </mail>
</target>

但是这会导致以下运行时异常:

java.lang.ClassNotFoundException: javax.mail.internet.MimeMessage

这是因为 Ant 的邮件任务依赖于 JavaMailJavaBeans Activation Framework,这些库显然不包含在其发行版中。我不清楚为什么 Ant 会定义一个依赖于库但不包含该库的任务。

这个问题已经在这篇文章中讨论过:ant mail task using mail and activation jar in external location。根据答案,似乎有两种解决方案。

首先是手动把这些库依赖放到ant类路径上。这可以使用-lib 命令行参数来完成,或者在eclipse 中可以使用Window &gt; Preferences &gt; Ant &gt; Runtime &gt; Global Entries,然后添加mail.jaractivation.jar(我很确定这与-lib 相同,如果我错了纠正我)。但这种解决方案对我们的团队来说是不可取的,因为这意味着我们每个人都必须手动执行这些步骤。我正在寻找一种方法来简单地提交我的通知代码,并且它应该可以在 svn 更新后的另一个 eclipse 安装上工作。

链接帖子中的另一个解决方案提到了一种以编程方式执行上述操作的方法,即从自身调用 Ant:

<exec executable="ant">
    <arg value="-lib"/>
    <arg value="PATH_TO_MY_LIB"/>
    <arg value="target"/>
</exec>

问题在于 Ant 命令行工具显然只包含在完整安装中,而不是 eclipse 发行版。因此,如果没有任何想要使用邮件任务的人手动操作,就无法使其正常工作。

有什么方法可以在不增加项目设置的烦人步骤的情况下实现自动化吗?我真的不明白为什么这很难实现 - 如果邮件任务 不是 由 Ant 预定义,这似乎会更容易。希望我错过了什么。

【问题讨论】:

  • 您是否考虑过使用 CI 来完成此类任务?它们带有邮件和大大改进的报告。我的投票是jenkins-ci.org

标签: java eclipse ant jakarta-mail


【解决方案1】:

邮件是 ANT 中的可选任务之一。为了安装这些额外的库,ANT 1.7 添加了一个 fetch.xml 脚本,调用如下:

ant -f $ANT_HOME/fetch.xml -Ddest=user -Dm2.url=http://repo1.maven.org/maven2 

在 windows 上你可以试试:

ant -f %ANT_HOME%/fetch.xml -Ddest=user -Dm2.url=http://repo1.maven.org/maven2 

如需完整说明,请参阅ANT Manual documentation


更新

以下 ANT 文件有一个 install-jars 目标,可用于安装邮件任务使用的缺失 ANT jar。

<project name="demo" default="notify">

    <target name="install-jars" description="Install ANT optional jars">
        <mkdir dir="${user.home}/.ant/lib"/>
        <get dest="${user.home}/.ant/lib/mail.jar"       src="http://search.maven.org/remotecontent?filepath=javax/mail/mail/1.4.4/mail-1.4.4.jar"/>
        <get dest="${user.home}/.ant/lib/activation.jar" src="http://search.maven.org/remotecontent?filepath=javax/activation/activation/1.1/activation-1.1.jar"/>
    </target>

    <target name="notify" description="notify team">
        <mail subject="latest deployment">
            <from address="me@gmail.com" />
            <to address="jimmy@yahoo.com" />
            <message>A new build has been pushed out to prod</message>
        </mail>
    </target>

</project>

我发现 ANT 邮件任务任务从 ANT 系统类路径加载它的依赖类。这意味着构建必须分两步运行:

$ ant install-jars
$ ant

大多数 ANT 任务允许您指定类路径引用。邮件任务没有。试图研究这个问题导致我进入以下邮件列表线程:

解决方案很复杂,不值得努力。我建议忍受不便......(install-jars 目标只需要运行一次)

【讨论】:

  • 如何通过构建文件以编程方式完成此操作,以便在 Eclipse 中对更改(和 jar)进行 svn 检出后,无需任何手动设置即可工作?
  • 在看到真正实现自动化是多么难以克服之后,我和我的团队决定放弃并吞下每次安装 Eclipse 时手动设置 Ant 的药丸。您的安装目标已接近,为此 +1 和链接 - 不幸的是 Ant 需要重新启动,但如果不陷入类加载器的混乱,似乎真的没有办法解决。
  • @PaulBellora 只是一个额外的想法,您可以检查文件是否存在,如果不存在,则只运行 install-jars。 check if file exists。这会将这些步骤透明地集成到您的工作流程中。
  • @oers 我想检查类的存在(而不是文件),但它并不能避免必须运行 ANT 两次......这就是我给的原因up :-( 这里的根本原因是不支持 classpathref 属性的旧 ANT 任务。相比之下,破解 ANT 类加载器似乎很笨拙,而且我们也拒绝了该选项(使用标准 ANT)
【解决方案2】:

通过this mail thread 的示例,我得到了一个有效的解决方案,可以在测试失败时发送电子邮件。

需要下载ant-classloadertask.jar, 和来自 javamail 的 mail.jar 并将它们放在 test.libs.dir 中。

<property name="test.libs.dir" location="${basedir}/lib/unit-test"/>
<property name="test.results.dir" location="${basedir}/test-results/"/>

<path id="project.classpath.tests">
    <pathelement location="${build}"/> 
    <path refid="project.lib.path"/>
</path>

<target name="unit-tests" depends="">
    <mkdir dir="${test.results.dir}"/>
    <junit fork="false" showoutput="yes" includeantruntime="false"
        errorproperty="test.error" failureproperty="test.error" 
        haltonerror="false" haltonfailure="false">
        <classpath refid="project.classpath.tests"/>
        <formatter type="plain" usefile="true" />
        <batchtest fork="no" todir="${test.results.dir}">
            <fileset dir="${build}/test/">
                <include name="package/dir/path/to/tests/TestFile.java"/>
            </fileset>
        </batchtest>
    </junit>
    <antcall target="sendMail"/> 
</target>

<path id="mail.path">
    <pathelement location="${test.libs.dir}/mail.jar"/>
</path>

<!-- http://enitsys.sourceforge.net/ant-classloadertask/ -->
<taskdef name="classloadertask"
    classname="org.apache.tools.ant.taskdefs.ClassloaderTask" 
    classpath="${test.libs.dir}/ant-classloadertask.jar"/>
    <classloadertask classpathRef="mail.path" loader="thread"/> 

<target name="sendMail" if="test.error">
    <mail mailhost="smtp.gmail.com"
        mailport="587"
        user=""
        password=""
        ssl="yes"
        failonerror="true"
        from=""
        tolist=""
        subject="Unit tests have failed"/>
</target>

【讨论】:

    【解决方案3】:

    使用taskdef 命令,您可以动态加载新任务并指定加载它们的类路径。我成功地使用它从不在 ant 类路径上的外部库中加载新任务。当任务已经存在时它是否也有效,我不知道。

    我可能会先尝试用新名称重新定义邮件任务:

    <taskdef name="mymail" classname="class.of.mail.task" classpath="mail.jar;activation.jar">
    

    这里可能需要在类路径中包含原来的ant类路径,这样才能找到邮件任务的类。

    如果这不起作用,也许您可​​以获取邮件任务的源代码,重命名类,将其与 mail.jaractivation.jar 中的类捆绑到您自己的 jar 中,然后从罐。这应该像它与任何未随 ant 一起提供的任务一样工作。

    【讨论】:

    • @oers 您能否提供更多详细信息,为什么这不起作用?
    • 对不起,我可能操之过急。我将您的答案误读为我尝试过的东西。这种方法可以奏效。
    • This seems to be possible,但由于类加载问题需要额外的 ant 任务。
    • 我试过了,不行。仍然得到 ClassNotFoundException 因为邮件任务正在从系统类路径加载它的依赖类。看起来@oers 发现了与我相同的邮件线程!
    【解决方案4】:

    您可以将这些 jars 作为外部 jars 放到 ant run config 的类路径中(这是我的 ftp 示例):

    并将这个运行配置保存到项目中(Tab:Common--> Shared File,我通常使用resources/eclipse之类的东西)并将其提交给svn。

    1. 它将可供所有从 svn 签出此项目的开发人员使用
    2. 您也必须交付该项目中的 jar。以便它们始终可用
    3. 每个人都可以从外部工具菜单轻松运行它

    当然你可以write your own mail task来处理这个问题。

    【讨论】:

    • +1 这是一个有趣的建议 - 最终我们决定容忍每次安装手动安装 Ant。
    【解决方案5】:

    使用 Ant 1.8.2 和 ant-classloadertask.jar 提到的解决方案 abovebro)我需要更改 classloadertaskloader 属性:

    loader="thread"
    

    进入:

    loader="project"
    

    否则类加载器找不到 activation.jarma​​il.jar 中的类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-15
      相关资源
      最近更新 更多