diff --git a/spring-web/src/main/java/org/springframework/http/MediaTypeResourceHintsRegistrar.java b/spring-web/src/main/java/org/springframework/http/MediaTypeResourceHintsRegistrar.java new file mode 100644 index 000000000000..5214f8a83149 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/MediaTypeResourceHintsRegistrar.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.http; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.lang.Nullable; + +/** + * {@link RuntimeHintsRegistrar} implementation that makes sure mime types + * are available in constrained environments. + * + * @author Stephane Nicoll + * @since 6.0 + */ +class MediaTypeResourceHintsRegistrar implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + hints.resources().registerPattern("org/springframework/http/mime.types"); + } +} diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java index 97fe725024ff..65d7ceb66820 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java @@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.springframework.aot.hint.annotation.Reflective; import org.springframework.core.annotation.AliasFor; /** @@ -72,6 +73,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping +@Reflective(RequestMappingReflectiveProcessor.class) public @interface RequestMapping { /** diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMappingReflectiveProcessor.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMappingReflectiveProcessor.java new file mode 100644 index 000000000000..9f6527697881 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMappingReflectiveProcessor.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.web.bind.annotation; + +import java.lang.reflect.Method; + +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.aot.hint.annotation.ReflectiveProcessor; +import org.springframework.aot.hint.annotation.SimpleReflectiveProcessor; + +/** + * {@link ReflectiveProcessor} implementation for {@link RequestMapping} + * annotated types. On top of registering reflection hints for invoking + * the annotated method, this implementation handles return types that + * are serialized as well as TBD. + * + * @author Stephane Nicoll + * @since 6.0 + */ +class RequestMappingReflectiveProcessor extends SimpleReflectiveProcessor { + + @Override + protected void registerMethodHint(ReflectionHints hints, Method method) { + super.registerMethodHint(hints, method); + // TODO + } +} diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/WebAnnotationsRuntimeHintsRegistrar.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/WebAnnotationsRuntimeHintsRegistrar.java new file mode 100644 index 000000000000..1adc3ba2f068 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/WebAnnotationsRuntimeHintsRegistrar.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.web.bind.annotation; + +import java.util.stream.Stream; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.support.RuntimeHintsUtils; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Controller; + +/** + * {@link RuntimeHintsRegistrar} implementation that make web binding + * annotations at runtime. + * + * @author Stephane Nicoll + * @since 6.0 + */ +public final class WebAnnotationsRuntimeHintsRegistrar implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + Stream.of(Controller.class, ControllerAdvice.class, CookieValue.class, + CrossOrigin.class, DeleteMapping.class, ExceptionHandler.class, + GetMapping.class, InitBinder.class, Mapping.class, MatrixVariable.class, + ModelAttribute.class, PatchMapping.class, PathVariable.class, + PostMapping.class, PutMapping.class, RequestAttribute.class, + RequestBody.class, RequestHeader.class, RequestMapping.class, + RequestParam.class, RequestPart.class, ResponseBody.class, + ResponseStatus.class, RestController.class, RestControllerAdvice.class, + SessionAttribute.class, SessionAttributes.class).forEach( + annotationType -> RuntimeHintsUtils.registerAnnotation(hints, annotationType)); + } + +} diff --git a/spring-web/src/main/resources/META-INF/native-image/org.springframework/spring-web/native-image.properties b/spring-web/src/main/resources/META-INF/native-image/org.springframework/spring-web/native-image.properties new file mode 100644 index 000000000000..bcc0e66ab102 --- /dev/null +++ b/spring-web/src/main/resources/META-INF/native-image/org.springframework/spring-web/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=org.springframework.http.HttpStatus diff --git a/spring-web/src/main/resources/META-INF/spring/aot.factories b/spring-web/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 000000000000..8b8f795777b5 --- /dev/null +++ b/spring-web/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar= \ +org.springframework.http.MediaTypeResourceHintsRegistrar \ No newline at end of file diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 7afe6a07a9b7..d929f44e54f1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -33,6 +33,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.context.annotation.Lazy; import org.springframework.core.SpringProperties; import org.springframework.core.convert.converter.Converter; @@ -70,6 +71,7 @@ import org.springframework.web.HttpRequestHandler; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.WebAnnotationsRuntimeHintsRegistrar; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.context.ServletContextAware; import org.springframework.web.cors.CorsConfiguration; @@ -188,6 +190,7 @@ * @see EnableWebMvc * @see WebMvcConfigurer */ +@ImportRuntimeHints(WebAnnotationsRuntimeHintsRegistrar.class) public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware { /**