spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.02k stars 40.65k forks source link

Missing callback-Method "onBind" in org.springframework.boot.context.properties.bind.BindHandler #36479

Open hosea opened 1 year ago

hosea commented 1 year ago

Hello!

There are several methods for influencing / processing PropertyBinding using org.springframework.boot.context.properties.bind.BindHandler. But I miss a callback-method like "onBind" that is called when binding takes places. This method should be called in org.springframework.boot.context.properties.bind.Binder#bindProperty before calling the converter but after resolving placeholders (btw.: I use version 2.6.11).

I try to explain my case as short as possible: I have to retrieve credentials / URLs etc. from a vault. Unfortunately I cannot use any of the standard-ways to retrieve via configuration / inject the credentials. The only way to do it, is to use a company-specific-proprietary library. All I want to do is to describe the credentials in my configuration in my own format and to resolve it during binding using the proprietary library, small example:

mysystem:
  secret: secret-spec{'safe':'${safe}','aimUser':'${aimUser}','objectName':'content'}

I build my own BindHandler, that just has a look at the given String and evaluates its specification. Then it uses the proprietary library to retrieve the specified value and returns it.

My solution works fine for Strings (BindHandler#onSuccess, even if it is late!), but fails for URLs etc. because the Converter cannot resolve something like secret-spec{....}. So I currently use onFailure for this situation. Not nice, would be perfectly working with a "onBind"-Method.

Please add the mentioned callback to make BindHandler more powerful.

Kind regards Hans

wilkinsona commented 1 year ago

Thanks for the suggestion but I'm not sure that we should open up BindHandler in this manner. You said that you cannot use any of the standard ways but I wonder what ways you consider to the standard. From what you've described thus far, custom ConfigDataLocationResolver and ConfigDataLoader implementations that can retrieve credentials/URLs from your proprietary vault feel like a better fit for your problem. If you've already considered and rejected this approach, it would be useful to know more about why it isn't suitable.

philwebb commented 1 year ago

A small sample application would also be quite useful to show exactly the approach that you're taking (it doesn't need to use your real company-specific-proprietary library.

hosea commented 1 year ago

Hi Phil, Andy,

I attached a simple sample. It is the slightly adjusted code that I use: spring-boot-36479.tar.gz

There is a small JUnit-Test, that triggers both cases "onSuccess" (for property "secret") and "onFailure" (for property "url").

There is another observation, that I just want to mention: Class Binder calls context.getConverter().convert(result, target) after nearly all BindHandler-methods.

These are the "interesting" points in mapping the "plain" value to the "real" bound object. And there is exactly one point where context.getConverter().convert(result, target) is called and there is no preceding call of a method of BindHandler, and that's the extension that I have asked for.

If you add this additional method (I just named it "onBind"), there is a real powerful API to extend the mapping at every "interesting" point. Further thinking: You could even integrate the context.getConverter().convert(result, target) into a BindHandler and simplify the Binding-Code.

Kind regards Hans