Add a command to produce a self-contained executable JAR for a CLI app
A new command, jar, has been added to the CLI. The command can be used to create a self-contained executable JAR file from a CLI app. Basic usage is: spring jar <jar-name> <source-files> For example: spring jar my-app.jar *.groovy The resulting jar will contain the classes generated by compiling the source files, all of the application's dependencies, and entries on the application's classpath. By default a CLI application has the current working directory on its classpath. This can be overridden using the --classpath option. Any file that is referenced directly by the classpath is always included in the jar. Any file that is found a result of being contained within a directory that is on the classpath is subject to filtering to determine whether or not it should be included. The default includes are public/**, static/**, resources/**, META-INF/**, *. The default excludes are .*, repository/**, build/**, target/**. To be included in the jar, a file must match one of the includes and none of the excludes. The filters can be overridden using the --include and --exclude options. Closes #241
This commit is contained in:
@@ -43,7 +43,7 @@ public class CommandLineIT {
|
||||
Invocation cli = this.cli.invoke("hint");
|
||||
assertThat(cli.await(), equalTo(0));
|
||||
assertThat(cli.getErrorOutput().length(), equalTo(0));
|
||||
assertThat(cli.getStandardOutputLines().size(), equalTo(6));
|
||||
assertThat(cli.getStandardOutputLines().size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
|
||||
import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JarCommandIT {
|
||||
|
||||
private final CommandLineInvoker cli = new CommandLineInvoker(new File(
|
||||
"src/it/resources/jar-command"));
|
||||
|
||||
@Test
|
||||
public void noArguments() throws Exception {
|
||||
Invocation invocation = this.cli.invoke("jar");
|
||||
invocation.await();
|
||||
assertEquals(0, invocation.getStandardOutput().length());
|
||||
assertEquals(
|
||||
"The name of the resulting jar and at least one source file must be specified",
|
||||
invocation.getErrorOutput().trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSources() throws Exception {
|
||||
Invocation invocation = this.cli.invoke("jar", "test-app.jar");
|
||||
invocation.await();
|
||||
assertEquals(0, invocation.getStandardOutput().length());
|
||||
assertEquals(
|
||||
"The name of the resulting jar and at least one source file must be specified",
|
||||
invocation.getErrorOutput().trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jarCreation() throws Exception {
|
||||
File jar = new File("target/test-app.jar");
|
||||
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(),
|
||||
"jar.groovy");
|
||||
invocation.await();
|
||||
assertEquals(0, invocation.getErrorOutput().length());
|
||||
assertTrue(jar.exists());
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(System.getProperty("java.home")
|
||||
+ "/bin/java", "-jar", jar.getAbsolutePath());
|
||||
Process process = builder.start();
|
||||
Invocation appInvocation = new Invocation(process);
|
||||
appInvocation.await();
|
||||
|
||||
assertEquals(0, appInvocation.getErrorOutput().length());
|
||||
assertTrue(appInvocation.getStandardOutput().contains("Hello World!"));
|
||||
assertTrue(appInvocation.getStandardOutput().contains("/static/test.txt"));
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,16 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class CommandLineInvoker {
|
||||
|
||||
private final File workingDirectory;
|
||||
|
||||
public CommandLineInvoker() {
|
||||
this(new File("."));
|
||||
}
|
||||
|
||||
public CommandLineInvoker(File workingDirectory) {
|
||||
this.workingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
public Invocation invoke(String... args) throws IOException {
|
||||
return new Invocation(runCliProcess(args));
|
||||
}
|
||||
@@ -45,7 +55,7 @@ public final class CommandLineInvoker {
|
||||
List<String> command = new ArrayList<String>();
|
||||
command.add(findLaunchScript().getAbsolutePath());
|
||||
command.addAll(Arrays.asList(args));
|
||||
return new ProcessBuilder(command).start();
|
||||
return new ProcessBuilder(command).directory(this.workingDirectory).start();
|
||||
}
|
||||
|
||||
private File findLaunchScript() {
|
||||
@@ -70,9 +80,9 @@ public final class CommandLineInvoker {
|
||||
}
|
||||
|
||||
/**
|
||||
* An ongoing CLI invocation.
|
||||
* An ongoing Process invocation.
|
||||
*/
|
||||
public final class Invocation {
|
||||
public static final class Invocation {
|
||||
|
||||
private final StringBuffer err = new StringBuffer();
|
||||
|
||||
@@ -80,7 +90,7 @@ public final class CommandLineInvoker {
|
||||
|
||||
private final Process process;
|
||||
|
||||
Invocation(Process process) {
|
||||
public Invocation(Process process) {
|
||||
this.process = process;
|
||||
new Thread(new StreamReadingRunnable(this.process.getErrorStream(), this.err))
|
||||
.start();
|
||||
|
||||
21
spring-boot-cli/src/it/resources/jar-command/jar.groovy
Normal file
21
spring-boot-cli/src/it/resources/jar-command/jar.groovy
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.test
|
||||
|
||||
@Component
|
||||
class Example implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private MyService myService
|
||||
|
||||
void run(String... args) {
|
||||
println "Hello ${this.myService.sayWorld()}"
|
||||
println getClass().getResource('/static/test.txt')
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
class MyService {
|
||||
|
||||
String sayWorld() {
|
||||
return 'World!'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user