I'm trying to build web app based on Spring Boot 3 and planning to run this in Kubernetes as native images. So my goal is to build native image, but it is where I got issue with Feign here.
My app is using Feign client to access third party API.
Application works perfect when run as plain Java application in non-native mode. But once I'm running it as native image in Docker, it is unable to make third party calls because request/response DTO types are not available in native runtime, forcing Jackson to throw error:
Cannot construct instance of `com.steam.trading.trade.bot.client.steam.dto.SteamResponse`: cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized
What I understand from this error is that AOT serialization hints are not created for Feign Client request/response dto data types. Also listing all classes for serialization is not an options, since it will be a lot of manual work to do and easy to miss something there.
Question is, is this some kind of bug in Open Feign, is there out of box RuntimeHintsRegistrar
to import or should I register all DTO's by myself?
Project setup
I'm using Spring Boot 3 and OpenFeign from Spring Cloud dependencies. Versions are:
<spring-boot.version>3.0.4</spring-boot.version>
<spring-cloud.version>2022.0.1</spring-cloud.version>
I have following Feign client:
@FeignClient(name = "steam-server-time-api", url = "${app.steam.api}", configuration = FeignSteamConfiguration.class)
public interface ServerTimeClient {
@RequestLine("POST /ITwoFactorService/QueryTime/v1/")
SteamResponse<QueryTime> getServerTime();
}
And following Feign Configuration:
public class FeignSteamConfiguration {
@Bean
public Contract useFeignAnnotations() {
return new Contract.Default();
}
@Bean
public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
return new FormEncoder(new SpringEncoder(messageConverters));
}
@Bean
public ErrorDecoder clientErrorDecoder() {
return new CustomErrorDecoder();
}
}
I tried Both default and Spring Contracts, but issue is the same.
I'm building images using command:
mvn -Pnative spring-boot:build-image
I tried to register manually, using RegisterReflectionForBinding, but having 50+ classes is not really good to manually list all of them. Also I tried to switch Default and Spring contracts, but it issue is still the same.