(Quick Reference)

4.6 Ant和Maven - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

4.6 Ant和Maven

如果你的团队或公司的所有其他项目都在使用像Ant或Maven这样的标准的构建工具进行构建的,而你使用Grails命令行来构建你的应用程序时你就可能成为团队或者公司这个大家庭的害群之马。幸运的是,今天你可以很容易的将Grails构建系统集成到当今主流的构建工具中(嗯,至少是在Java项目中使用的那种构建工具)。

Ant 整合

当你通过 create-app 命令来创建一个Grails应用程序时,Grails不会自动创建Apache Ant 工具使用的build.xml文件,但是你可以通过integrate-with 命令来生成一个:

grails integrate-with --ant

这个命令会创建一个 build.xml 文件,这个文件包含了下列的任务:

  • clean - 清理Grails应用程序
  • compile - -编译你的应用程序的源码
  • test - 运行单元测试
  • run - 等同于“grails run-app”的功能
  • war - 创建一个WAR文件
  • deploy - 默认为空,但可以用它实现自动部署

这些任务都可以被Ant运行,例如:

ant war

为了实现依赖管理,构建文件已经被全面改进为使用 Apache Ivy for dependency management,这意味着它可以自动下载所有需要的Grails JAR文件和其他以来的文件。你甚至不必在本地安装Grails就可以使用它了!这对于需要使用像CruiseControl 或者 Jenkins这样的持续集成系统进行自动构建时特别有用。

这里使用了Grails的Ant task来对现有的Grails构建系统进行钩子操作。这个任务允许你运行任何可用的Grails脚本,不只是由生成的构建文件所使用的那些。要使用某个任务,你必须先声明它:

<taskdef name="grailsTask"
         classname="grails.ant.GrailsTask"
         classpathref="grails.classpath"/>

这也引出了另外的问题:“grails.classpath”中应该是什么内容?这个任务本身是在“grails-bootstrap”这个JAR工件中的,因此至少grails-bootstrap-xxx.jar需要在classpath中。同时也应该包含“groovy-all”这个JAR。对于这个任务定义,你只需要使用它!下表列出了可用的属性:

属性描述是否必填
home构建时需要用到的Grails安装目录的位置。除非classpath被指定否则必填。
classpathref载入Grails的Classpath。必须包含“grails-bootstrap”工件并且应该包含“grails-scripts”。除非home被设置或者你使用classpath元素否则必填。
script要运行的Grails脚本的名称,例如:“TestApp”。必填。
args要加入脚本中的参数,例如:“-unit -xml”。不是必填。默认为“”。
environment运行脚本时的Grails环境。不是必填。默认为脚本的default。
includeRuntimeClasspath高级设置:如果设为true则将应用程序的运行时classpath添加到构建classpath中。不是必填。默认为true

这个任务也支持下列内嵌元素,这些全都是标准的Ant路径结构:

  • classpath - 构建classpath(用来载入Gant和Grails脚本)。
  • compileClasspath - 用来编译应用程序的类的Classpath。
  • runtimeClasspath - 用来运行应用程序并将程序打成WAR包的Classpath。通常包含了compileClasspath中的一切。
  • testClasspath - 用来编译和运行测试的Classpath。通常包含了runtimeClasspath中的一切。.

要如何填写这些路径信息完全取决于你。如果你正在使用 home 属性并且把你自己的依赖内容放在了 lib 目录中,那么你不需要使用以上任何一个路径。如果想看看使用它们的例子,那么就查看为一个新应用而生成的Ant构建文件吧。

Maven集成

Grails通过一个Maven插件提供了与 Maven 2 的集成 .当前作为基础的Maven插件,特别是由 Octo 创建的这个版本是非常有效的,它做得非常出色。

准备

In order to use the new plugin, all you need is Maven 2 installed and set up. This is because you no longer need to install Grails separately to use it with Maven! 为了使用这个新的插件,你只需要安装和设置Maven 2。你不再需要单独的安装Grails!

