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
This commit is contained in:
Phillip Webb
2014-01-24 17:37:21 -08:00
parent 19ca4d4eae
commit ab4baa3c43
17 changed files with 901 additions and 18 deletions

View File

@@ -1,6 +1,7 @@
# Spring Boot - Gradle Plugin
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
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
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
@@ -45,7 +63,6 @@ $ java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
```
### Running a Project in Place
To run a project in place without building a jar first you can use the "bootRun" task:
```

View File

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

View File

@@ -16,8 +16,10 @@
package org.springframework.boot.gradle;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.plugins.ApplicationPlugin;
import org.gradle.api.plugins.BasePlugin;
@@ -26,8 +28,8 @@ import org.springframework.boot.gradle.task.Repackage;
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 Dave Syer
*/
@@ -44,19 +46,31 @@ public class SpringBootPlugin implements Plugin<Project> {
project.getPlugins().apply(ApplicationPlugin.class);
project.getExtensions().create("springBoot", SpringBootPluginExtension.class);
// register BootRepackage so that we can use
// task foo(type: BootRepackage) {}
project.getExtensions().getExtraProperties().set("BootRepackage", Repackage.class);
Repackage packageTask = addRepackageTask(project);
ensureTaskRunsOnAssembly(project, packageTask);
addRunAppTask(project);
applyRepackage(project);
applyRun(project);
applyResolutionStrategy(project);
}
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 applyRepackage(Project project) {
Repackage packageTask = addRepackageTask(project);
ensureTaskRunsOnAssembly(project, packageTask);
}
private void applyRun(Project project) {
addRunAppTask(project);
// register BootRepackage so that we can use task foo(type: BootRepackage) {}
project.getExtensions().getExtraProperties().set("BootRepackage", Repackage.class);
}
private void applyResolutionStrategy(Project project) {
project.getConfigurations().all(new Action<Configuration>() {
@Override
public void execute(Configuration configuration) {
SpringBootResolutionStrategy.apply(configuration.getResolutionStrategy());
}
});
}
private Repackage addRepackageTask(Project project) {
@@ -71,6 +85,13 @@ public class SpringBootPlugin implements Plugin<Project> {
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) {
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
}

View File

@@ -39,8 +39,19 @@ import org.springframework.boot.loader.tools.Layouts
public class SpringBootPluginExtension {
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;
private LayoutType(Layout layout) {
this.layout = layout;
}
@@ -85,6 +96,6 @@ public class SpringBootPluginExtension {
* @return the Layout to use or null if not explicitly set
*/
Layout convertLayout() {
layout==null ? null : layout.layout
(layout == null ? null : layout.layout)
}
}

View File

@@ -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());
}
}
}

View File

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