简体   繁体   English

如何以编程方式为邮件任务添加Ant库依赖项

[英]How to programmatically add Ant library dependencies for mail task

I've been tasked with creating automated notifications for our Ant build scripts. 我的任务是为Ant构建脚本创建自动通知。 This is so that when someone pushes out a deployment, our team can automatically receive an email about it. 这样,当有人推出部署时,我们的团队可以自动收到有关它的电子邮件。

The obvious choice was to use Ant's mail task , which comes predefined with Ant: 显而易见的选择是使用Ant的邮件任务 ,它是使用Ant预定义的:

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

However this results in the following runtime exception: 但是,这会导致以下运行时异常:

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

This is because Ant's mail task depends on JavaMail and JavaBeans Activation Framework , libraries which are apparently not included with its distribution. 这是因为Ant的邮件任务依赖于JavaMailJavaBeans Activation Framework ,这些库显然不包含在其发行版中。 Why Ant would define a task that depended on a library but not include that library is unclear to me. 为什么Ant会定义依赖于库但不包含该库的任务我不清楚。

This issue has already been discussed on this post: ant mail task using mail and activation jar in external location . 此帖已经讨论过这个问题: 在外部位置使用邮件和激活jar的ant邮件任务 Based on the answers there seem to be two solutions. 基于答案,似乎有两种解决方案。

The first is to manually put these library dependencies on the ant classpath. 第一种是手动将这些库依赖项放在ant类路径上。 This can be done using the -lib command line argument, or in eclipse one can use Window > Preferences > Ant > Runtime > Global Entries , and then add mail.jar and activation.jar (I'm pretty sure this amounts to the same thing as -lib , correct me if I'm wrong). 这可以使用-lib命令行参数完成,或者在eclipse中可以使用Window > Preferences > Ant > Runtime > Global Entries ,然后添加mail.jaractivation.jar (我很确定这相同)事情为-lib ,如果我错了,请纠正我)。 But this solution is undesirable for our team because it would mean every one of us would have to manually carry out these steps. 但是这个解决方案对我们的团队来说是不受欢迎的,因为这意味着我们每个人都必须手动执行这些步骤。 I'm looking for a way to simply commit my notification code, and it should work on another eclipse install after svn update. 我正在寻找一种方法来简单地提交我的通知代码,它应该在svn更新后的另一个eclipse安装上工作。

The other solution in the linked post mentions a way to do the above programmatically, by calling Ant from itself: 链接文章中的另一个解决方案提到了一种通过从自身调用Ant来以编程方式执行上述操作的方法:

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

The problem with this is that the Ant command line tool is apparently only included with the full install, not the eclipse distribution. 这个问题是Ant命令行工具显然只包含在完整安装中,而不是eclipse发行版。 So again there's no way to make it work without some manual action by anyone wanting to use the mail task. 因此,如果没有任何想要使用邮件任务的人进行手动操作,就无法使其工作。

Is there any way I can automate this without adding another annoying step to project setup? 有没有什么方法可以自动化这个,而不会给项目设置添加另一个恼人的步骤? I really don't understand why this is so hard to achieve - it seems like if the mail task wasn't predefined by Ant this would be easier. 我真的不明白为什么这么难实现 - 看起来如果邮件任务没有被Ant预定义,这会更容易。 Hopefully I'm missing something. 希望我错过了一些东西。

With the example from this mail thread I got a working solution that sends email when the tests fail. 通过这个邮件线程的示例,我得到了一个可以在测试失败时发送电子邮件的工作解决方案。

You need to download ant-classloadertask.jar , and mail.jar from javamail and place them in test.libs.dir. 您需要从javamail下载ant-classloadertask.jar和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>

Mail is one of the optional tasks in ANT. 邮件是ANT中的可选任务之一。 To install these additional libraries ANT 1.7 added a fetch.xml script, invoked as follows: 要安装这些附加库,ANT 1.7添加了一个fetch.xml脚本,调用如下:

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

On windows you could try: 在Windows上你可以尝试:

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

For a full explanation, see the ANT Manual documentation . 有关完整说明,请参阅ANT手册文档


Update 更新

The following ANT file has an install-jars target that can be used to install the missing ANT jars used by the mail task. 以下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>

I discovered that the ANT mail task task loads it's dependent classes from the ANT system classpath. 我发现ANT邮件任务任务从ANT系统类路径加载它的依赖类。 This means the build has to be run in two steps: 这意味着构建必须分两步运行:

$ ant install-jars
$ ant

Most ANT tasks allow you to specify a classpath reference. 大多数ANT任务允许您指定类路径引用。 The Mail task does not. 邮件任务没有。 Trying to research this issue lead me to the following mailing list thread: 试图研究这个问题让我看到以下邮件列表主题:

The solution is convoluted and not worth the effort. 解决方案很复杂,不值得付出努力。 I'd recommend living with the inconvenience... (The install-jars target only needs to be run once) 我建议生活带来不便......(安装罐子目标只需要运行一次)

With Ant 1.8.2 and ant-classloadertask.jar solution mentioned above (by bro ) I needed to change loader attribute of classloadertask from: 使用上面提到的Ant 1.8.2和ant-classloadertask.jar解决方案(由bro )我需要更改classloadertask的 loader属性:

loader="thread"

into: 成:

loader="project"

otherwise classes in activation.jar and mail.jar were not found by the classloader. 否则classloader找不到activation.jarmail.jar中的类。

With the taskdef command, you can dynamically load new tasks and specify a classpath from where they are loaded. 使用taskdef命令,您可以动态加载新任务并指定加载它们的类路径。 I use this successfully for loading new tasks from an external library which is not on the ant class path. 我成功地使用它来从不在ant类路径上的外部库加载新任务。 Whether it also works when the task already exists, I don't know. 当任务已经存在时它是否也有效,我不知道。

I would probably start with trying to re-define the mail task with a new name: 我可能会尝试使用新名称重新定义邮件任务:

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

Perhaps you need to include the original ant class path in the class path here so that the class of the mail task can be found. 也许您需要在类路径中包含原始ant类路径,以便可以找到邮件任务的类。

If this doesn't work, perhaps you can take the source code of the mail task, rename the class, bundle it together with the classes from mail.jar and activation.jar into your own jar and load this task from the JAR. 如果这不起作用,也许您可​​以获取邮件任务的源代码,重命名该类,将它与mail.jaractivation.jar的类一起捆绑到您自己的jar中,并从JAR加载此任务。 This should work just as it works with any task not shipped with ant. 这应该适用于任何未附带ant的任务。

You can put these jars as external jars to the classpath of the ant run config (this is my ftp example): 您可以将这些jar作为外部jar放到ant run config的类路径中(这是我的ftp示例):

在此输入图像描述

and save this run config to the project(Tab: Common--> Shared File, I usually take something like resources/eclipse for that) and commit it to svn. 并将此运行配置保存到项目中(Tab:Common - > Shared File,我通常采用类似resources/eclipse的方式)并将其提交给svn。

  1. it will be available for all developers who check this project out from svn 它将适用于从svn检查此项目的所有开发人员
  2. you have to deliver the jars in that project, too. 你也必须在该项目中交付罐子。 So that they will always be available 这样他们将永远可用
  3. Everybody can run it easily from the external tools menu 每个人都可以从外部工具菜单轻松运行它

Of course you could write your own mail task , to take care of that. 当然你可以编写自己的邮件任务来处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM