From 6f54d63be8e6e91e763c2e27166c7012f9c855a7 Mon Sep 17 00:00:00 2001 From: Appearances Bot Date: Fri, 30 Sep 2022 19:01:24 -0700 Subject: [PATCH 1/4] add support for Spring Framework 6 AOT engine, which can produce GraalVM native images. --- pom.xml | 93 ++++++++++--------- spring/pom.xml | 5 +- ...KubernetesReconcilerAutoConfiguration.java | 2 +- ...BeanFactoryInitializationAotProcessor.java | 81 ++++++++++++++++ .../resources/META-INF/spring/aot.factories | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 3 + 6 files changed, 139 insertions(+), 46 deletions(-) create mode 100644 spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java create mode 100644 spring/src/main/resources/META-INF/spring/aot.factories create mode 100644 spring/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/pom.xml b/pom.xml index 0fd4f3b212..760b2795ee 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ 1.0.0 1.6.0 UTF-8 - + 0.10.2 1.3.2 1.33 2.0.3 @@ -89,6 +89,11 @@ + + org.reflections + reflections + ${reflections.version} + org.apache.commons commons-lang3 @@ -482,49 +487,49 @@ src/test/groovy/**/*.groovy - - java,javax,org,com,com.diffplug, - - - - - -/* -Copyright $YEAR The Kubernetes 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. -*/ - - - - - -/* -Copyright $YEAR The Kubernetes 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 - - - - - + + java,javax,org,com,com.diffplug, + + + + + + /* + Copyright $YEAR The Kubernetes 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. + */ + + + + + + /* + Copyright $YEAR The Kubernetes 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 + + + + + diff --git a/spring/pom.xml b/spring/pom.xml index 93cb0df61a..ffb7f4f250 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -14,8 +14,11 @@ ../pom.xml - + + org.reflections + reflections + io.kubernetes client-java-api diff --git a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/KubernetesReconcilerAutoConfiguration.java b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/KubernetesReconcilerAutoConfiguration.java index f59f66c311..45627feb36 100644 --- a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/KubernetesReconcilerAutoConfiguration.java +++ b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/KubernetesReconcilerAutoConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -@Configuration(proxyBeanMethods = false) +@Configuration @ConditionalOnKubernetesReconcilerEnabled public class KubernetesReconcilerAutoConfiguration { diff --git a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java new file mode 100644 index 0000000000..f1294b508f --- /dev/null +++ b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java @@ -0,0 +1,81 @@ +package io.kubernetes.client.spring.extended.controller.config.aot; + + +import com.google.gson.annotations.JsonAdapter; +import io.swagger.annotations.ApiModel; +import org.jetbrains.annotations.NotNull; +import org.reflections.Reflections; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.AutoConfigurationPackages; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * Registers hints to support Spring Framework 6 and Spring Boot 3 AOT + */ +public class KubernetesBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesBeanFactoryInitializationAotProcessor.class); + + private final MemberCategory[] allMemberCategories = MemberCategory.values(); + + @Override + public BeanFactoryInitializationAotContribution processAheadOfTime( + @NotNull ConfigurableListableBeanFactory beanFactory) { + return (generationContext, beanFactoryInitializationCode) -> { + RuntimeHints hints = generationContext.getRuntimeHints(); + String[] classNames = new String[]{ + "com.google.gson.JsonElement",// + "io.kubernetes.client.informer.cache.ProcessorListener", // + "io.kubernetes.client.extended.controller.Controller", // + "io.kubernetes.client.util.generic.GenericKubernetesApi$StatusPatch", // + "io.kubernetes.client.util.Watch$Response" // + }; + for (String className : classNames) { + LOGGER.info("registering " + className + " for reflection"); + hints.reflection().registerType(TypeReference.of(className), allMemberCategories); + } + registerForPackage("io.kubernetes", hints); + Collection packages = AutoConfigurationPackages.get(beanFactory); + for (String packageName : packages) { + registerForPackage(packageName, hints); + } + }; + } + + private void registerForPackage(String packageName, RuntimeHints hints) { + Reflections reflections = new Reflections(packageName); + Set> apiModels = reflections.getTypesAnnotatedWith(ApiModel.class); + Set> jsonAdapters = findJsonAdapters(reflections); + Set> all = new HashSet<>(); + all.addAll(jsonAdapters); + all.addAll(apiModels); + for (Class clazz : all) { + LOGGER.info("registering " + clazz.getName() + " for reflection"); + hints.reflection().registerType(clazz, allMemberCategories); + } + } + + private Set> findJsonAdapters(Reflections reflections) { + Class jsonAdapterClass = JsonAdapter.class; + Set> classes = new HashSet<>(); + for (Class clazz : reflections.getTypesAnnotatedWith(jsonAdapterClass)) { + JsonAdapter annotation = clazz.getAnnotation(jsonAdapterClass); + if (null != annotation) { + classes.add(annotation.value()); + } + classes.add(clazz); + } + return classes; + } +} \ No newline at end of file diff --git a/spring/src/main/resources/META-INF/spring/aot.factories b/spring/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 0000000000..ffb354197e --- /dev/null +++ b/spring/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1 @@ +org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=io.kubernetes.client.spring.extended.controller.config.aot.KubernetesBeanFactoryInitializationAotProcessor \ No newline at end of file diff --git a/spring/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000..7e78a1ccfa --- /dev/null +++ b/spring/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,3 @@ +io.kubernetes.client.spring.extended.controller.config.KubernetesInformerAutoConfiguration +io.kubernetes.client.spring.extended.controller.config.KubernetesReconcilerAutoConfiguration +io.kubernetes.client.spring.extended.manifests.config.KubernetesManifestsAutoConfiguration \ No newline at end of file From b8eb8f07fb74373df3e3f6f2975ef5e5ee6a05bf Mon Sep 17 00:00:00 2001 From: Appearances Bot Date: Sun, 2 Oct 2022 13:19:27 -0700 Subject: [PATCH 2/4] polishing the AOT support --- pom.xml | 127 ++++++++++-------- spring/pom.xml | 1 - ...BeanFactoryInitializationAotProcessor.java | 27 ++-- 3 files changed, 85 insertions(+), 70 deletions(-) diff --git a/pom.xml b/pom.xml index 760b2795ee..c32e221f2b 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,6 @@ 1.0.0 1.6.0 UTF-8 - 0.10.2 1.3.2 1.33 2.0.3 @@ -60,9 +59,10 @@ 1.21 2.11.0 1.15 - 2.7.4 + 3.0.0-M5 5.3.23 0.15.0 + 0.10.2 true @@ -329,7 +329,16 @@ default - + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + @@ -398,21 +407,21 @@ - - + + org.apache.maven.plugins maven-source-plugin 3.2.1 - - attach-sources - - jar-no-fork - - + + attach-sources + + jar-no-fork + + - - + + org.apache.maven.plugins maven-assembly-plugin 3.4.2 @@ -487,49 +496,49 @@ src/test/groovy/**/*.groovy - - java,javax,org,com,com.diffplug, - - - - - - /* - Copyright $YEAR The Kubernetes 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. - */ - - - - - - /* - Copyright $YEAR The Kubernetes 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 - - - - - + + java,javax,org,com,com.diffplug, + + + + + + /* + Copyright $YEAR The Kubernetes 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. + */ + + + + + + /* + Copyright $YEAR The Kubernetes 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 + + + + + @@ -546,8 +555,8 @@ verify sign - - + + --pinentry-mode @@ -567,4 +576,4 @@ - + \ No newline at end of file diff --git a/spring/pom.xml b/spring/pom.xml index ffb7f4f250..b22d731250 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -29,7 +29,6 @@ client-java-extended ${project.version} - org.springframework.boot spring-boot diff --git a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java index f1294b508f..400a4309df 100644 --- a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java +++ b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/aot/KubernetesBeanFactoryInitializationAotProcessor.java @@ -1,7 +1,11 @@ package io.kubernetes.client.spring.extended.controller.config.aot; +import com.google.gson.JsonElement; import com.google.gson.annotations.JsonAdapter; +import io.kubernetes.client.informer.cache.ProcessorListener; +import io.kubernetes.client.util.Watch; +import io.kubernetes.client.util.generic.GenericKubernetesApi; import io.swagger.annotations.ApiModel; import org.jetbrains.annotations.NotNull; import org.reflections.Reflections; @@ -34,16 +38,13 @@ public BeanFactoryInitializationAotContribution processAheadOfTime( @NotNull ConfigurableListableBeanFactory beanFactory) { return (generationContext, beanFactoryInitializationCode) -> { RuntimeHints hints = generationContext.getRuntimeHints(); - String[] classNames = new String[]{ - "com.google.gson.JsonElement",// - "io.kubernetes.client.informer.cache.ProcessorListener", // - "io.kubernetes.client.extended.controller.Controller", // - "io.kubernetes.client.util.generic.GenericKubernetesApi$StatusPatch", // - "io.kubernetes.client.util.Watch$Response" // + Class[] classes = new Class[]{JsonElement.class, ProcessorListener.class, + io.kubernetes.client.extended.controller.Controller.class, + GenericKubernetesApi.StatusPatch.class, Watch.Response.class }; - for (String className : classNames) { - LOGGER.info("registering " + className + " for reflection"); - hints.reflection().registerType(TypeReference.of(className), allMemberCategories); + for (Class clazz : classes) { + logClassReflectionRegistration(clazz); + hints.reflection().registerType(TypeReference.of(clazz), allMemberCategories); } registerForPackage("io.kubernetes", hints); Collection packages = AutoConfigurationPackages.get(beanFactory); @@ -61,11 +62,17 @@ private void registerForPackage(String packageName, RuntimeHints hints) { all.addAll(jsonAdapters); all.addAll(apiModels); for (Class clazz : all) { - LOGGER.info("registering " + clazz.getName() + " for reflection"); + logClassReflectionRegistration(clazz); hints.reflection().registerType(clazz, allMemberCategories); } } + private static void logClassReflectionRegistration(Class clazz) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("registering " + clazz.getName() + " for Spring AOT reflection"); + } + } + private Set> findJsonAdapters(Reflections reflections) { Class jsonAdapterClass = JsonAdapter.class; Set> classes = new HashSet<>(); From 41aa20403a3dc77e2326fb85e0bb8a96b0dcd5d6 Mon Sep 17 00:00:00 2001 From: Appearances Bot Date: Sun, 2 Oct 2022 13:29:20 -0700 Subject: [PATCH 3/4] polishing the AOT support --- pom.xml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index c32e221f2b..da365f2e27 100644 --- a/pom.xml +++ b/pom.xml @@ -329,16 +329,7 @@ default - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - + From 7284a24245e21654a3a1a4ecb72c4becd4638e14 Mon Sep 17 00:00:00 2001 From: Appearances Bot Date: Sun, 2 Oct 2022 13:36:08 -0700 Subject: [PATCH 4/4] polish --- pom.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index da365f2e27..bdc2b03e6d 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,7 @@ 1.0.0 1.6.0 UTF-8 + 1.3.2 1.33 2.0.3 @@ -329,7 +330,16 @@ default - + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + @@ -530,7 +540,6 @@ - release-sign-artifacts