codeconsole commented on PR #16019:
URL: https://github.com/apache/grails-core/pull/16019#issuecomment-5095501387

   The `grails-databinding` conversion (623ce9748d), which drove a DSL 
addition: `bean(Type)` no longer requires a factory closure (4dab384019). Five 
of these seven beans were nothing but their own no-argument construction, and 
spelling that out as `bean('xmlDataBindingSourceCreator', 
XmlDataBindingSourceCreator) { new XmlDataBindingSourceCreator() }` restates 
the type three times to say nothing. Imports and comments are trimmed here; 
each linked filename is the verbatim, commit-pinned source.
   
   Before, 
[`DataBindingConfiguration.java`](https://github.com/codeconsole/grails-core/blob/700cf9c329a16e67179566a3879aeb29c3d7beb1/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingConfiguration.java#L49-L132)
 (since deleted):
   
   ```java
   @AutoConfiguration
   @AutoConfigureOrder
   @EnableConfigurationProperties(DataBindingConfigurationProperties.class)
   @ImportAutoConfiguration(DefaultConvertersConfiguration.class)
   public class DataBindingConfiguration {
   
       private final DataBindingConfigurationProperties configurationProperties;
   
       public DataBindingConfiguration(DataBindingConfigurationProperties 
configurationProperties) {
           this.configurationProperties = configurationProperties;
       }
   
       @Lazy
       @Bean("grailsWebDataBinder")
       protected GrailsWebDataBinder grailsWebDataBinder(
               GrailsApplication grailsApplication,
               ValueConverter[] valueConverters,
               FormattedValueConverter[] formattedValueConverters,
               TypedStructuredBindingEditor[] structuredBindingEditors,
               DataBindingListener[] dataBindingListeners) {
   
           GrailsWebDataBinder dataBinder = new 
GrailsWebDataBinder(grailsApplication);
           
dataBinder.setConvertEmptyStringsToNull(configurationProperties.isConvertEmptyStringsToNull());
           // ... converter/editor/listener merging with the main context, 
elided ...
           return dataBinder;
       }
   
       @Bean("xmlDataBindingSourceCreator")
       protected XmlDataBindingSourceCreator xmlDataBindingSourceCreator() {
           return new XmlDataBindingSourceCreator();
       }
   
       @Bean("jsonDataBindingSourceCreator")
       protected JsonDataBindingSourceCreator jsonDataBindingSourceCreator() {
           return new JsonDataBindingSourceCreator();
       }
   
       @Bean("halJsonDataBindingSourceCreator")
       protected HalJsonDataBindingSourceCreator 
halJsonDataBindingSourceCreator() {
           return new HalJsonDataBindingSourceCreator();
       }
   
       @Bean("halXmlDataBindingSourceCreator")
       protected HalXmlDataBindingSourceCreator 
halXmlDataBindingSourceCreator() {
           return new HalXmlDataBindingSourceCreator();
       }
   
       @Bean("jsonApiDataBindingSourceCreator")
       protected JsonApiDataBindingSourceCreator 
jsonApiDataBindingSourceCreator() {
           return new JsonApiDataBindingSourceCreator();
       }
   
       @Bean("dataBindingSourceRegistry")
       protected DataBindingSourceRegistry 
dataBindingSourceRegistry(DataBindingSourceCreator... creators) {
           final DefaultDataBindingSourceRegistry registry = new 
DefaultDataBindingSourceRegistry();
           registry.setDataBindingSourceCreators(creators);
           registry.initialize();
           return registry;
       }
   }
   ```
   
   After — 
[`DataBindingGrailsPlugin.groovy`](https://github.com/codeconsole/grails-core/blob/bab7b058f3527c311c6da2464a72fdaab269c185/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingGrailsPlugin.groovy#L60-L130)'s
 class declaration and `beans` block. The plugin previously held nothing but a 
`version` property, so this is the whole file:
   
   ```groovy
   @CompileStatic
   @GrailsBeans
   @AutoConfiguration
   @AutoConfigureOrder
   @EnableConfigurationProperties(DataBindingConfigurationProperties)
   @ImportAutoConfiguration(DefaultConvertersConfiguration)
   class DataBindingGrailsPlugin extends Plugin {
   
       def version = GrailsUtil.getGrailsVersion()
   
       def beans = {
           bean(GrailsWebDataBinder).lazy() { GrailsApplication 
grailsApplication,
                   DataBindingConfigurationProperties configurationProperties,
                   ValueConverter[] valueConverters,
                   FormattedValueConverter[] formattedValueConverters,
                   TypedStructuredBindingEditor[] structuredBindingEditors,
                   DataBindingListener[] dataBindingListeners ->
   
               GrailsWebDataBinder dataBinder = new 
GrailsWebDataBinder(grailsApplication)
               dataBinder.convertEmptyStringsToNull = 
configurationProperties.convertEmptyStringsToNull
               // ... converter/editor/listener merging with the main context, 
elided ...
               dataBinder
           }
   
           bean(XmlDataBindingSourceCreator)
           bean(JsonDataBindingSourceCreator)
           bean(HalJsonDataBindingSourceCreator)
           bean(HalXmlDataBindingSourceCreator)
           bean(JsonApiDataBindingSourceCreator)
   
           bean(DataBindingSourceRegistry) { DataBindingSourceCreator[] 
creators ->
               DefaultDataBindingSourceRegistry registry = new 
DefaultDataBindingSourceRegistry()
               registry.dataBindingSourceCreators = creators
               registry.initialize()
               registry
           }
       }
   }
   ```
   
   **The bodyless `bean(Type)` form.** The trailing closure is now optional: 
`bean(Type)` and `bean('name', Type)` generate a parameterless factory method 
returning `new Type()`, and chain the existing qualifiers exactly as the 
closure form does — `bean(Widget).primary().lazy().conditionalOnMissingBean()` 
compiles the same way it would with an empty body. Because it constructs the 
*declared* type, it is rejected at compile time for an interface or abstract 
class with a message pointing at the fix, rather than deferring to a confusing 
error inside generated code. That is precisely why `dataBindingSourceRegistry` 
above keeps its closure: it declares the `DataBindingSourceRegistry` interface 
while constructing `DefaultDataBindingSourceRegistry` and then initializing it.
   
   **No explicit names.** Each of these seven types decapitalizes to exactly 
the bean name the hand-written class declared, so passing the name would only 
restate it. Reading the `@Bean` values back out of the bytecode confirms all 
seven are unchanged. The same cleanup was applied to the earlier `grails-core` 
and `grails-cache` conversions (bab7b058f3), which had carried the same 
redundancy; the names that remain across all conversions are the ones a type 
genuinely does not produce — `grailsUrlConverter` from `UrlConverter`, 
`mailSession` from `JndiObjectFactoryBean`, `grailsDomainClassMappingContext` 
from `DefaultMappingContextFactoryBean`, and so on.
   
   **Two structural notes.** `configurationProperties` was a 
constructor-injected field, and the generated sibling always has a no-arg 
constructor; only `grailsWebDataBinder` reads it, so that one bean takes it as 
a parameter. And `dataBindingSourceRegistry`'s `DataBindingSourceCreator...` 
parameter is written as an array — Spring resolves both identically, and javap 
shows Groovy hands the generated method the varargs flag back anyway, since a 
trailing array parameter on a closure compiles to varargs.
   
   The class is renamed `DataBindingConfiguration` → 
`DataBindingAutoConfiguration` by the `*GrailsPlugin` → `*AutoConfiguration` 
convention. Beyond dropping the inconsistency, it corrects a class that was 
registered in `AutoConfiguration.imports` while named only `*Configuration`. 
The imports entry was its only reference in the repository; the 7.0 upgrade 
guide's note about the original `DataBindingGrailsPlugin` → 
`DataBindingConfiguration` move is left alone as an accurate record of the 7.x 
change.
   
   One imperfection worth stating rather than glossing: the generated 
`grailsWebDataBinder` body keeps four explicit array casts on 
`GrailsArrayUtils.concat` that the Java original did not need. Groovy's 
`@CompileStatic` cannot infer `T[]` from `concat`'s `<T> T[]` signature the way 
javac does; removing the casts produces *more* runtime coercion, not less (nine 
`invokedynamic` sites rather than five), and an explicit type witness does not 
help either. The five that remain are all `invokedynamic cast` — array 
coercion, not dynamic dispatch — in a `@Lazy` bean method.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to