Circuit Breaker doesn't support dynamic fallback URI in Java configuration
Configure a circuit breaker in Java to copy the segments in the fallback URI
`` @Configuration class RouteConfiguration {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
builder.routes().route(r -> r.path("api/{*segments}").filters(f -> {
f.circuitBreaker(c -> c
.setName("test")
.setFallbackUri("forward:/inCaseOfFailureUseThis/{segments}")
);
}
return f;
})
.uri(http://localhost:8080)
);
``
Result:
Caused by: java.lang.IllegalArgumentException: Illegal character in path at index 32: forward:/inCaseOfFailureUseThis/{segments} at java.base/java.net.URI.create(URI.java:906) ~[na:na]
Caused by: java.net.URISyntaxException: Illegal character in path at index 32: forward:/inCaseOfFailureUseThis/{segments}
at java.base/java.net.URI$Parser.fail(URI.java:2976) ~[na:na]
at java.base/java.net.URI$Parser.checkChars(URI.java:3147) ~[na:na]
at java.base/java.net.URI$Parser.parseHierarchical(URI.java:3229) ~[na:na]
at java.base/java.net.URI$Parser.parse(URI.java:3177) ~[na:na]
at java.base/java.net.URI.
Documentation extract
`` @Configuration class RouteConfiguration {
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
return route("circuitbreaker_route")
.route(path("/consumingServiceEndpoint/{*segments}"), http("https://example.org"))
.filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis/{segments}")))
.build();
}
} ``
Note:
Using the config via yaml is not possible in my case as a part of the URI (prefix) has to be done in the code. So a configuration in Java of the fallback URI is required.
I created a route config like the following in a unit test
.route("fallback_with_segments", r -> r.path("/fallback/{segments}").filters(f -> f.setPath("/circuitbreakerFallbackController/{segments}")).uri(uri))
and it worked.
Can you try removing * in {segments} and see if it works? If it doesn't can you please provide a sample to reproduce it?
The usage of "{segments}" works well in a filter.
The issue is only in Circuit Breaker.
The code in your comment or test is not using Circuit Breaker.
I need to copy the segments for the fallback route, otherwise this information is lost in the fallback route,
Please test the piece of code provided previously (one comes from the documentation in this git repository).
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-gateway' implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j' ...
Spring Cloud: 2022.0.4
Spring Boot: 3.1.6
The exception come from this class and function:
` package org.springframework.cloud.gateway.filter.factory; public abstract class SpringCloudCircuitBreakerFilterFactory extends AbstractGatewayFilterFactory<SpringCloudCircuitBreakerFilterFactory.Config> {
public Config setFallbackUri(String fallbackUri) {
return setFallbackUri(URI.create(fallbackUri));
}
`
-> URI.create will create an exception due to the character "{"
Thanks I was able to reproduce this and have a PR with a fix.
As a workaround I think you can do the following and it should work
UriComponentsBuilder.fromUriString("forward:/inCaseOfFailureUseThis/{segments}").build().toUri()