Grails集成Maven 2已经针对Maven 2.0.9及以上版本进行了设计和测试。它将无法工作在更早期的版本中。

The default mvn setup DOES NOT supply sufficient memory to run the Grails environment. We recommend that you add the following environment variable setting to prevent poor performance: 默认的mvn设置没有配置充足的内存来运行grails环境。我们推荐你添加下面的环境变量防止系统表现不佳。

export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=256"

创建一个 Grails Maven 项目

要简单地创建一个支持Maven的Grails项目只要运行下边的命令:

mvn archetype:generate -DarchetypeGroupId=org.grails \
    -DarchetypeArtifactId=grails-maven-archetype \
    -DarchetypeVersion=1.3.2 \
    -DgroupId=example -DartifactId=my-app

无论你想为你的应用选择哪个grails version,group ID和artifact ID,一切内容格式都必须像上面写的那样。这将创建一个新的Maven项目以及一个POM文件和一系列其他文件。你不会看到有什么是像一个Grails应用。因此,下一步就要创建一个你要使用的项目结构了。 但首先, 为了配置目标 JDK 为 Java 6, 打开 my-app/pom.xml 并且更新

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
</plugin>
<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.6</source>
    <target>1.6</target>
  </configuration>
</plugin>

然后您就可以创建项目结构:

cd my-app
mvn initialize

如果你遇到下面类似的消息:

Resolving plugin JAR dependencies …
:: problems summary ::
:::: WARNINGS
        module not found: org.hibernate#hibernate-core;3.3.1.GA

你需要手动增加这个插件到 application.properties:

plugins.hibernate=2.0.0
plugins.tomcat=2.0.0

then run

mvn compile

最后 hibernate 和 tomcat 插件 会被安装。

现在你已经有一个可以使用的Grails应用了。插件已经集成到了标准的构建周期,因此你可以使用标准的Maven语法来构建和打包你的应用程序了: mvn clean , mvn compile , mvn test , mvn package , mvn install

你也可以利用许多已经被包装成Maven目标的Grails命令:

你可以调用 mvn grails:help 来获取一个完整的,最新的命令列表

给现有项目加入Maven支持

创建一个全新的项目当然是一个很好的途径,但如果已经有一个项目了该怎么办呢?你应该不会愿意先创建一个新项目然后再把旧项目的内容拷贝进去的。解决方法是使用下列命令为现有项目创建一个POM文件(以现有项目的Grails版本号代替下面的版本号):

mvn org.grails:grails-maven-plugin:1.3.2:create-pom -DgroupId=com.mycompany
当这个命令完成时,你就可以立即使用标准的语法了,如 mvn package 。需要注意的是当创建POM文件时你必须指定一个group ID。

你也可能想要设置目标JDK为Java 6,请看上面

添加Grails命令到 phase 中

标准的POM文件被创建是为了让Grails将合适的核心Grails命令附加到它们对应的构建语法上,因此“compile”对应“compile”语法,“war”对应“package”语法。当你想要将一个插件的命令附加到一个特定的phase上时,这可能没有什么帮助。典型的例子是功能测试。你如何确保你的功能测试(无论正在使用你决定的哪个插件)是使用“integration-test” phase来运行的?

恐怕不是:所有事情都是可能的。在这个例子中,你可以使用额外的“execution”块来将命令联合到一个 phase 上:

<plugin>
    <groupId>org.grails</groupId>
    <artifactId>grails-maven-plugin</artifactId>
    <version>1.3.2</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <goals></goals>
        </execution>
        <!-- 添加 "functional-tests" 命令到 "integration-test" phase -->
        <execution>
            <id>functional-tests</id>
            <phase>integration-test</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <command>functional-tests</command>
            </configuration>
        </execution>
    </executions>
</plugin>

