spring-native
spring-native copied to clipboard
Add support for Spring Cloud Gateway
I've got a Graal + Spring Cloud Gateway app that I can't quite get over the GraalVM compilation hump. The code is in this repository.
And there's a compile.sh
at the root of the project that illustrates my build. I get an inscrutible error, like this:
01:47:50.613 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.maxDirectMemory: 13362528256 bytes
01:47:50.613 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.uninitializedArrayAllocationThreshold: -1
01:47:50.613 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.internal.CleanerJava6 - java.nio.ByteBuffer.cleaner(): available
01:47:50.613 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
01:47:50.616 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
01:47:50.616 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.targetRecords: 4
01:47:56.091 [ForkJoinPool-4-worker-9] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
01:47:56.091 [ForkJoinPool-4-worker-9] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
01:47:56.091 [ForkJoinPool-4-worker-9] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
01:47:56.091 [ForkJoinPool-4-worker-9] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
01:47:56.091 [ForkJoinPool-4-worker-9] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.delayedQueue.ratio: 8
01:48:09.991 [ForkJoinPool-2-worker-15] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
01:48:09.991 [ForkJoinPool-2-worker-15] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
01:48:09.991 [ForkJoinPool-2-worker-15] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@57afd16
01:48:10.027 [ForkJoinPool-2-worker-15] DEBUG io.netty.buffer.AdvancedLeakAwareByteBuf - -Dio.netty.leakDetection.acquireAndReleaseOnly: false
01:48:15.387 [ForkJoinPool-2-worker-0] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
01:48:15.388 [ForkJoinPool-2-worker-0] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
[gateway:70358] analysis: 26,237.13 ms, 4.59 GB
Fatal error:java.lang.NullPointerException
at com.oracle.graal.pointsto.flow.MethodTypeFlow.getParsingContext(MethodTypeFlow.java:99)
at com.oracle.graal.pointsto.util.AnalysisError.parsingContext(AnalysisError.java:122)
at com.oracle.graal.pointsto.util.AnalysisError.access$000(AnalysisError.java:37)
at com.oracle.graal.pointsto.util.AnalysisError$ParsingError.message(AnalysisError.java:97)
at com.oracle.graal.pointsto.util.AnalysisError$ParsingError.<init>(AnalysisError.java:87)
at com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:138)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.doParse(MethodTypeFlow.java:336)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureParsed(MethodTypeFlow.java:311)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.addContext(MethodTypeFlow.java:112)
at com.oracle.graal.pointsto.DefaultAnalysisPolicy$DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultAnalysisPolicy.java:228)
at com.oracle.graal.pointsto.flow.TypeFlow.notifyObservers(TypeFlow.java:470)
at com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:542)
at com.oracle.graal.pointsto.BigBang$2.run(BigBang.java:530)
at com.oracle.graal.pointsto.util.CompletionExecutor.lambda$execute$0(CompletionExecutor.java:173)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1541)
at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1299)
at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1260)
at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1219)
This problem was already in the Graal tracker ( https://github.com/oracle/graal/issues/2595 ) so I've added a reference to this bug and your test project. They are using different spring cloud dependencies in that version but exception looks the same. Doesn't work on Graal 20.2 dev builds either.
Ah, I hadn't run that darn gu install native-image command on the 20.2 I grabbed. Now I've done this, the sample is compiling without NPE. Grab 20.2 (I used 20200627) from https://github.com/graalvm/graalvm-ce-dev-builds/releases
Now building, the app doesn't run of course, but it fails for expected reasons :) I bet running it with the agent to collect a first go of config and then re-attempting native image build will behave better.
Ran with the agent to collect config. Gets further, now breaks with ObjenesisCglibAopProxy
usage.
Ok, upgraded the project to 0.8.0-SNAPSHOT of the Spring GraalVM feature. Now we're at:
Caused by: org.springframework.cglib.core.CodeGenerationException: com.oracle.svm.core.jdk.UnsupportedFeatureError-->Unsupported method java.lang.ClassLoader.defineClass1(String, byte[], int, int, ProtectionDomain, String) is reachable
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:538) ~[na:na]
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) ~[na:na]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) ~[na:na]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) ~[na:na]
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[na:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:na]
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[na:na]
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[na:na]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) ~[na:na]
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) ~[na:na]
at org.springframework.cglib.core.KeyFactory$Generator.create(KeyFactory.java:237) ~[na:na]
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:184) ~[na:na]
at org.springframework.cglib.core.KeyFactory.create(KeyFactory.java:160) ~[na:na]
at org.springframework.cglib.proxy.Enhancer.<clinit>(Enhancer.java:104) ~[na:na]
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:351) ~[na:na]
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:271) ~[na:na]
Hmm, I got it going but not totally happy with the solution:
2020-06-30 22:02:30.019 INFO 53618 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-06-30 22:02:30.025 INFO 53618 --- [ main] com.example.gateway.GatewayApplication : Started GatewayApplication in 0.147 seconds (JVM running for 0.149)
But I guess that means I understand all the issues in play, so that's good :)
OK - to get it working (these are the current steps, obviously not how it'll be in the end):
- Enable all security features in the native image build, otherwise you'll get a nasty security exception ( add parameter
--enable-all-security-services
tonative-image
call) - Switch to a Graal 20.2 dev build.
- Update to GraalVM spring feature 0.8.0-SNAPSHOT instead of 0.7.1
- Tweak the Spring application to currently turn off the validation config. Tweak it to:
@SpringBootApplication (proxyBeanMethods = false, exclude = {ValidationAutoConfiguration.class})
- Run it with the agent:
mkdir -p graal/META-INF/native-image
java -agentlib:native-image-agent=config-output-dir=graal/META-INF/native-image -jar target/gateway-0.0.1-SNAPSHOT.jar
and add the graal folder to the classpath in compile.sh:
-cp $CP:../../graal $MAINCLASS
Hello! I'm trying to replicate a native spring gateway with your repository but doesn't work
I've followed @aclement steps and managed to boot up a native spring cloud gateway. you can find the demo project here. Using :
<spring-cloud.version>2020.0.2</spring-cloud.version>
<spring-native.version>0.9.1</spring-native.version>
<graalvm.version>21.0.0.2</graalvm.version>
But at the first Http request I get this error:
java.lang.NoClassDefFoundError: Could not initialize class io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:239) ~[na:na]
at io.netty.resolver.dns.DnsServerAddressStreamProviders.unixDefault(DnsServerAddressStreamProviders.java:107) ~[gatewayapplication.exe:4.1.60.Final]
at io.netty.resolver.dns.DnsServerAddressStreamProviders.platformDefault(DnsServerAddressStreamProviders.java:103) ~[gatewayapplication.exe:4.1.60.Final]
at io.netty.resolver.dns.DnsNameResolverBuilder.<init>(DnsNameResolverBuilder.java:60) ~[na:na]
at reactor.netty.transport.NameResolverProvider.newNameResolverGroup(NameResolverProvider.java:405) ~[na:na]
at reactor.netty.tcp.TcpResources.getOrCreateDefaultResolver(TcpResources.java:306) ~[na:na]
at reactor.netty.http.HttpResources.getOrCreateDefaultResolver(HttpResources.java:140) ~[na:na]
at reactor.netty.http.client.HttpClientConfig.defaultAddressResolverGroup(HttpClientConfig.java:380) ~[na:na]
at reactor.netty.transport.ClientTransportConfig.resolverInternal(ClientTransportConfig.java:219) ~[na:na]
at reactor.netty.http.client.HttpClientConfig.resolverInternal(HttpClientConfig.java:434) ~[na:na]
at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.lambda$subscribe$0(HttpClientConnect.java:264) ~[na:na]
at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57) ~[na:na]
at reactor.core.publisher.FluxRetryWhen.subscribe(FluxRetryWhen.java:76) ~[na:na]
at reactor.core.publisher.MonoRetryWhen.subscribeOrReturn(MonoRetryWhen.java:46) ~[na:na]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) ~[na:na]
at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:271) ~[na:na]
And Im stuck. Can't find a workaround
@hanouard I tried your project with Spring Boot 2.4.5, Spring Native 0.9.2 and GraalVM 20.1.0, I was able to compile with mvn -Pnative-image clean package
and run it successfully.
@sdeleuze did you try to make a GET /test/posts ?
@hanouard Yes it seems to work.
@sdeleuze I can't reproduce what you've done. I get this error:
Could not find option 'InlineBeforeAnalysis'
Which is normal since this option was added in GraalVM 21.0.0
It was a typo, I meant GraalVM 21.0.0.
@joshlong Could you please check again the status of Gateway support with 0.10.2-SNAPSHOT
and share your feedback?
Aloha! Things are much improved! But not 100% there.
Given the following program:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.nativex.hint.AccessBits;
import org.springframework.nativex.hint.TypeHint;
@SpringBootApplication
public class GatewayNativeApplication {
@Bean
RouteLocator gateway(RouteLocatorBuilder rlb) {
return rlb
.routes()
.route(rs -> rs
.path("/")
.uri("https://start.spring.io")
)
.build();
}
public static void main(String[] args) {
SpringApplication.run(GatewayNativeApplication.class, args);
}
}
and the following Maven build:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>gateway-native</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-native</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<repackage.classifier/>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-native.version>0.10.2-SNAPSHOT</spring-native.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring-native.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>${repackage.classifier}</classifier>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>${spring-native.version}</version>
<executions>
<execution>
<id>test-generate</id>
<goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<id>native</id>
<properties>
<repackage.classifier>exec</repackage.classifier>
<native-buildtools.version>0.9.1</native-buildtools.version>
</properties>
<dependencies>
<dependency>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>junit-platform-native</artifactId>
<version>${native-buildtools.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-buildtools.version}</version>
<executions>
<execution>
<id>test-native</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
<execution>
<id>build-native</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
It fails. But, it's one type hint away from working:
I added
@TypeHint(
typeNames = "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$Config",
access = AccessBits.ALL
)
and it worked! :-)
curl http://localhost:8080/
This is a super trivial Gateway example that uses none of the filters or does anything beyond proxying an HTTP request, but it's still very cool that it can work with just that one change. Congrats!
I would love to take this further and contribute some hints for your consideration when I get back from vacation on Monday. If that one hint is all that's required, then maybe this is an ideal ticket to open to first-time contributors? Either way, thanks for all your work thus far, and c'ya in ~50h
OK, a bit of a sledgehammer approach, but, adding all of the following seems to allow me a lot of forward progress. These are all subclasses of Configurable<T>.class
and the T.class
itself. So, FooFactory<T>.class
and FooFactory<T>.T.class
, if that makes sense.
@TypeHint(
access = AccessBits.ALL,
typeNames = {
"org.springframework.cloud.gateway.handler.predicate.ReadBodyRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory",
"org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory$NameConfig",
"org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RemoveRequestParameterGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.SetRequestHostHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory",
"org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter",
"org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.RequestHeaderSizeGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.support.WeightConfig",
"org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory",
"org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory",
"org.springframework.cloud.gateway.config.conditional.OnEnabledPredicate$DefaultValue",
"org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory",
"org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RequestHeaderSizeGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.ReadBodyRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.TokenRelayGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory",
"org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory",
"org.springframework.cloud.gateway.config.conditional.OnEnabledFilter$DefaultValue",
"org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerResilience4JFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory$RequestSizeConfig",
"org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.CloudFoundryRouteServiceRoutePredicateFactory",
"org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter$Config",
"org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory$Config",
"org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.SetRequestHostHeaderGatewayFilterFactory$Config",
"org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory$RetryConfig",
"org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory",
"org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory",
"org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory$Config"
}
)
Alrght, I've gotten something more future-proof working here: https://github.com/joshlong/gateway-hints/blob/main/gateway-hints/src/main/java/gateway/GatewayHints.java
Spring Cloud Gateway makes use of classes of the form FooFactory
, and those in turn have .class
references to nested FooFactory.Config
classes. So long as this pattern holds true, this hint should buy us a lot
I haven't tried it with every possible filter (as some of htem require other libraries on the classpath, like resilience4j and spring security), but let's cross that bridge later.
Hi,
is possible use in pom
<parent> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Hoxton.SR12</version> </parent>
tnx.
Any updates on this? Would love to try out native with cloud gateway, but currently build fails for the newest version 2021.0.0 with your big list @joshlong.
Fatal error:java.lang.TypeNotPresentException: Type org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager not present
The source you provided in your repo seems to not work with a newer version if I'm correct. At least some of the types you used are not available in newest Spring native version (at least that's what IntelliJ suggesting)
Cc @OlgaMaciaszek.
Spring Native is now superseded by Spring Boot 3 official native support, see the related reference documentation for more details.
As a consequence, I am closing this issue, and recommend trying your use case with latest Spring Boot 3 version. If you still experience the issue reported here, please open an issue directly on the related Spring project (Spring Framework, Data, Security, Boot, Cloud, etc.) with a reproducer.
Thanks for your contribution on the experimental Spring Native project, we hope you will enjoy the official native support introduced by Spring Boot 3.