Allow gradle builds without version numbers

Add a gradle `ResolutionStrategy` that resolves missing version numbers
using the `spring-boot-dependencies` POM.

This commit also introduces a new `spring-boot-dependency-tools` module
that provides programmatic access to the `dependencyManagement` section
of the dependencies POM.

Fixed gh-262
pull/272/head
Phillip Webb 11 years ago
parent 19ca4d4eae
commit ab4baa3c43

@ -616,6 +616,10 @@
<artifactId>maven-install-plugin</artifactId> <artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version> <version>2.5.1</version>
</plugin> </plugin>
<plugin>
<artifactId>maven-help-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin> <plugin>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>2.4</version> <version>2.4</version>

@ -14,6 +14,7 @@
<main.basedir>${basedir}/..</main.basedir> <main.basedir>${basedir}/..</main.basedir>
</properties> </properties>
<modules> <modules>
<module>spring-boot-dependency-tools</module>
<module>spring-boot-loader</module> <module>spring-boot-loader</module>
<module>spring-boot-loader-tools</module> <module>spring-boot-loader-tools</module>
<module>spring-boot-maven-plugin</module> <module>spring-boot-maven-plugin</module>

@ -0,0 +1,4 @@
# Spring Boot - Dependency Tools
The Spring Boot Dependency Tools module provides support utilities to help when resolving
'blessed' Spring Boot dependencies. It basically provides programmatic access to the
managed dependencies section of `spring-boot-dependencies/pom.xml`

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-tools</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-dependency-tools</artifactId>
<packaging>jar</packaging>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
<generated.pom.dir>${project.build.directory}/generated-resources/org/springframework/boot/dependency/tools</generated.pom.dir>
</properties>
<build>
<resources>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies-pom</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy file="${main.basedir}/spring-boot-dependencies/pom.xml"
tofile="${generated.pom.dir}/dependencies-pom.xml" />
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-help-plugin</artifactId>
<executions>
<execution>
<id>generate-effective-dependencies-pom</id>
<phase>generate-resources</phase>
<goals>
<goal>effective-pom</goal>
</goals>
<configuration>
<output>${generated.pom.dir}/effective-pom.xml</output>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-help-plugin
</artifactId>
<versionRange>
[2.2,)
</versionRange>
<goals>
<goal>effective-pom</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-antrun-plugin
</artifactId>
<versionRange>
[1.7,)
</versionRange>
<goals>
<goal>run</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -0,0 +1,32 @@
/*
* 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.springframework.boot.dependency.tools;
/**
* Simple subset of the Spring Assert utility.
*
* @author Phillip Webb
*/
class Assert {
public static void notNull(Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
}

@ -0,0 +1,234 @@
/*
* 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.springframework.boot.dependency.tools;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* A single managed dependency.
*
* @author Phillip Webb
* @see ManagedDependencies
*/
public final class Dependency {
private final String groupId;
private final String artifactId;
private final String version;
private final List<Exclusion> exclusions;
/**
* Create a new {@link Dependency} instance.
* @param groupId the group ID
* @param artifactId the artifact ID
* @param version the version
*/
public Dependency(String groupId, String artifactId, String version) {
this(groupId, artifactId, version, Collections.<Exclusion> emptyList());
}
/**
* Create a new {@link Dependency} instance.
* @param groupId the group ID
* @param artifactId the artifact ID
* @param version the version
* @param exclusions the exclusions
*/
public Dependency(String groupId, String artifactId, String version,
List<Exclusion> exclusions) {
Assert.notNull(groupId, "GroupId must not be null");
Assert.notNull(artifactId, "ArtifactId must not be null");
Assert.notNull(version, "Version must not be null");
Assert.notNull(exclusions, "Exclusions must not be null");
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.exclusions = Collections.unmodifiableList(exclusions);
}
/**
* Return the dependency group id.
*/
public String getGroupId() {
return this.groupId;
}
/**
* Return the dependency artifact id.
*/
public String getArtifactId() {
return this.artifactId;
}
/**
* Return the dependency version.
*/
public String getVersion() {
return this.version;
}
/**
* Return the dependency exclusions.
*/
public List<Exclusion> getExclusions() {
return this.exclusions;
}
@Override
public String toString() {
return this.groupId + ":" + this.artifactId + ":" + this.version;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.groupId.hashCode();
result = prime * result + this.artifactId.hashCode();
result = prime * result + this.version.hashCode();
result = prime * result + this.exclusions.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() == obj.getClass()) {
Dependency other = (Dependency) obj;
boolean result = true;
result &= this.groupId.equals(other.groupId);
result &= this.artifactId.equals(other.artifactId);
result &= this.version.equals(other.version);
result &= this.exclusions.equals(other.exclusions);
return result;
}
return false;
}
static Dependency fromDependenciesXml(Element element) throws Exception {
String groupId = getTextContent(element, "groupId");
String artifactId = getTextContent(element, "artifactId");
String version = getTextContent(element, "version");
List<Exclusion> exclusions = Exclusion.fromExclusionsXml(element
.getElementsByTagName("exclusions"));
return new Dependency(groupId, artifactId, version, exclusions);
}
private static String getTextContent(Element element, String tagName) {
return element.getElementsByTagName(tagName).item(0).getTextContent();
}
/**
* A dependency exclusion.
*/
public final static class Exclusion {
private final String groupId;
private final String artifactId;
private Exclusion(String groupId, String artifactId) {
Assert.notNull(groupId, "GroupId must not be null");
Assert.notNull(groupId, "ArtifactId must not be null");
this.groupId = groupId;
this.artifactId = artifactId;
}
/**
* Return the exclusion artifact id.
*/
public String getArtifactId() {
return this.artifactId;
}
/**
* Return the exclusion group id.
*/
public String getGroupId() {
return this.groupId;
}
@Override
public String toString() {
return this.groupId + ":" + this.artifactId;
}
@Override
public int hashCode() {
return this.groupId.hashCode() * 31 + this.artifactId.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() == obj.getClass()) {
Exclusion other = (Exclusion) obj;
boolean result = true;
result &= this.groupId.equals(other.groupId);
result &= this.artifactId.equals(other.artifactId);
return result;
}
return false;
}
private static List<Exclusion> fromExclusionsXml(NodeList exclusion) {
if (exclusion == null || exclusion.getLength() == 0) {
return Collections.emptyList();
}
return fromExclusionsXml(exclusion.item(0));
}
private static List<Exclusion> fromExclusionsXml(Node item) {
List<Exclusion> exclusions = new ArrayList<Dependency.Exclusion>();
NodeList children = item.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child instanceof Element) {
exclusions.add(fromExclusionXml((Element) child));
}
}
return exclusions;
}
private static Exclusion fromExclusionXml(Element element) {
String groupId = getTextContent(element, "groupId");
String artifactId = getTextContent(element, "artifactId");
return new Exclusion(groupId, artifactId);
}
}
}