这也展示了 grails:exec 目标,它可以用来运行任何Grails命令。简单的将命令的名字作为 command 系统特性,还可以通过 args 特性来选择性地指定参数:

mvn grails:exec -Dcommand=create-webtest -Dargs=Book

调试一个 Grails Maven 工程

Maven可以使用“mvnDebug”命令在调试模式下启动。要启动调试你的Grails应用程序,只需运行:

mvnDebug grails:run-app

这一过程在启动的时候将被暂停和监听8000端口的调试器 The process will be suspended on startup and listening for a debugger on port 8000.

如果您需要更多的控制调试器,这可以使用的MAVEN_OPTS环境变量指定,并用默认的“MVN”命令来启动Maven:

MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
mvn grails:run-app

提出问题

如果你遇到任何与Maven的集成的问题,请作为一个子任务提出一个JIRA问题GRAILS-3547.

If all the other projects in your team or company are built using a standard build tool such as Ant or Maven, you become the black sheep of the family when you use the Grails command line to build your application. Fortunately, you can easily integrate the Grails build system into the main build tools in use today (well, the ones in use in Java projects at least).

Ant Integration

When you create a Grails application with the create-app command, Grails doesn't automatically create an Ant build.xml file but you can generate one with the integrate-with command:


grails integrate-with --ant

This creates a build.xml file containing the following targets:

  • clean - Cleans the Grails application
  • compile - Compiles your application's source code
  • test - Runs the unit tests
  • run - Equivalent to "grails run-app"
  • war - Creates a WAR file
  • deploy - Empty by default, but can be used to implement automatic deployment

Each of these can be run by Ant, for example:

ant war

The build file is configured to use Apache Ivy for dependency management, which means that it will automatically download all the requisite Grails JAR files and other dependencies on demand. You don't even have to install Grails locally to use it! That makes it particularly useful for continuous integration systems such as CruiseControl or Jenkins.

It uses the Grails Ant task to hook into the existing Grails build system. The task lets you run any Grails script that's available, not just the ones used by the generated build file. To use the task, you must first declare it:

<taskdef name="grailsTask"
         classname="grails.ant.GrailsTask"
         classpathref="grails.classpath"/>

This raises the question: what should be in "grails.classpath"? The task itself is in the "grails-bootstrap" JAR artifact, so that needs to be on the classpath at least. You should also include the "groovy-all" JAR. With the task defined, you just need to use it! The following table shows you what attributes are available:

AttributeDescriptionRequired
homeThe location of the Grails installation directory to use for the build.Yes, unless classpath is specified.
classpathrefClasspath to load Grails from. Must include the "grails-bootstrap" artifact and should include "grails-scripts".Yes, unless home is set or you use a classpath element.
scriptThe name of the Grails script to run, e.g. "TestApp".Yes.
argsThe arguments to pass to the script, e.g. "-unit -xml".No. Defaults to "".
environmentThe Grails environment to run the script in.No. Defaults to the script default.
includeRuntimeClasspathAdvanced setting: adds the application's runtime classpath to the build classpath if true.No. Defaults to true.

The task also supports the following nested elements, all of which are standard Ant path structures:

  • classpath - The build classpath (used to load Gant and the Grails scripts).
  • compileClasspath - Classpath used to compile the application's classes.
  • runtimeClasspath - Classpath used to run the application and package the WAR. Typically includes everything in @compileClasspath.
  • testClasspath - Classpath used to compile and run the tests. Typically includes everything in runtimeClasspath.

How you populate these paths is up to you. If you use the home attribute and put your own dependencies in the lib directory, then you don't even need to use any of them. For an example of their use, take a look at the generated Ant build file for new apps.

Maven Integration

Grails provides integration with Maven 2 with a Maven plugin. The current Maven plugin is based on but supersedes the version created by Octo, who did a great job with the original.

Preparation

In order to use the new plugin, all you need is Maven 2 installed and set up. This is because you no longer need to install Grails separately to use it with Maven!

