Explore native configuration inference for programmatic API
Almost every time I use Jackson to convert something to a POJO, I end up adding that POJO class to the @SerializationHint annotation. Can anyone tell me why this process is necessary (from an end-user point of view) and if it could be improved in the future, is it a really annoying process?
Why do Spring Native and Quarkus need to support third-party libraries instead of creating a standard support agreement?
Sorry for the newbie questions, but I think many others will ask the same, thanks for the amazing work.
@oclay1st thanks for the suggestion. Can you share the use cases of "convert something to a POJO"? I can imagine that we could look for controller methods and infer that the return type is going to be serialized to json potentially but I'd like to understand if there are more of those.
Thanks for your answer @snicoll
Just a simple: POJO pojo = objectMapper.readValue(json, POJO.class) and I end adding that POJO class to the Spring Native's annotations. Anything that touches reflection needs to be included, which is annoying for any developer.
Can I detect possible errors before compiling to native?.
Could this situation be improved in the future?
What are the workarounds, right now?
Why do you need to support third-party libraries and not in the other way around?
LOL, so many questions, sorry for that I just want to understand and help if possible.
Unfortunately, I don't think we're going to parse your source code to find out places where you may call readValue. We need some sort of signal and that's what I was trying to get at with my question. If you have a return type on a controller, we are taking care of it already.
What do you think @sdeleuze?
Typical use case for that is using http clients like RestTemplate or WebClient, and that's probably the number one remaining issue people get with our current native support, so I deeply care about finding a solution, but that's not an easy one. But let's try.
First way to avoid this problem is to use a library that does not require reflection. In the context of Spring, this is possible for Kotlin developers who I advise to use our support for Kotlin Serialization. But for Java and a lot of various use cases, avoiding reflection is not possible and I don't think we (the Spring team) want to maintain a JSON serialization library.
Currently we indeed don't have a clear signal for that so we require a dedicated @TypeHint(type = POJO.class, accessBits=AccessBits.FULL_REFLECTION) annotation. We could maybe consider some small improvements but they do not really address the root issue:
- We could have an annotation to put directly on
POJOas a shortcut - We could add a mechanism to add class reflection configuration when some Jackson annotations are detected on classes (I think we don't have that yet, to be verified)
Another angle of attack is to have an ASM visitor that will add reflection automatically for certain usage patterns like with ObjectMapper, WebClient or RestTemplate serialization methods. Conceptually, that's a kind of signal, but a programmatic one that require other mechanisms to be found.
I think the challenges would be:
- To find the sweet spot in term of scope to not scan everything
- Get that maintainable, ie. is that ok to list most popular serialization methods like those for
ObjectMapper,WebClientorRestTemplate?
So what if we would have a BeanNativeConfigurationProcessor that would:
- Be configured with a set of method handles to consider (that way we avoid typos, and it breaks if the method is removed)
- Apply an ASM visitor on each bean class and subclass and add automatically reflection when a class is passed as parameter for the set of method handles configured
We could even allow users to specify some kind of hints to add method handles that would be used for such mechanism later.
For now I can't think of another way to solve this painful problem for most common use cases.
Any thoughts @snicoll @aclement ?
Maybe we can catch a lot of cases with simplistic analysis (asm visitor), we would certainly catch class literal references like POJO in here:
POJO pojo = objectMapper.readValue(json, POJO.class)
what is harder to catch is anything requiring flow awareness, like this usage in spring framework:
return objectMapper.readValue(inputMessage.getBody(), javaType);
Knowing what javaType is, well it is a parameter to the method that that line is in, so I don't think I necessarily want to get into the business of working that out (via static analysis). But perhaps that kind of usage only happens in framework style internal usage and an application usually is typically the easy first structure? It seems a relatively easy win to do what Sebastien describes, it is what I would try, recognizing it is not going to be a 100% automatic solution.
Given that GraalVM has more detailed static analysis built in - if that were pluggable down the line you could imagine a world where for certain method patterns you could write a plugin to be called at the right time in GraalVM analysis to contribute configuration based on domain knowledge. It should have a more accurate view of the actual parameter values.
Just thinking through other options.... if you had good tests and they ran with the agent in incremental form contributing extraneous configuration only that wasn't being computed automatically (and we know it can run in that form now), you would catch even that harder secondary situation.
Probably worth to explore later.
Hi, is there any updates? Thanks!
On Spring Native side no, but we are going likely to explore this in Spring Framework 6 and Spring Boot 3.
Thank you! Looking forward to spring6
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.