@ -0,0 +1,199 @@
/*
* 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.springframework.boot.dependency.tools;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Provides access to the managed dependencies declared in
* {@literal spring-boot-dependencies}.
*
* @author Phillip Webb
* @see Dependency
*/
public class ManagedDependencies implements Iterable<Dependency> {
private static ManagedDependencies instance;
private final String version;
private final Map<ArtifactAndGroupId, Dependency> byArtifactAndGroupId;
private final Map<String, Dependency> byArtifactId;
ManagedDependencies(String dependenciesPomResource, String effectivePomResource) {
try {
Document dependenciesPomDocument = readDocument(dependenciesPomResource);
this.version = dependenciesPomDocument.getElementsByTagName("version")
.item(0).getTextContent();
// Parse all dependencies from the effective POM (with resolved properties)
Document effectivePomDocument = readDocument(effectivePomResource);
Map<ArtifactAndGroupId, Dependency> all = new HashMap<ArtifactAndGroupId, Dependency>();
for (Dependency dependency : readDependencies(effectivePomDocument)) {
all.put(new ArtifactAndGroupId(dependency), dependency);
}
// But only add those from the dependencies POM
this.byArtifactAndGroupId = new LinkedHashMap<ManagedDependencies.ArtifactAndGroupId, Dependency>();
this.byArtifactId = new LinkedHashMap<String, Dependency>();
for (Dependency dependency : readDependencies(dependenciesPomDocument)) {
ArtifactAndGroupId artifactAndGroupId = new ArtifactAndGroupId(dependency);
Dependency effectiveDependency = all.get(artifactAndGroupId);
if (effectiveDependency != null) {
this.byArtifactAndGroupId
.put(artifactAndGroupId, effectiveDependency);
this.byArtifactId.put(effectiveDependency.getArtifactId(),
effectiveDependency);
}
}
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
private Document readDocument(String resource) throws Exception {
InputStream stream = getClass().getResourceAsStream(resource);
if (stream == null) {
throw new IllegalStateException("Unable to open resource " + resource);
}
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = documentBuilder.parse(stream);
document.getDocumentElement().normalize();
return document;
}
private List<Dependency> readDependencies(Document document) throws Exception {
Element element = (Element) document.getElementsByTagName("project").item(0);
element = (Element) element.getElementsByTagName("dependencyManagement").item(0);
element = (Element) element.getElementsByTagName("dependencies").item(0);
NodeList nodes = element.getChildNodes();
List<Dependency> dependencies = new ArrayList<Dependency>();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node instanceof Element) {
dependencies.add(Dependency.fromDependenciesXml((Element) node));
}
}
return dependencies;
}
/**
* Return the 'spring-boot-dependencies' POM version.
*/
public String getVersion() {
return this.version;
}
/**
* Find a single dependency for the given group and artifact IDs.
* @param groupId the group ID
* @param artifactId the artifact ID
* @return a {@link Dependency} or {@code null}
*/
public Dependency find(String groupId, String artifactId) {
return this.byArtifactAndGroupId.get(new ArtifactAndGroupId(groupId, artifactId));
}
/**
* Find a single dependency for the artifact IDs.
* @param artifactId the artifact ID
* @return a {@link Dependency} or {@code null}
*/
public Dependency find(String artifactId) {
return this.byArtifactId.get(artifactId);
}
/**
* Provide an {@link Iterator} over all managed {@link Dependency Dependencies}.
*/
@Override
public Iterator<Dependency> iterator() {
return this.byArtifactAndGroupId.values().iterator();
}
/**
* @return The Spring Boot managed dependencies.
*/
public static ManagedDependencies get() {
if (instance == null) {
return new ManagedDependencies("dependencies-pom.xml", "effective-pom.xml");
}
return instance;
}
/**
* Simple holder for an artifact+group ID.
*/
private static class ArtifactAndGroupId {
private final String groupId;
private final String artifactId;
public ArtifactAndGroupId(Dependency dependency) {
this(dependency.getGroupId(), dependency.getArtifactId());
}
public ArtifactAndGroupId(String groupId, String artifactId) {
Assert.notNull(groupId, "GroupId must not be null");
Assert.notNull(artifactId, "ArtifactId must not be null");
this.groupId = groupId;
this.artifactId = artifactId;
}
@Override
public int hashCode() {
return this.groupId.hashCode() * 31 + this.artifactId.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() == obj.getClass()) {
ArtifactAndGroupId other = (ArtifactAndGroupId) obj;
boolean result = true;
result &= this.groupId.equals(other.groupId);
result &= this.artifactId.equals(other.artifactId);
return result;
}
return false;
}
}
}

