Support for non-executable JAR in addition to the repackaged one
Stretches the Gradle boot plugin a bit, so there's a sample build in the "profile" sample. Howto docs give examples. Fixes gh-1135
This commit is contained in:
parent
1b97e8d921
commit
542896b28f
|
|
@ -404,6 +404,10 @@ The following configuration options are available:
|
|||
|===
|
||||
|Name |Description
|
||||
|
||||
|`enabled`
|
||||
|Boolean flag to switch the repackager off (sometimes useful if you
|
||||
want the other Boot features but not this one)
|
||||
|
||||
|`mainClass`
|
||||
|The main class that should be run. If not specified the `mainClassName` project property
|
||||
will be used or, if the no `mainClassName` id defined the archive will be searched for a
|
||||
|
|
@ -419,9 +423,10 @@ The following configuration options are available:
|
|||
the original jar as a dependency in another project, it's best to use an extension to
|
||||
define the executable archive.
|
||||
|
||||
|`withJarTask`
|
||||
|The name of the `Jar` task (defaults to all) which is used to locate the archive to
|
||||
repackage.
|
||||
|`withJarTask`
|
||||
|The name or value of the `Jar` task (defaults to all
|
||||
tasks of type `Jar`) which is used to locate the archive to
|
||||
repackage.
|
||||
|
||||
|`customConfiguration`
|
||||
|The name of the custom configuration whuch is used to populate the nested lib directory
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,122 @@ See the {spring-boot-maven-plugin-site}/usage.html[plugin documentation] for ful
|
|||
details.
|
||||
|
||||
|
||||
[[howto-create-an-additional-executable-jar]]
|
||||
=== Create an additional executable JAR
|
||||
|
||||
If you want to use your project as a library jar for other projects to
|
||||
depend on, and in addition have an executable (e.g. demo) version of
|
||||
it, you will want to configure the build in a slightly different way.
|
||||
|
||||
For Maven the normal JAR plugin and the Spring Boot plugin both have a
|
||||
"classifier" configuration that you can add to create an additional JAR.
|
||||
Example (using the Spring Boot Starter Parent to manage the plugin
|
||||
versions and other configuration defaults):
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
Two jars are produced, the default one, and an executable one using
|
||||
the Boot plugin with classifier "exec".
|
||||
|
||||
For Gradle users the steps are similar. Example:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
bootRepackage {
|
||||
classifier = 'exec'
|
||||
}
|
||||
----
|
||||
|
||||
[[howto-create-a-nonexecutable-jar]]
|
||||
=== Create a non-executable JAR with exclusions
|
||||
|
||||
Often if you have an executable and a non-executable jar
|
||||
as biuld products, the executable version will have additional
|
||||
configuration files that ar enot needed in a library jar. E.g. the
|
||||
`application.yml` configuration file might excluded from the
|
||||
non-executable JAR.
|
||||
|
||||
Here's how to do that in Maven
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>exec</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- Need this to ensure application.yml is excluded -->
|
||||
<forceCreation>true</forceCreation>
|
||||
<excludes>
|
||||
<exclude>application.yml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
In Gradle you can create a new JAR archive with standard task DSL
|
||||
features, and then have the `bootRepackage` task depend on that one
|
||||
using its `withJarTask` property:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
jar {
|
||||
baseName = 'spring-boot-sample-profile'
|
||||
version = '0.0.0'
|
||||
excludes = ['**/application.yml']
|
||||
}
|
||||
|
||||
task('execJar', type:Jar, dependsOn: 'jar') {
|
||||
baseName = 'spring-boot-sample-profile'
|
||||
version = '0.0.0'
|
||||
classifier = 'exec'
|
||||
from sourceSets.main.output
|
||||
}
|
||||
|
||||
bootRepackage {
|
||||
withJarTask = tasks['execJar']
|
||||
}
|
||||
----
|
||||
|
||||
[[howto-remote-debug-maven-run]]
|
||||
=== Remote debug a Spring Boot application started with Maven
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
buildscript {
|
||||
ext {
|
||||
springBootVersion = '1.1.2.BUILD-SNAPSHOT'
|
||||
}
|
||||
repositories {
|
||||
// NOTE: You should declare only repositories that you need here
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven { url "http://repo.spring.io/release" }
|
||||
maven { url "http://repo.spring.io/milestone" }
|
||||
maven { url "http://repo.spring.io/snapshot" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'spring-boot'
|
||||
|
||||
jar {
|
||||
baseName = 'spring-boot-sample-profile'
|
||||
version = '0.0.0'
|
||||
excludes = ['**/application.yml']
|
||||
}
|
||||
|
||||
task('execJar', type:Jar, dependsOn: 'jar') {
|
||||
baseName = 'spring-boot-sample-profile'
|
||||
version = '0.0.0'
|
||||
classifier = 'exec'
|
||||
from sourceSets.main.output
|
||||
}
|
||||
|
||||
bootRepackage {
|
||||
withJarTask = tasks['execJar']
|
||||
}
|
||||
|
||||
repositories {
|
||||
// NOTE: You should declare only repositories that you need here
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven { url "http://repo.spring.io/release" }
|
||||
maven { url "http://repo.spring.io/milestone" }
|
||||
maven { url "http://repo.spring.io/snapshot" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile("org.springframework.boot:spring-boot-starter")
|
||||
testCompile("org.springframework.boot:spring-boot-starter-test")
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.6'
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?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">
|
||||
<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>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
|
|
@ -34,6 +35,37 @@
|
|||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>exec</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- Need this to ensure application.yml is excluded -->
|
||||
<forceCreation>true</forceCreation>
|
||||
<excludes>
|
||||
<exclude>application.yml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
|
|
|||
|
|
@ -50,18 +50,22 @@ public class RepackagePluginFeatures implements PluginFeatures {
|
|||
+ "archives so that they can be executed from the command "
|
||||
+ "line using 'java -jar'");
|
||||
task.setGroup(BasePlugin.BUILD_GROUP);
|
||||
task.dependsOn(project.getConfigurations()
|
||||
.getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts()
|
||||
.getBuildDependencies());
|
||||
task.dependsOn(project.getConfigurations().getByName(
|
||||
Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts().getBuildDependencies());
|
||||
registerOutput(project, task);
|
||||
ensureTaskRunsOnAssembly(project, task);
|
||||
}
|
||||
|
||||
private void registerOutput(Project project, final RepackageTask task) {
|
||||
project.afterEvaluate(new Action<Project>() {
|
||||
|
||||
@Override
|
||||
public void execute(Project project) {
|
||||
project.getTasks().withType(Jar.class, new OutputAction(task));
|
||||
Object withJar = task.getWithJarTask();
|
||||
if (withJar!=null) {
|
||||
task.dependsOn(withJar);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -74,8 +78,8 @@ public class RepackagePluginFeatures implements PluginFeatures {
|
|||
* Register BootRepackage so that we can use task {@code foo(type: BootRepackage)}.
|
||||
*/
|
||||
private void registerRepackageTaskProperty(Project project) {
|
||||
project.getExtensions().getExtraProperties()
|
||||
.set("BootRepackage", RepackageTask.class);
|
||||
project.getExtensions().getExtraProperties().set("BootRepackage",
|
||||
RepackageTask.class);
|
||||
}
|
||||
|
||||
private class OutputAction implements Action<Jar> {
|
||||
|
|
@ -115,8 +119,7 @@ public class RepackagePluginFeatures implements PluginFeatures {
|
|||
SpringBootPluginExtension.class);
|
||||
if (task.getClassifier() != null) {
|
||||
classifier = task.getClassifier();
|
||||
}
|
||||
else if (extension.getClassifier() != null) {
|
||||
} else if (extension.getClassifier() != null) {
|
||||
classifier = extension.getClassifier();
|
||||
}
|
||||
if (classifier != null) {
|
||||
|
|
|
|||
|
|
@ -53,10 +53,16 @@ public class RepackageTask extends DefaultTask {
|
|||
|
||||
private File outputFile;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
public void setCustomConfiguration(String customConfiguration) {
|
||||
this.customConfiguration = customConfiguration;
|
||||
}
|
||||
|
||||
public Object getWithJarTask() {
|
||||
return withJarTask;
|
||||
}
|
||||
|
||||
public void setWithJarTask(Object withJarTask) {
|
||||
this.withJarTask = withJarTask;
|
||||
}
|
||||
|
|
@ -77,6 +83,14 @@ public class RepackageTask extends DefaultTask {
|
|||
this.classifier = classifier;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void repackage() {
|
||||
Project project = getProject();
|
||||
|
|
@ -85,12 +99,13 @@ public class RepackageTask extends DefaultTask {
|
|||
ProjectLibraries libraries = getLibraries();
|
||||
project.getTasks().withType(Jar.class, new RepackageAction(extension, libraries));
|
||||
}
|
||||
|
||||
|
||||
public File[] getDependencies() {
|
||||
ProjectLibraries libraries = getLibraries();
|
||||
final List<File> files = new ArrayList<File>();
|
||||
try {
|
||||
libraries.doWithLibraries(new LibraryCallback() {
|
||||
|
||||
@Override
|
||||
public void library(File file, LibraryScope scope) throws IOException {
|
||||
files.add(file);
|
||||
|
|
@ -112,8 +127,7 @@ public class RepackageTask extends DefaultTask {
|
|||
}
|
||||
if (this.customConfiguration != null) {
|
||||
libraries.setCustomConfigurationName(this.customConfiguration);
|
||||
}
|
||||
else if (extension.getCustomConfiguration() != null) {
|
||||
} else if (extension.getCustomConfiguration() != null) {
|
||||
libraries.setCustomConfigurationName(extension.getCustomConfiguration());
|
||||
}
|
||||
return libraries;
|
||||
|
|
@ -133,22 +147,30 @@ public class RepackageTask extends DefaultTask {
|
|||
|
||||
@Override
|
||||
public void execute(Jar archive) {
|
||||
if (!enabled) {
|
||||
getLogger().info("Repackage disabled");
|
||||
return;
|
||||
}
|
||||
// if withJarTask is set, compare tasks and bail out if we didn't match
|
||||
if (RepackageTask.this.withJarTask != null
|
||||
&& !archive.equals(RepackageTask.this.withJarTask)) {
|
||||
&& !(archive.equals(RepackageTask.this.withJarTask)
|
||||
|| archive.equals(getProject().getTasks().findByName(
|
||||
RepackageTask.this.withJarTask.toString())))) {
|
||||
getLogger().info(
|
||||
"Jar task not repackaged (didn't match withJarTask): " + archive);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("".equals(archive.getClassifier())) {
|
||||
if ("".equals(archive.getClassifier())
|
||||
|| RepackageTask.this.withJarTask != null) {
|
||||
File file = archive.getArchivePath();
|
||||
if (file.exists()) {
|
||||
Repackager repackager = new LoggingRepackager(file);
|
||||
File out = RepackageTask.this.outputFile;
|
||||
if (out != null) {
|
||||
if (out != null && !file.equals(out)) {
|
||||
try {
|
||||
FileCopyUtils.copy(file, out);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalStateException(ex.getMessage(), ex);
|
||||
}
|
||||
file = out;
|
||||
|
|
@ -161,8 +183,7 @@ public class RepackageTask extends DefaultTask {
|
|||
repackager.setBackupSource(this.extension.isBackupSource());
|
||||
try {
|
||||
repackager.repackage(file, this.libraries);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalStateException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
|
@ -173,13 +194,11 @@ public class RepackageTask extends DefaultTask {
|
|||
String mainClass = (String) getProject().property("mainClassName");
|
||||
if (RepackageTask.this.mainClass != null) {
|
||||
mainClass = RepackageTask.this.mainClass;
|
||||
}
|
||||
else if (this.extension.getMainClass() != null) {
|
||||
} else if (this.extension.getMainClass() != null) {
|
||||
mainClass = this.extension.getMainClass();
|
||||
}
|
||||
else if (getProject().getTasks().getByName("run").hasProperty("main")) {
|
||||
mainClass = (String) getProject().getTasks().getByName("run")
|
||||
.property("main");
|
||||
} else if (getProject().getTasks().getByName("run").hasProperty("main")) {
|
||||
mainClass = (String) getProject().getTasks().getByName("run").property(
|
||||
"main");
|
||||
}
|
||||
getLogger().info("Setting mainClass: " + mainClass);
|
||||
repackager.setMainClass(mainClass);
|
||||
|
|
@ -197,8 +216,7 @@ public class RepackageTask extends DefaultTask {
|
|||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
return super.findMainMethod(source);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
if (duration > FIND_WARNING_TIMEOUT) {
|
||||
getLogger().warn(
|
||||
|
|
|
|||
Loading…
Reference in New Issue