spring-projects / spring-projects/spring-ai
Provide a customization hook for RestClient.Builder used by model provider auto-configurations
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 6
Description
Hi, thanks for the great project!
I've been using Spring AI and encountered a situation where
a customization hook for the internal RestClient would be helpful.
I'd like to propose the following.
Expected Behavior
Spring AI's model provider auto-configurations should provide a way to customize
the RestClient.Builder before it is used to build the internal RestClient.
For example, users should be able to replace the message converters (and thus
the ObjectMapper) used by the RestClient, configure timeouts, add
interceptors, or set proxy settings — without having to replace the entire
API bean via @ConditionalOnMissingBean.
A common functional interface (e.g., SpringAiRestClientBuilderCustomizer)
accepted by all provider auto-configurations would allow a single bean to
apply customizations across all providers consistently.
Current Behavior
Model provider auto-configurations inject the global RestClient.Builder
and pass it directly to the API builder without any customization hook:
// e.g., OpenAiChatAutoConfiguration.java
restClientBuilderProvider.getIfAvailable(RestClient::builder)
This means the RestClient inherits the application's global ObjectMapper
via Spring Boot's HttpMessageConvertersRestClientCustomizer. While this works
fine for most configurations, certain custom Jackson modules
(e.g., a module that overrides enum deserialization with strict Enum.valueOf())
can break deserialization of model provider DTOs.
Currently, the only workaround is to define a custom API bean (e.g., OpenAiApi)
to replace the auto-configured one entirely, which requires duplicating
all the connection property resolution logic.
Context
In our project, we register a custom Jackson module on the global ObjectMapper
that uses Enum.valueOf() for enum deserialization. This causes Spring AI's
OpenAI API calls to fail because the API response contains lowercase enum values
(e.g., "assistant") while the Java enum constants are uppercase (ASSISTANT):
HttpMessageNotReadableException: JSON parse error:
No enum constant ...ChatCompletionMessage.Role.assistant
Caused by: java.lang.IllegalArgumentException:
No enum constant ...Role.assistant
at java.lang.Enum.valueOf(Enum.java:293)
at ...AbstractJackson2HttpMessageConverter.readJavaType(...)
at ...DefaultRestClient.readWithMessageConverters(...)
The same call succeeds when the custom module is not registered.
A customization hook would allow us to isolate the ObjectMapper for
Spring AI's RestClient without replacing the entire API bean:
@Bean
SpringAiRestClientBuilderCustomizer springAiRestClientCustomizer() {
ObjectMapper isolatedMapper = new ObjectMapper();
return builder -> builder.messageConverters(converters -> {
converters.removeIf(c -> c instanceof MappingJackson2HttpMessageConverter);
converters.add(new MappingJackson2HttpMessageConverter(isolatedMapper));
});
}
This pattern is consistent with Spring Boot's existing customizer conventions
(e.g., RestClientCustomizer, WebClientCustomizer).
I'd be happy to submit a PR if this approach aligns with the project's direction.
Thank you!
Related Issues
- #512 — HTTP Client configuration for models and vector stores
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with OpenAiChatAutoConfiguration and the RestClient::builder usage shown in the issue, then compare the other model-provider auto-configurations and read related issue #512. Trace how RestClient.Builder reaches each API builder. Done means a common customization hook works consistently across providers without replacing their API beans, with relevant tests covering customization.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring-boot
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100