diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/AstUtils.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/AstUtils.java index 9eaba3eb41..4a4e68f721 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/AstUtils.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/AstUtils.java @@ -34,6 +34,7 @@ import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.Statement; +import org.springframework.util.PatternMatchUtils; /** * General purpose AST utilities. @@ -69,7 +70,7 @@ public abstract class AstUtils { String... annotations) { for (AnnotationNode annotationNode : node.getAnnotations()) { for (String annotation : annotations) { - if (annotation.equals(annotationNode.getClassNode().getName())) { + if (PatternMatchUtils.simpleMatch(annotation, annotationNode.getClassNode().getName())) { return true; } } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java index 12c6ff34f6..490f5755f1 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GroovyCompiler.java @@ -191,8 +191,8 @@ public class GroovyCompiler { for (Object loadedClass : collector.getLoadedClasses()) { classes.add((Class) loadedClass); } - ClassNode mainClassNode = (ClassNode) compilationUnit.getAST().getClasses() - .get(0); + ClassNode mainClassNode = getMainClass(compilationUnit); + Class mainClass = null; for (Class loadedClass : classes) { if (mainClassNode.getName().equals(loadedClass.getName())) { @@ -265,6 +265,7 @@ public class GroovyCompiler { throws CompilationFailedException { ImportCustomizer importCustomizer = new ImportCustomizer(); + ClassNode mainClassNode = getMainClass(source.getAST().getClasses()); // Additional auto configuration for (CompilerAutoConfiguration autoConfiguration : GroovyCompiler.this.compilerAutoConfigurations) { @@ -273,8 +274,7 @@ public class GroovyCompiler { autoConfiguration.applyImports(importCustomizer); importCustomizer.call(source, context, classNode); } - if (source.getAST().getClasses().size() > 0 - && classNode.equals(source.getAST().getClasses().get(0))) { + if (classNode.equals(mainClassNode)) { autoConfiguration.applyToMainClass(GroovyCompiler.this.loader, GroovyCompiler.this.configuration, context, source, classNode); @@ -290,4 +290,23 @@ public class GroovyCompiler { } + @SuppressWarnings("unchecked") + private static ClassNode getMainClass(CompilationUnit source) { + return getMainClass((List) source.getAST().getClasses()); + } + + private static ClassNode getMainClass(List classes) { + for (ClassNode node : classes) { + if (AstUtils.hasAtLeastOneAnnotation(node, "Enable*AutoConfiguration")) { + return null; // No need to enhance this + } + if (AstUtils.hasAtLeastOneAnnotation(node, "*Controller", "Configuration", + "Component", "*Service", "Repository", "Enable*")) { + return node; + } + } + return classes.isEmpty() ? null : classes.get(0); + + } + } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/ReactorCompilerAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/ReactorCompilerAutoConfiguration.java index 4b019bdd30..baec6158b4 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/ReactorCompilerAutoConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/ReactorCompilerAutoConfiguration.java @@ -31,7 +31,7 @@ public class ReactorCompilerAutoConfiguration extends CompilerAutoConfiguration @Override public boolean matches(ClassNode classNode) { - return AstUtils.hasAtLeastOneAnnotation(classNode, "EnableReactor"); + return AstUtils.hasAtLeastOneAnnotation(classNode, "EnableReactor") || AstUtils.hasAtLeastOneFieldOrMethod(classNode, "Reactor"); } @Override diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringBootCompilerAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringBootCompilerAutoConfiguration.java index bb2e403268..9bd197c663 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringBootCompilerAutoConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringBootCompilerAutoConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.boot.cli.compiler.autoconfigure; import groovy.lang.GroovyClassLoader; import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.CompilationFailedException; @@ -79,16 +80,9 @@ public class SpringBootCompilerAutoConfiguration extends CompilerAutoConfigurati private void addEnableAutoConfigurationAnnotation(SourceUnit source, ClassNode classNode) { if (!hasEnableAutoConfigureAnnotation(classNode)) { - try { - Class annotationClass = source.getClassLoader().loadClass( - "org.springframework.boot.autoconfigure.EnableAutoConfiguration"); - AnnotationNode annotationNode = new AnnotationNode(new ClassNode( - annotationClass)); - classNode.addAnnotation(annotationNode); - } - catch (ClassNotFoundException ex) { - throw new IllegalStateException(ex); - } + AnnotationNode annotationNode = new AnnotationNode( + ClassHelper.make("EnableAutoConfiguration")); + classNode.addAnnotation(annotationNode); } } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringTestCompilerAutoConfiguration.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringTestCompilerAutoConfiguration.java index 1c3d8eb640..20806874ad 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringTestCompilerAutoConfiguration.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/autoconfigure/SpringTestCompilerAutoConfiguration.java @@ -35,21 +35,27 @@ import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; * * @author Dave Syer */ -public class SpringTestCompilerAutoConfiguration extends CompilerAutoConfiguration { +public class SpringTestCompilerAutoConfiguration extends + CompilerAutoConfiguration { @Override public boolean matches(ClassNode classNode) { - return AstUtils.hasAtLeastOneAnnotation(classNode, "SpringApplicationConfiguration"); + return AstUtils.hasAtLeastOneAnnotation(classNode, + "SpringApplicationConfiguration"); } - + @Override public void apply(GroovyClassLoader loader, GroovyCompilerConfiguration configuration, GeneratorContext generatorContext, SourceUnit source, ClassNode classNode) throws CompilationFailedException { if (!AstUtils.hasAtLeastOneAnnotation(classNode, "RunWith")) { - AnnotationNode runwith = new AnnotationNode(ClassHelper.make("RunWith")); - runwith.addMember("value", new ClassExpression(ClassHelper.make("SpringJUnit4ClassRunner"))); + AnnotationNode runwith = new AnnotationNode( + ClassHelper.make("RunWith")); + runwith.addMember( + "value", + new ClassExpression(ClassHelper + .make("SpringJUnit4ClassRunner"))); classNode.addAnnotation(runwith); } } @@ -59,6 +65,8 @@ public class SpringTestCompilerAutoConfiguration extends CompilerAutoConfigurati throws CompilationFailedException { imports.addStarImports("org.junit.runner") .addStarImports("org.springframework.boot.test") - .addStarImports("org.springframework.test.context.junit4"); + .addStarImports("org.springframework.test.context.junit4") + .addImports( + "org.springframework.test.context.web.WebAppConfiguration"); } } diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/TestCommandIntegrationTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/TestCommandIntegrationTests.java index fd7aefa9b8..6409035097 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/TestCommandIntegrationTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/TestCommandIntegrationTests.java @@ -88,6 +88,18 @@ public class TestCommandIntegrationTests { assertThat(output, containsString("OK (1 test)")); } + @Test + public void integrationAutoConfigEmbeddedTest() throws Exception { + String output = this.cli.test("integration_auto.groovy"); + assertThat(output, containsString("OK (1 test)")); + } + + @Test + public void integrationAutoConfigTest() throws Exception { + String output = this.cli.test("integration_auto_test.groovy", "reactor.groovy"); + assertThat(output, containsString("OK (1 test)")); + } + @Test public void spockTester() throws Exception { String output = this.cli.test("spock.groovy"); diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoaderTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoaderTests.java index 76e97af497..6e9524be0b 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoaderTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/compiler/ExtendedGroovyClassLoaderTests.java @@ -53,7 +53,7 @@ public class ExtendedGroovyClassLoaderTests { } @Test - public void filteresNonGroovy() throws Exception { + public void filtersNonGroovy() throws Exception { this.contextClassLoader.loadClass("org.springframework.util.StringUtils"); this.thrown.expect(ClassNotFoundException.class); this.defaultScopeGroovyClassLoader diff --git a/spring-boot-cli/test-samples/integration_auto.groovy b/spring-boot-cli/test-samples/integration_auto.groovy new file mode 100644 index 0000000000..71b90c5d16 --- /dev/null +++ b/spring-boot-cli/test-samples/integration_auto.groovy @@ -0,0 +1,19 @@ +@SpringApplicationConfiguration(classes=Application) +@IntegrationTest('server.port:0') +@WebAppConfiguration +class RestTests { + + @Value('${local.server.port}') + int port + + @Test + void testHome() { + assertEquals('Hello', new TestRestTemplate().getForObject('http://localhost:' + port, String)) + } + + @RestController + static class Application { + @RequestMapping('/') + String hello() { 'Hello' } + } +} diff --git a/spring-boot-cli/test-samples/integration_auto_test.groovy b/spring-boot-cli/test-samples/integration_auto_test.groovy new file mode 100644 index 0000000000..069069af0c --- /dev/null +++ b/spring-boot-cli/test-samples/integration_auto_test.groovy @@ -0,0 +1,13 @@ +@SpringApplicationConfiguration(classes=ReactorApplication) +@IntegrationTest('server.port:0') +class RestTests { + + @Autowired + Reactor reactor + + @Test + void test() { + assertNotNull(reactor) + } + +} diff --git a/spring-boot-cli/test-samples/reactor.groovy b/spring-boot-cli/test-samples/reactor.groovy new file mode 100644 index 0000000000..d009bc6aa9 --- /dev/null +++ b/spring-boot-cli/test-samples/reactor.groovy @@ -0,0 +1,4 @@ +@Configuration +@EnableReactor +class ReactorApplication { +}