1+ /*
2+ Copyright 2022 The Kubernetes Authors.
3+ Licensed under the Apache License, Version 2.0 (the "License");
4+ you may not use this file except in compliance with the License.
5+ You may obtain a copy of the License at
6+ http://www.apache.org/licenses/LICENSE-2.0
7+ Unless required by applicable law or agreed to in writing, software
8+ distributed under the License is distributed on an "AS IS" BASIS,
9+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+ See the License for the specific language governing permissions and
11+ limitations under the License.
12+ */
113package io .kubernetes .client .spring .aot ;
214
315import com .google .gson .annotations .JsonAdapter ;
416import io .kubernetes .client .extended .controller .Controller ;
517import io .swagger .annotations .ApiModel ;
18+ import java .lang .annotation .Annotation ;
19+ import java .util .Collection ;
20+ import java .util .HashSet ;
21+ import java .util .Set ;
622import org .jetbrains .annotations .NotNull ;
723import org .reflections .Reflections ;
824import org .slf4j .Logger ;
1531import org .springframework .beans .factory .config .ConfigurableListableBeanFactory ;
1632import org .springframework .boot .autoconfigure .AutoConfigurationPackages ;
1733
18- import java .lang .annotation .Annotation ;
19- import java .util .Collection ;
20- import java .util .HashSet ;
21- import java .util .Set ;
22-
2334/**
24- * GraalVM native images need to know about when you might reflectively work with types at runtime. The Kubernetes Java
25- * client works with several types reflectively at runtime. This code uses the third-party Reflections library to
26- * reflect upon all the code in your Spring Boot application or in the official Kubernetes Java client that has
27- * {@link ApiModel}, {@link JsonAdapter}, and registers them. It also registers a few other specific handful of
28- * classes that should be accounted for, in specific cases.
35+ * GraalVM native images need to know about when you might reflectively work with types at runtime.
36+ * The Kubernetes Java client works with several types reflectively at runtime. This code uses the
37+ * third-party Reflections library to reflect upon all the code in your Spring Boot application or
38+ * in the official Kubernetes Java client that has {@link ApiModel}, {@link JsonAdapter}, and
39+ * registers them. It also registers a few other specific handful of classes that should be
40+ * accounted for, in specific cases.
2941 *
3042 * @author Josh Long
3143 */
3244@ SuppressWarnings ("unused" )
3345public class KubernetesBeanFactoryInitializationAotProcessor
34- implements BeanFactoryInitializationAotProcessor {
46+ implements BeanFactoryInitializationAotProcessor {
3547
36- private static final Logger LOGGER = LoggerFactory .getLogger (KubernetesBeanFactoryInitializationAotProcessor .class );
48+ private static final Logger LOGGER =
49+ LoggerFactory .getLogger (KubernetesBeanFactoryInitializationAotProcessor .class );
3750
38- private final MemberCategory [] allMemberCategories = MemberCategory .values ();
51+ private final MemberCategory [] allMemberCategories = MemberCategory .values ();
3952
40- @ Override
41- public BeanFactoryInitializationAotContribution processAheadOfTime (
42- @ NotNull ConfigurableListableBeanFactory beanFactory ) {
43- return (generationContext , beanFactoryInitializationCode ) -> {
44- RuntimeHints hints = generationContext .getRuntimeHints ();
45- String [] classNames = new String []{
46- "com.google.gson.JsonElement" ,//
47- "io.kubernetes.client.informer.cache.ProcessorListener" , //
48- "io.kubernetes.client.extended.controller.Controller" , //
49- "io.kubernetes.client.util.generic.GenericKubernetesApi$StatusPatch" , //
50- "io.kubernetes.client.util.Watch$Response" //
51- };
52- for (String className : classNames ) {
53- LOGGER .info ("registering " + className + " for reflection" );
54- hints .reflection ().registerType (TypeReference .of (className ), allMemberCategories );
55- }
56- registerForPackage ("io.kubernetes" , hints );
57- Collection <String > packages = AutoConfigurationPackages .get (beanFactory );
58- for (String packageName : packages ) {
59- registerForPackage (packageName , hints );
60- }
61- };
62- }
53+ @ Override
54+ public BeanFactoryInitializationAotContribution processAheadOfTime (
55+ @ NotNull ConfigurableListableBeanFactory beanFactory ) {
56+ return (generationContext , beanFactoryInitializationCode ) -> {
57+ RuntimeHints hints = generationContext .getRuntimeHints ();
58+ String [] classNames =
59+ new String [] {
60+ "com.google.gson.JsonElement" , //
61+ "io.kubernetes.client.informer.cache.ProcessorListener" , //
62+ "io.kubernetes.client.extended.controller.Controller" , //
63+ "io.kubernetes.client.util.generic.GenericKubernetesApi$StatusPatch" , //
64+ "io.kubernetes.client.util.Watch$Response" //
65+ };
66+ for (String className : classNames ) {
67+ LOGGER .info ("registering " + className + " for reflection" );
68+ hints .reflection ().registerType (TypeReference .of (className ), allMemberCategories );
69+ }
70+ registerForPackage ("io.kubernetes" , hints );
71+ Collection <String > packages = AutoConfigurationPackages .get (beanFactory );
72+ for (String packageName : packages ) {
73+ registerForPackage (packageName , hints );
74+ }
75+ };
76+ }
6377
64- private void registerForPackage (String packageName , RuntimeHints hints ) {
65- Reflections reflections = new Reflections (packageName );
66- Set <Class <?>> apiModels = reflections .getTypesAnnotatedWith (ApiModel .class );
67- Set <Class <? extends Controller >> controllers = reflections .getSubTypesOf (Controller .class );
68- Set <Class <?>> jsonAdapters = findJsonAdapters (reflections );
69- Set <Class <?>> all = new HashSet <>();
70- all .addAll (jsonAdapters );
71- all .addAll (controllers );
72- all .addAll (apiModels );
73- for (Class <?> clazz : all ) {
74- LOGGER .info ("registering " + clazz .getName () + " for reflection" );
75- hints .reflection ().registerType (clazz , allMemberCategories );
76- }
78+ private void registerForPackage (String packageName , RuntimeHints hints ) {
79+ Reflections reflections = new Reflections (packageName );
80+ Set <Class <?>> apiModels = reflections .getTypesAnnotatedWith (ApiModel .class );
81+ Set <Class <? extends Controller >> controllers = reflections .getSubTypesOf (Controller .class );
82+ Set <Class <?>> jsonAdapters = findJsonAdapters (reflections );
83+ Set <Class <?>> all = new HashSet <>();
84+ all .addAll (jsonAdapters );
85+ all .addAll (controllers );
86+ all .addAll (apiModels );
87+ for (Class <?> clazz : all ) {
88+ LOGGER .info ("registering " + clazz .getName () + " for reflection" );
89+ hints .reflection ().registerType (clazz , allMemberCategories );
7790 }
91+ }
7892
79- private <R extends Annotation > Set <Class <?>> findJsonAdapters (Reflections reflections ) {
80- Class <JsonAdapter > jsonAdapterClass = JsonAdapter .class ;
81- Set <Class <?>> classes = new HashSet <>();
82- for (Class <?> clazz : reflections .getTypesAnnotatedWith (jsonAdapterClass )) {
83- JsonAdapter annotation = clazz .getAnnotation (jsonAdapterClass );
84- if (null != annotation ) {
85- classes .add (annotation .value ());
86- }
87- classes .add (clazz );
88- }
89- return classes ;
93+ private <R extends Annotation > Set <Class <?>> findJsonAdapters (Reflections reflections ) {
94+ Class <JsonAdapter > jsonAdapterClass = JsonAdapter .class ;
95+ Set <Class <?>> classes = new HashSet <>();
96+ for (Class <?> clazz : reflections .getTypesAnnotatedWith (jsonAdapterClass )) {
97+ JsonAdapter annotation = clazz .getAnnotation (jsonAdapterClass );
98+ if (null != annotation ) {
99+ classes .add (annotation .value ());
100+ }
101+ classes .add (clazz );
90102 }
91- }
103+ return classes ;
104+ }
105+ }
0 commit comments