@ -0,0 +1,24 @@
/*
* 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.
*/
/**
* Utilities for working with the managed dependencies declared in the
* {@literal spring-boot-dependencies} project.
*
* @see org.springframework.boot.dependency.tools.ManagedDependencies
*/
package org.springframework.boot.dependency.tools;

@ -0,0 +1,99 @@
/*
* 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.springframework.boot.dependency.tools;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link ManagedDependencies}.
*
* @author Phillip Webb
*/
public class ManagedDependenciesTests {
private ManagedDependencies dependencies;
@Before
public void setup() {
this.dependencies = new ManagedDependencies("test-dependencies-pom.xml",
"test-effective-pom.xml");
}
@Test
public void version() throws Exception {
assertThat(this.dependencies.getVersion(), equalTo("1.0.0.BUILD-SNAPSHOT"));
}
@Test
public void iterate() throws Exception {
Iterator<Dependency> iterator = this.dependencies.iterator();
assertThat(iterator.next().toString(), equalTo("org.sample:sample01:1.0.0"));
assertThat(iterator.next().toString(), equalTo("org.sample:sample02:1.0.0"));
assertThat(iterator.hasNext(), equalTo(false));
}
@Test
public void findByArtifactAndGroupId() throws Exception {
assertThat(this.dependencies.find("org.sample", "sample02").toString(),
equalTo("org.sample:sample02:1.0.0"));
}
@Test
public void findByArtifactAndGroupIdMissing() throws Exception {
assertThat(this.dependencies.find("org.sample", "missing"), nullValue());
}
@Test
public void findByArtifactAndGroupIdOnlyInEffectivePom() throws Exception {
assertThat(this.dependencies.find("org.extra", "extra01"), nullValue());
}
@Test
public void findByArtifactId() throws Exception {
assertThat(this.dependencies.find("sample02").toString(),
equalTo("org.sample:sample02:1.0.0"));
}
@Test
public void findByArtifactIdMissing() throws Exception {
assertThat(this.dependencies.find("missing"), nullValue());
}
@Test
public void exludes() throws Exception {
Dependency dependency = this.dependencies.find("org.sample", "sample01");
assertThat(dependency.getExclusions().toString(),
equalTo("[org.exclude:exclude01]"));
}
@Test
public void get() throws Exception {
ManagedDependencies dependencies = ManagedDependencies.get();
assertThat(dependencies.iterator().hasNext(), equalTo(true));
assertThat(dependencies.find("org.springframework", "spring-core"),
notNullValue());
}
}

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0.BUILD-SNAPSHOT</version>
<properties>
<sample.version>1.0.0</sample.version>
</properties>
<prerequisites>
<maven>3.0.0</maven>
</prerequisites>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sample</groupId>
<artifactId>sample01</artifactId>
<version>${sample.version}</version>
<exclusions>
<exclusion>
<groupId>org.exclude</groupId>
<artifactId>exclude01</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.sample</groupId>
<artifactId>sample02</artifactId>
<version>${sample.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<version>1.0.0.BUILD-SNAPSHOT</version>
<properties>
<sample.version>1.0.0</sample.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sample</groupId>
<artifactId>sample01</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>org.exclude</groupId>
<artifactId>exclude01</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.sample</groupId>
<artifactId>sample02</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.extra</groupId>
<artifactId>extra01</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -1,6 +1,7 @@
# Spring Boot - Gradle Plugin # Spring Boot - Gradle Plugin
The Spring Boot Gradle Plugin provides Spring Boot support in Gradle, allowing you to The Spring Boot Gradle Plugin provides Spring Boot support in Gradle, allowing you to
package executable jar or war archives. package executable jar or war archives, run Spring Boot applications and remove version
information from your `build.gradle` file.
## Including the plugin ## Including the plugin
To use the Spring Boot Gradle Plugin simply include a `buildscript` dependency and apply To use the Spring Boot Gradle Plugin simply include a `buildscript` dependency and apply
@ -27,6 +28,23 @@ buildscript {
} }
``` ```
## Declaring dependencies without versions
The `spring-boot` plugin will register a custom Gradle `ResolutionStrategy` with your
build that allows you to omit version numbers when declaring dependencies to known
artifacts. All artifacts with a `org.springframework.boot` group ID, and any of the
artifacts declared in the `managementDependencies` section of the `spring-dependencies`
POM can have their version number resolved automatically.
Simply declare dependencies in the usual way, but leave the version number empty:
```groovy
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.thymeleaf:thymeleaf-spring4")
compile("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
}
```
## Packaging executable jar and war files ## Packaging executable jar and war files
Once the `spring-boot` plugin has been applied to your project it will automatically Once the `spring-boot` plugin has been applied to your project it will automatically
attempt to rewrite archives to make them executable using the `bootRepackage` task. You attempt to rewrite archives to make them executable using the `bootRepackage` task. You
@ -45,7 +63,6 @@ $ java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
``` ```
### Running a Project in Place ### Running a Project in Place
To run a project in place without building a jar first you can use the "bootRun" task: To run a project in place without building a jar first you can use the "bootRun" task:
``` ```