The Maven 2 integration for Grails has been designed and tested for Maven 2.0.9 and above. It will not work with earlier versions.

The default mvn setup DOES NOT supply sufficient memory to run the Grails environment. We recommend that you add the following environment variable setting to prevent poor performance:

export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=256"

Creating a Grails Maven Project

To create a Mavenized Grails project simply run the following command:

mvn archetype:generate -DarchetypeGroupId=org.grails \
    -DarchetypeArtifactId=grails-maven-archetype \
    -DarchetypeVersion=1.3.2 \
    -DgroupId=example -DartifactId=my-app

Choose whichever grails version, group ID and artifact ID you want for your application, but everything else must be as written. This will create a new Maven project with a POM and a couple of other files. What you won't see is anything that looks like a Grails application. So, the next step is to create the project structure that you're used to. But first, to set target JDK to Java 6, do that now. Open my-app/pom.xml and change

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
</plugin>
to
<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.6</source>
    <target>1.6</target>
  </configuration>
</plugin>

Then you're ready to create the project structure:

cd my-app
mvn initialize

if you see a message similar to this:

Resolving plugin JAR dependencies …
:: problems summary ::
:::: WARNINGS
        module not found: org.hibernate#hibernate-core;3.3.1.GA

you need to add the plugins manually to application.properties:

plugins.hibernate=2.0.0
plugins.tomcat=2.0.0

then run

mvn compile

and the hibernate and tomcat plugins will be installed.

Now you have a Grails application all ready to go. The plugin integrates into the standard build cycle, so you can use the standard Maven phases to build and package your app: mvn clean , mvn compile , mvn test , mvn package , mvn install .

You can also use some of the Grails commands that have been wrapped as Maven goals:

For a complete, up to date list, run mvn grails:help

Mavenizing an existing project

Creating a new project is great way to start, but what if you already have one? You don't want to create a new project and then copy the contents of the old one over. The solution is to create a POM for the existing project using this Maven command (substitute the version number with the grails version of your existing project):

mvn org.grails:grails-maven-plugin:1.3.2:create-pom -DgroupId=com.mycompany
When this command has finished, you can immediately start using the standard phases, such as mvn package. Note that you have to specify a group ID when creating the POM.

You may also want to set target JDK to Java 6; see above.

Adding Grails commands to phases

The standard POM created for you by Grails already attaches the appropriate core Grails commands to their corresponding build phases, so "compile" goes in the "compile" phase and "war" goes in the "package" phase. That doesn't help though when you want to attach a plugin's command to a particular phase. The classic example is functional tests. How do you make sure that your functional tests (using which ever plugin you have decided on) are run during the "integration-test" phase?

Fear not: all things are possible. In this case, you can associate the command to a phase using an extra "execution" block:

<plugin>
    <groupId>org.grails</groupId>
    <artifactId>grails-maven-plugin</artifactId>
    <version>1.3.2</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <goals></goals>
        </execution>
        <!-- Add the "functional-tests" command to the "integration-test" phase -->
        <execution>
            <id>functional-tests</id>
            <phase>integration-test</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <command>functional-tests</command>
            </configuration>
        </execution>
    </executions>
</plugin>

This also demonstrates the grails:exec goal, which can be used to run any Grails command. Simply pass the name of the command as the command system property, and optionally specify the arguments with the args property:

mvn grails:exec -Dcommand=create-webtest -Dargs=Book

Debugging a Grails Maven Project

Maven can be launched in debug mode using the "mvnDebug" command. To launch your Grails application in debug, simply run:

mvnDebug grails:run-app

The process will be suspended on startup and listening for a debugger on port 8000.

If you need more control of the debugger, this can be specified using the MAVEN_OPTS environment variable, and launch Maven with the default "mvn" command:

MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
mvn grails:run-app

Raising issues

If you come across any problems with the Maven integration, please raise a JIRA issue as a sub-task of GRAILS-3547.