diff --git a/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc b/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc index 16092882a20..707e50c3ab4 100644 --- a/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc +++ b/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc @@ -607,11 +607,155 @@ further information. +[[build-tool-plugins-antlib]] +== Spring Boot AntLib module +The Spring Boot AntLib module provides basic Spring Boot support for Apache Ant. You can +use the module to create executable jars. To use the module you need to declare an +additional `spring-boot` namespace in your `build.xml`: + +[source,xml,indent=0] +---- + + ... + +---- + +You'll need to remember to start Ant using the `-lib` option, for example: + +[indent=0,subs="verbatim,quotes,attributes"] +---- + $ ant -lib +---- + +TIP: The "`Using Spring Boot`" section includes a more complete example of +<> + + +=== Spring Boot Ant tasks +Once the `spring-boot-antlib` namespace has been declared, the following additional +tasks are available. + + + +==== spring-boot:exejar +The `exejar` task can be used to creates a Spring Boot executable jar. The following +attributes are supported by the task: + +[cols="1,2,2"] +|==== +|Attribute |Description |Required + +|`destfile` +|The destination jar file to create +|Yes + +|`classes` +|The root directory of Java classfiles +|Yes + +|`start-class` +|The main application class to run +|No _(default is first class found declaring a `main` method)_ +|==== + +The following nested elements can be used with the task: + +[cols="1,4"] +|==== +|Element |Description + +|`resources` +|One or more {ant-manual}/Types/resources.html#collection[Resource Collections] +describing a set of {ant-manual}/Types/resources.html[Resources] that should be added to +the content of the created +jar+ file. + +|`lib` +|One or more {ant-manual}/Types/resources.html#collection[Resource Collections] +that should be added to the set of jar libraries that make up the runtime dependency +classpath of the application. +|==== + + + +===== Examples +.Specify +start-class+ +[source,xml,indent=0] +---- + + + + + + + + +---- + +.Detect +start-class+ +[source,xml,indent=0] +---- + + + + + +---- + + + +=== spring-boot:findmainclass +The `findmainclass` task is used internally by `exejar` to locate a class declaring a +`main`. You can also use this task directly in your build if needed. The following +attributes are supported + +[cols="1,2,2"] +|==== +|Attribute |Description |Required + +|`classesroot` +|The root directory of Java classfiles +|Yes _(unless `mainclass` is specified)_ + +|`mainclass` +|Can be used to short-circuit the `main` class search +|No + +|`property` +|The Ant property that should be set with the result +|No _(result will be logged if unspecified)_ +|==== + + + +===== Examples +.Find and log +[source,xml,indent=0] +---- + +---- + +.Find and set +[source,xml,indent=0] +---- + +---- + +.Override and set +[source,xml,indent=0] +---- + +---- + + + [[build-tool-plugins-other-build-systems]] == Supporting other build systems -If you want to use a build tool other than Maven or Gradle, you will likely need to develop -your own plugin. Executable jars need to follow a specific format and certain entries need -to be written in an uncompressed form (see the +If you want to use a build tool other than Maven, Gradle or Ant, you will likely need to +develop your own plugin. Executable jars need to follow a specific format and certain +entries need to be written in an uncompressed form (see the _<>_ section in the appendix for details). @@ -668,6 +812,8 @@ Here is a typical example repackage: }); ---- + + [[build-tool-plugins-whats-next]] == What to read next If you're interested in how the build tool plugins work you can diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index fd3f141bbbd..b8124aa2449 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -2198,9 +2198,10 @@ details. [[howto-build-an-executable-archive-with-ant]] -=== Build an executable archive with Ant +=== Build an executable archive from Ant without using spring-boot-antlib To build with Ant you need to grab dependencies, compile and then create a jar or war -archive as normal. To make it executable: +archive as normal. To make it executable you can either use the `spring-boot-antlib` +module, or you can follow these instructions: . Use the appropriate launcher as a `Main-Class`, e.g. `JarLauncher` for a jar file, and specify the other properties it needs as manifest entries, principally a `Start-Class`. @@ -2236,7 +2237,7 @@ The Actuator Sample has a `build.xml` that should work if you run it with [indent=0,subs="verbatim,quotes,attributes"] ---- - $ ant -lib /ivy-2.2.jar + $ ant -lib ---- after which you can run the application with diff --git a/spring-boot-docs/src/main/asciidoc/index.adoc b/spring-boot-docs/src/main/asciidoc/index.adoc index c2d0483bf53..d805cba5af9 100644 --- a/spring-boot-docs/src/main/asciidoc/index.adoc +++ b/spring-boot-docs/src/main/asciidoc/index.adoc @@ -39,6 +39,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson; :spring-data-mongo-javadoc: http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb :spring-data-rest-javadoc: http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest :gradle-userguide: http://www.gradle.org/docs/current/userguide +:ant-manual: http://ant.apache.org/manual // ====================================================================================== include::documentation-overview.adoc[] diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc index ed074d49c42..c1c6c10885d 100644 --- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc +++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc @@ -210,12 +210,68 @@ endif::[] [[using-boot-ant]] === Ant -It is possible to build a Spring Boot project using Apache Ant, however, no special -support or plugins are provided. Ant scripts can use the Ivy dependency system to import -starter POMs. +It is possible to build a Spring Boot project using Apache Ant+Ivy. The +`spring-boot-antlib` "`AntLib`" module is also available to help Ant create executable +jars. -See the _<>_ "`How-to`" for more -complete instructions. +To declare dependencies a typical `ivy.xml` file will look something like this: + +[source,xml,indent=0] +---- + + + + + + + + + + +---- + +A typical `build.xml` will look like this: + +[source,xml,indent=0] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +TIP: See the _<>_ "`How-to`" if +you don't want to use the `spring-boot-antlib` module. diff --git a/spring-boot-tools/pom.xml b/spring-boot-tools/pom.xml index dbd6e76065f..370869d27d4 100644 --- a/spring-boot-tools/pom.xml +++ b/spring-boot-tools/pom.xml @@ -25,5 +25,6 @@ spring-boot-loader-tools spring-boot-maven-plugin spring-boot-gradle-plugin + spring-boot-antlib diff --git a/spring-boot-tools/spring-boot-antlib/pom.xml b/spring-boot-tools/spring-boot-antlib/pom.xml new file mode 100644 index 00000000000..a3500a2ab50 --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-tools + 1.3.0.BUILD-SNAPSHOT + + spring-boot-antlib + Spring Boot Antlib + Spring Boot Antlib + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + 1.9.3 + + + + org.springframework.boot + spring-boot-loader + provided + + + org.springframework.boot + spring-boot-loader-tools + compile + + + org.apache.ant + ant + ${ant.version} + provided + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + org.springframework.boot:spring-boot-loader-tools + org.springframework:spring-core + + + true + false + true + + + + shade-runtime-dependencies + package + + shade + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + antunit + integration-test + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + org.apache.ant + ant + ${ant.version} + + + org.apache.ant + ant-launcher + ${ant.version} + + + org.apache.ant + ant-antunit + 1.3 + + + org.apache.ivy + ivy + 2.4.0 + + + org.eclipse.jdt.core.compiler + ecj + 4.4.2 + + + + + + diff --git a/spring-boot-tools/spring-boot-antlib/src/it/sample/build.xml b/spring-boot-tools/spring-boot-antlib/src/it/sample/build.xml new file mode 100644 index 00000000000..c6992bb33ec --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/it/sample/build.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Checking @{jar} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot-tools/spring-boot-antlib/src/it/sample/ivysettings.xml b/spring-boot-tools/spring-boot-antlib/src/it/sample/ivysettings.xml new file mode 100644 index 00000000000..72631b8ba83 --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/it/sample/ivysettings.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..3b04532758d --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.test; + +import org.joda.time.LocalDate; + +public class SampleApplication { + + public static void main(String[] args) { + System.out.println(LocalDate.class.getSimpleName()); + } + +} + diff --git a/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/resources/foo b/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/resources/foo new file mode 100644 index 00000000000..b7d6715e2df --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/it/sample/src/main/resources/foo @@ -0,0 +1 @@ +FOO diff --git a/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/FindMainClass.java b/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/FindMainClass.java new file mode 100644 index 00000000000..b88b343acd1 --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/FindMainClass.java @@ -0,0 +1,115 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.ant; + +import java.io.File; +import java.io.IOException; +import java.util.jar.JarFile; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.springframework.boot.loader.tools.MainClassFinder; +import org.springframework.util.StringUtils; + +/** + * Ant task to find a main class. + * + * @author Matt Benson + * @since 1.3.0 + */ +public class FindMainClass extends Task { + + private String mainClass; + + private File classesRoot; + + private String property; + + public FindMainClass(Project project) { + setProject(project); + } + + @Override + public void execute() throws BuildException { + String mainClass = this.mainClass; + if (!StringUtils.hasText(mainClass)) { + mainClass = findMainClass(); + if (!StringUtils.hasText(mainClass)) { + throw new BuildException( + "Could not determine main class given @classesRoot " + + this.classesRoot); + } + } + handle(mainClass); + } + + private String findMainClass() { + if (this.classesRoot == null) { + throw new BuildException( + "one of @mainClass or @classesRoot must be specified"); + } + if (!this.classesRoot.exists()) { + throw new BuildException("@classesRoot " + this.classesRoot + + " does not exist"); + } + try { + if (this.classesRoot.isDirectory()) { + return MainClassFinder.findSingleMainClass(this.classesRoot); + } + return MainClassFinder + .findSingleMainClass(new JarFile(this.classesRoot), "/"); + } + catch (IOException ex) { + throw new BuildException(ex); + } + } + + private void handle(String mainClass) { + if (StringUtils.hasText(this.property)) { + getProject().setProperty(this.property, mainClass); + } + else { + log("Found main class " + mainClass); + } + } + + /** + * Set the main class, which will cause the search to be bypassed. + * @param mainClass + */ + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + /** + * Set the root location of classes to be searched. + * @param classesRoot + */ + public void setClassesRoot(File classesRoot) { + this.classesRoot = classesRoot; + } + + /** + * Set the property to set (if unset, result will be printed to the log). + * @param property + */ + public void setProperty(String property) { + this.property = property; + } + +} diff --git a/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/ShareAntlibLoader.java b/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/ShareAntlibLoader.java new file mode 100644 index 00000000000..d00149c1b72 --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/main/java/org/springframework/boot/ant/ShareAntlibLoader.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.ant; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.springframework.util.StringUtils; + +/** + * Quiet task that establishes a reference to its loader. + * + * @author Matt Benson + * @since 1.3.0 + */ +public class ShareAntlibLoader extends Task { + + private String refid; + + public ShareAntlibLoader(Project project) { + super(); + setProject(project); + } + + @Override + public void execute() throws BuildException { + if (!StringUtils.hasText(this.refid)) { + throw new BuildException("@refid has no text"); + } + getProject().addReference(this.refid, getClass().getClassLoader()); + } + + public void setRefid(String refid) { + this.refid = refid; + } + +} diff --git a/spring-boot-tools/spring-boot-antlib/src/main/resources/org/springframework/boot/ant/antlib.xml b/spring-boot-tools/spring-boot-antlib/src/main/resources/org/springframework/boot/ant/antlib.xml new file mode 100644 index 00000000000..21237dc4ec1 --- /dev/null +++ b/spring-boot-tools/spring-boot-antlib/src/main/resources/org/springframework/boot/ant/antlib.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + Using start class ${start-class} + + + + + + + + + + + + + + + + + + Using destination directory ${destdir} + + + Extracting spring-boot-loader to ${destdir}/dependency + + + + + + Embedding spring-boot-loader v${spring-boot.version}... + + + + + + + + + + + + + + + +