diff --git a/http/src/main/java/io/micronaut/http/annotation/Controller.java b/http/src/main/java/io/micronaut/http/annotation/Controller.java index 37c1862b323..75c06150fe6 100644 --- a/http/src/main/java/io/micronaut/http/annotation/Controller.java +++ b/http/src/main/java/io/micronaut/http/annotation/Controller.java @@ -20,7 +20,6 @@ import io.micronaut.context.annotation.AliasFor; import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.DefaultScope; -import io.micronaut.context.annotation.Executable; import io.micronaut.http.MediaType; import javax.inject.Singleton; @@ -31,9 +30,6 @@ /** *

Indicates that the role of a class is a controller within an application.

- *

- *

By default all public methods of a controller are considered {@link Executable} and - * the necessary classes generated to perform the invocation.

* * @author Graeme Rocher * @since 1.0 @@ -42,7 +38,6 @@ @Retention(RUNTIME) @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Bean -@Executable @DefaultScope(Singleton.class) public @interface Controller { diff --git a/http/src/main/java/io/micronaut/http/annotation/Filter.java b/http/src/main/java/io/micronaut/http/annotation/Filter.java index 0bf8414086a..02775203410 100644 --- a/http/src/main/java/io/micronaut/http/annotation/Filter.java +++ b/http/src/main/java/io/micronaut/http/annotation/Filter.java @@ -16,7 +16,6 @@ package io.micronaut.http.annotation; import io.micronaut.context.annotation.AliasFor; -import io.micronaut.context.annotation.Executable; import io.micronaut.http.HttpMethod; import javax.inject.Singleton; @@ -40,7 +39,6 @@ @Documented @Retention(RUNTIME) @Target(ElementType.TYPE) -@Executable public @interface Filter { /** diff --git a/http/src/main/java/io/micronaut/http/annotation/Status.java b/http/src/main/java/io/micronaut/http/annotation/Status.java index 294907e9111..7cbf471aace 100644 --- a/http/src/main/java/io/micronaut/http/annotation/Status.java +++ b/http/src/main/java/io/micronaut/http/annotation/Status.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.annotation; +import io.micronaut.context.annotation.Executable; import io.micronaut.http.HttpStatus; import java.lang.annotation.Documented; @@ -33,6 +34,7 @@ @Documented @Retention(RUNTIME) @Target({ElementType.METHOD}) +@Executable public @interface Status { /** diff --git a/inject-groovy/src/test/groovy/io/micronaut/inject/executable/ExecutableBeanSpec.groovy b/inject-groovy/src/test/groovy/io/micronaut/inject/executable/ExecutableBeanSpec.groovy index b58e5780fac..230b187767e 100644 --- a/inject-groovy/src/test/groovy/io/micronaut/inject/executable/ExecutableBeanSpec.groovy +++ b/inject-groovy/src/test/groovy/io/micronaut/inject/executable/ExecutableBeanSpec.groovy @@ -20,6 +20,29 @@ import io.micronaut.inject.BeanDefinition class ExecutableBeanSpec extends AbstractBeanDefinitionSpec { + void "test executable on stereotype"() { + given: + BeanDefinition definition = buildBeanDefinition('test.ExecutableController','''\ +package test; + +import io.micronaut.inject.annotation.*; +import io.micronaut.context.annotation.*; +import io.micronaut.http.annotation.Get; + +@javax.inject.Singleton +class ExecutableController { + + @Get("/round") + public int round(float num) { + return Math.round(num); + } +} +''') + expect: + definition != null + definition.findMethod("round", float.class).get().returnType.type == int.class + } + void "test executable method return types"() { given: BeanDefinition definition = buildBeanDefinition('test.ExecutableBean1','''\ diff --git a/messaging/src/main/java/io/micronaut/messaging/annotation/MessageListener.java b/messaging/src/main/java/io/micronaut/messaging/annotation/MessageListener.java index 579edda2068..3f7902392ae 100644 --- a/messaging/src/main/java/io/micronaut/messaging/annotation/MessageListener.java +++ b/messaging/src/main/java/io/micronaut/messaging/annotation/MessageListener.java @@ -17,8 +17,6 @@ import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.DefaultScope; -import io.micronaut.context.annotation.Executable; - import javax.inject.Singleton; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -38,7 +36,6 @@ @Retention(RUNTIME) @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) @Bean -@Executable(processOnStartup = true) @DefaultScope(Singleton.class) public @interface MessageListener { } diff --git a/messaging/src/main/java/io/micronaut/messaging/annotation/MessageMapping.java b/messaging/src/main/java/io/micronaut/messaging/annotation/MessageMapping.java index 3b541fe95fe..8c9ed941d11 100644 --- a/messaging/src/main/java/io/micronaut/messaging/annotation/MessageMapping.java +++ b/messaging/src/main/java/io/micronaut/messaging/annotation/MessageMapping.java @@ -15,6 +15,7 @@ */ package io.micronaut.messaging.annotation; +import io.micronaut.context.annotation.Executable; import io.micronaut.core.annotation.EntryPoint; import java.lang.annotation.Documented; @@ -34,6 +35,7 @@ @Retention(RUNTIME) @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD}) @EntryPoint +@Executable(processOnStartup = true) public @interface MessageMapping { /** diff --git a/router/src/test/groovy/io/micronaut/context/router/GroovyRouteBuilderSpec.groovy b/router/src/test/groovy/io/micronaut/context/router/GroovyRouteBuilderSpec.groovy index 0760bea37d3..a81f3256c4f 100644 --- a/router/src/test/groovy/io/micronaut/context/router/GroovyRouteBuilderSpec.groovy +++ b/router/src/test/groovy/io/micronaut/context/router/GroovyRouteBuilderSpec.groovy @@ -17,6 +17,7 @@ package io.micronaut.context.router import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext +import io.micronaut.context.annotation.Executable import io.micronaut.http.HttpMethod import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get @@ -121,6 +122,7 @@ class GroovyRouteBuilderSpec extends Specification { } @Controller('/book') + @Executable static class BookController { String hello(String message) { @@ -147,6 +149,7 @@ class GroovyRouteBuilderSpec extends Specification { } @Controller('/author') + @Executable static class AuthorController { List index() { ["author"] @@ -167,6 +170,7 @@ class GroovyRouteBuilderSpec extends Specification { } @Controller('/error-handling') + @Executable static class ErrorHandlingController { @Get('/throws-a') diff --git a/src/main/docs/guide/appendix/breaks.adoc b/src/main/docs/guide/appendix/breaks.adoc index 710b91168d1..ede514cbe4d 100644 --- a/src/main/docs/guide/appendix/breaks.adoc +++ b/src/main/docs/guide/appendix/breaks.adoc @@ -127,6 +127,16 @@ public class AProvider implements Provider { } ---- +==== Fewer Executable Methods Generated for Controllers and Message Listeners + +Previous versions of Micronaut specified the ann:context.annotation.Executable[] annotation as a meta-annotation on the ann:http.annotation.Controller[], ann:http.annotation.Filter[] and ann:messaging.annotation.MessageListener[] annotations. This resulted in generating executable method all non-private methods of classes annotated with these annotations. + +In Micronaut 3.x and above the ann:context.annotation.Executable[] has been moved to a meta-annotation of ann:http.annotation.HttpMethodMapping[] and ann:messaging.annotation.MessageMapping[] instead to reduce memory consumption and improve efficiency. + +If you were relying on the present of these executable methods you will need to annotate explicitly methods in your classes with ann:context.annotation.Executable[] to restore this behaviour. + +=== Module Changes + ==== New package for Micronaut Cassandra The classes in Micronaut Cassandra have been moved from `io.micronaut.configuration.cassandra` to `io.micronaut.cassandra` package.