@ -18,6 +18,11 @@
<artifactId>spring-boot-loader-tools</artifactId> <artifactId>spring-boot-loader-tools</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-boot-dependency-tools</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Provided --> <!-- Provided -->
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>org.codehaus.groovy</groupId>

@ -16,8 +16,10 @@
package org.springframework.boot.gradle; package org.springframework.boot.gradle;
import org.gradle.api.Action;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.Dependency;
import org.gradle.api.plugins.ApplicationPlugin; import org.gradle.api.plugins.ApplicationPlugin;
import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.BasePlugin;
@ -26,8 +28,8 @@ import org.springframework.boot.gradle.task.Repackage;
import org.springframework.boot.gradle.task.RunApp; import org.springframework.boot.gradle.task.RunApp;
/** /**
* Gradle 'Spring Boot' {@link Plugin}. Provides 2 tasks (bootRepackge and bootRun). * Gradle 'Spring Boot' {@link Plugin}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
*/ */
@ -44,19 +46,31 @@ public class SpringBootPlugin implements Plugin<Project> {
project.getPlugins().apply(ApplicationPlugin.class); project.getPlugins().apply(ApplicationPlugin.class);
project.getExtensions().create("springBoot", SpringBootPluginExtension.class); project.getExtensions().create("springBoot", SpringBootPluginExtension.class);
// register BootRepackage so that we can use applyRepackage(project);
// task foo(type: BootRepackage) {} applyRun(project);
project.getExtensions().getExtraProperties().set("BootRepackage", Repackage.class); applyResolutionStrategy(project);
}
private void applyRepackage(Project project) {
Repackage packageTask = addRepackageTask(project); Repackage packageTask = addRepackageTask(project);
ensureTaskRunsOnAssembly(project, packageTask); ensureTaskRunsOnAssembly(project, packageTask);
}
private void applyRun(Project project) {
addRunAppTask(project); addRunAppTask(project);
// register BootRepackage so that we can use task foo(type: BootRepackage) {}
project.getExtensions().getExtraProperties().set("BootRepackage", Repackage.class);
} }
private void addRunAppTask(Project project) { private void applyResolutionStrategy(Project project) {
RunApp runJarTask = project.getTasks().create(RUN_APP_TASK_NAME, RunApp.class); project.getConfigurations().all(new Action<Configuration>() {
runJarTask.setDescription("Run the project with support for auto-detecting main class and reloading static resources");
runJarTask.setGroup("Execution"); @Override
runJarTask.dependsOn("assemble"); public void execute(Configuration configuration) {
SpringBootResolutionStrategy.apply(configuration.getResolutionStrategy());
}
});
} }
private Repackage addRepackageTask(Project project) { private Repackage addRepackageTask(Project project) {
@ -71,6 +85,13 @@ public class SpringBootPlugin implements Plugin<Project> {
return packageTask; return packageTask;
} }
private void addRunAppTask(Project project) {
RunApp runJarTask = project.getTasks().create(RUN_APP_TASK_NAME, RunApp.class);
runJarTask.setDescription("Run the project with support for auto-detecting main class and reloading static resources");
runJarTask.setGroup("Execution");
runJarTask.dependsOn("assemble");
}
private void ensureTaskRunsOnAssembly(Project project, Repackage task) { private void ensureTaskRunsOnAssembly(Project project, Repackage task) {
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task); project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
} }

