Skip to content

Commit

Permalink
Merge pull request #2457 from joshlong/boot3-aot
Browse files Browse the repository at this point in the history
add a module for Spring Boot 3 AOT
  • Loading branch information
k8s-ci-robot authored Dec 2, 2022
2 parents bbd7b10 + 3d710de commit ce32410
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 5 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17.0.x
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
Expand Down
20 changes: 16 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,23 @@ jobs:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ matrix.java }}-${{ hashFiles('pom.xml', '**/pom.xml') }}
- name: Build with Maven
shell: bash
run: |
mvn clean test -q -B --define=org.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
if [ $(grep -E '^(8|11)\.' <<< '${{ matrix.java }}') ]; then
# some module doesn't compile on java platform lower than 17, need to skip them by specifying a profile
MODS_OVERRIDES='-pl !spring-aot'
fi
mvn -q -B --define=org.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn $MODS_OVERRIDES clean test
build-graalvm:
runs-on: ubuntu-latest
name: GraalVM Maven Test
steps:
- uses: actions/checkout@v3
- uses: DeLaGuardo/setup-graalvm@48f2bf339ab7d35e31029b1822a213681fdfc42e
- uses: graalvm/setup-graalvm@v1
with:
graalvm-version: '19.3.0.java8'
version: '22.3.0'
java-version: '17'
components: 'native-image'
- name: Build with Maven
run: mvn -q test -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
e2e:
Expand All @@ -62,6 +69,11 @@ jobs:
- uses: actions/checkout@v3
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.4.0
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17.0.x
- name: Run E2E with Maven
run: |
mvn clean install \
Expand All @@ -81,7 +93,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 11.0.x
java-version: 17.0.x
- name: Cache local Maven repository
uses: actions/cache@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<module>extended</module>
<module>fluent</module>
<module>spring</module>
<module>spring-aot</module>
<module>e2e</module>
<module>examples</module>
<module>client-java-contrib/cert-manager</module>
Expand Down Expand Up @@ -63,6 +64,7 @@
<spring.boot.version>2.7.5</spring.boot.version>
<spring.version>5.3.23</spring.version>
<prometheus.client.version>0.15.0</prometheus.client.version>
<reflections.version>0.10.2</reflections.version>

<e2e.skip>true</e2e.skip>

Expand Down
87 changes: 87 additions & 0 deletions spring-aot/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.kubernetes</groupId>
<artifactId>client-java-spring-aot-integration</artifactId>
<packaging>bundle</packaging>
<name>client-java-spring-aot-integration</name>
<url>https://github.com/kubernetes-client/java</url>
<parent>
<artifactId>client-java-parent</artifactId>
<groupId>io.kubernetes</groupId>
<version>16.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<spring.boot.version>3.0.0</spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${reflections.version}</version>
</dependency>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java-spring-integration</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright 2022 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 io.kubernetes.client.spring.aot;

import com.google.gson.annotations.JsonAdapter;
import io.kubernetes.client.extended.controller.Controller;
import io.swagger.annotations.ApiModel;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
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;

/**
* GraalVM native images need to know about when you might reflectively work with types at runtime.
* The Kubernetes Java client works with several types reflectively at runtime. This code uses the
* third-party Reflections library to reflect upon all the code in your Spring Boot application or
* in the official Kubernetes Java client that has {@link ApiModel}, {@link JsonAdapter}, and
* registers them. It also registers a few other specific handful of classes that should be
* accounted for, in specific cases.
*
* @author Josh Long
*/
@SuppressWarnings("unused")
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<String> packages = AutoConfigurationPackages.get(beanFactory);
for (String packageName : packages) {
registerForPackage(packageName, hints);
}
};
}

private void registerForPackage(String packageName, RuntimeHints hints) {
Reflections reflections = new Reflections(packageName);
Set<Class<?>> apiModels = reflections.getTypesAnnotatedWith(ApiModel.class);
Set<Class<? extends Controller>> controllers = reflections.getSubTypesOf(Controller.class);
Set<Class<?>> jsonAdapters = findJsonAdapters(reflections);
Set<Class<?>> all = new HashSet<>();
all.addAll(jsonAdapters);
all.addAll(controllers);
all.addAll(apiModels);
for (Class<?> clazz : all) {
LOGGER.info("registering " + clazz.getName() + " for reflection");
hints.reflection().registerType(clazz, allMemberCategories);
}
}

private <R extends Annotation> Set<Class<?>> findJsonAdapters(Reflections reflections) {
Class<JsonAdapter> jsonAdapterClass = JsonAdapter.class;
Set<Class<?>> 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=io.kubernetes.client.spring.aot.KubernetesBeanFactoryInitializationAotProcessor
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit ce32410

Please sign in to comment.