@ -39,8 +39,19 @@ import org.springframework.boot.loader.tools.Layouts
public class SpringBootPluginExtension { public class SpringBootPluginExtension {
static enum LayoutType { static enum LayoutType {
JAR(new Layouts.Jar()), WAR(new Layouts.War()), ZIP(new Layouts.Expanded()), DIR(new Layouts.Expanded()), NONE(new Layouts.None());
JAR(new Layouts.Jar()),
WAR(new Layouts.War()),
ZIP(new Layouts.Expanded()),
DIR(new Layouts.Expanded()),
NONE(new Layouts.None());
Layout layout; Layout layout;
private LayoutType(Layout layout) { private LayoutType(Layout layout) {
this.layout = layout; this.layout = layout;
} }
@ -85,6 +96,6 @@ public class SpringBootPluginExtension {
* @return the Layout to use or null if not explicitly set * @return the Layout to use or null if not explicitly set
*/ */
Layout convertLayout() { Layout convertLayout() {
layout==null ? null : layout.layout (layout == null ? null : layout.layout)
} }
} }

@ -0,0 +1,51 @@
package org.springframework.boot.gradle;
import org.gradle.api.Action;
import org.gradle.api.artifacts.DependencyResolveDetails;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.ResolutionStrategy;
import org.springframework.boot.dependency.tools.Dependency;
import org.springframework.boot.dependency.tools.ManagedDependencies;
/**
* A resolution strategy to resolve missing version numbers using the
* 'spring-boot-dependencies' POM.
*
* @author Phillip Webb
*/
public class SpringBootResolutionStrategy {
private static final String SPRING_BOOT_GROUP = "org.springframework.boot";
public static void apply(ResolutionStrategy resolutionStrategy) {
resolutionStrategy.eachDependency(new Action<DependencyResolveDetails>() {
@Override
public void execute(DependencyResolveDetails resolveDetails) {
String version = resolveDetails.getTarget().getVersion();
if (version == null || version.trim().length() == 0) {
resolve(resolveDetails);
}
}
});
}
protected static void resolve(DependencyResolveDetails resolveDetails) {
ManagedDependencies dependencies = ManagedDependencies.get();
ModuleVersionSelector target = resolveDetails.getTarget();
if (SPRING_BOOT_GROUP.equals(target.getGroup())) {
resolveDetails.useVersion(dependencies.getVersion());
return;
}
Dependency dependency = dependencies.find(target.getGroup(), target.getName());
if (dependency != null) {
resolveDetails.useVersion(dependency.getVersion());
}
}
}

@ -36,7 +36,7 @@ import org.springframework.boot.loader.tools.MainClassFinder;
/** /**
* Run the project from Gradle. * Run the project from Gradle.
* *
* @author Dave Syer * @author Dave Syer
*/ */
public class RunApp extends DefaultTask { public class RunApp extends DefaultTask {
@ -57,6 +57,7 @@ public class RunApp extends DefaultTask {
main = set; main = set;
} }
}; };
}); });
final Set<File> allResources = new LinkedHashSet<File>(); final Set<File> allResources = new LinkedHashSet<File>();

Loading…
Cancel
Save