codeconsole commented on PR #16019: URL: https://github.com/apache/grails-core/pull/16019#issuecomment-5094651012
The `grails-domain-class` conversion (700cf9c329), same pattern and the same naming decision as the cache one: the sibling takes the convention name `DomainClassAutoConfiguration` rather than being pinned to `GrailsDomainClassAutoConfiguration`. This one also exercises two things the earlier conversions did not — replacing constructor injection, and a rename that other modules reference. Imports and comments are trimmed here; each linked filename is the verbatim, commit-pinned source. Before, [`GrailsDomainClassAutoConfiguration.groovy`](https://github.com/codeconsole/grails-core/blob/311fb9a959e646469432ba8983ee02319fffbd6c/grails-domain-class/src/main/groovy/org/grails/plugins/domain/GrailsDomainClassAutoConfiguration.groovy#L40-L79) (since deleted): ```groovy @CompileStatic @AutoConfiguration(afterName = ['org.grails.plugins.i18n.I18nAutoConfiguration']) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) class GrailsDomainClassAutoConfiguration { GrailsApplication grailsApplication List<MessageSource> messageSources @Autowired GrailsDomainClassAutoConfiguration(GrailsApplication grailsApplication, List<MessageSource> messageSources) { this.grailsApplication = grailsApplication this.messageSources = messageSources } @Lazy @Bean(name = 'grailsDomainClassMappingContext') DefaultMappingContextFactoryBean grailsDomainClassMappingContext(List<ConstraintFactory> factories) { new DefaultMappingContextFactoryBean(grailsApplication, messageSources).tap { constraintFactories = factories ?: [] } } @Lazy @Bean DefaultConstraintEvaluatorFactoryBean validateableConstraintsEvaluator(@Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext) { new DefaultConstraintEvaluatorFactoryBean(messageSources, mappingContext, grailsApplication) } @Lazy @Bean ValidatorRegistryFactoryBean gormValidatorRegistry(@Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext) { new ValidatorRegistryFactoryBean().tap { it.mappingContext = mappingContext } } } ``` After — [`DomainClassGrailsPlugin.groovy`](https://github.com/codeconsole/grails-core/blob/700cf9c329a16e67179566a3879aeb29c3d7beb1/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy#L49-L85)'s class declaration and `beans` block (the plugin's metadata properties between them are elided below, unchanged by the conversion; `beanRegistrar()` further down the file is pre-existing plugin logic, untouched): ```groovy @CompileStatic @GrailsBeans @AutoConfiguration(afterName = ['org.grails.plugins.i18n.I18nAutoConfiguration']) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) class DomainClassGrailsPlugin extends Plugin { // ... pre-existing plugin metadata properties, unchanged ... def beans = { bean('grailsDomainClassMappingContext', DefaultMappingContextFactoryBean).lazy() { GrailsApplication grailsApplication, List<MessageSource> messageSources, List<ConstraintFactory> factories -> new DefaultMappingContextFactoryBean(grailsApplication, messageSources).tap { constraintFactories = factories ?: [] } } bean('validateableConstraintsEvaluator', DefaultConstraintEvaluatorFactoryBean).lazy() { GrailsApplication grailsApplication, List<MessageSource> messageSources, @Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext -> new DefaultConstraintEvaluatorFactoryBean(messageSources, mappingContext, grailsApplication) } bean('gormValidatorRegistry', ValidatorRegistryFactoryBean).lazy() { @Qualifier('grailsDomainClassMappingContext') MappingContext mappingContext -> new ValidatorRegistryFactoryBean().tap { it.mappingContext = mappingContext } } } ``` The one structural change is the constructor. The deleted class held `grailsApplication` and `messageSources` as fields populated by an `@Autowired` constructor, and the generated sibling always has a no-arg constructor, so neither could be reproduced as-is. Declaring them as `field(...)` instead would not have worked either: a `field('messageSources', List)` is a raw `List`, and Spring cannot resolve that injection point without an element type. Taking both as bean method parameters keeps the generics, and Spring resolves them identically — only when the bean that needs them is created, rather than when the configuration class is instantiated. Verified with javap: ``` public DefaultMappingContextFactoryBean grailsDomainClassMappingContext(GrailsApplication, List<MessageSource>, List<ConstraintFactory>) ``` `List<MessageSource>` and `List<ConstraintFactory>` survive as distinct injection points, and the two `@Qualifier('grailsDomainClassMappingContext') MappingContext` parameters carry their annotation through from the closure. Unlike the cache rename, this class is referenced across modules, so two call sites move with it. `ControllersAutoConfiguration` orders itself after this one by class literal, and that reference simply follows the rename — worth stating explicitly, since the generated sibling is emitted into the module's jar and therefore resolves from a dependent module's Java compile like any other class. (Verified rather than assumed: swapping the reference to `after = {DomainClassAutoConfiguration.class}` compiles cleanly.) That keeps the reference type-safe, so a future rename is a compile error rather than a silently stale string. The 8.0 upgrade guide's `grails-domain-class` row also gains a note naming the new class and telling anyone with an `@EnableAutoConfiguration(exclude = ...)` or `spring.autoconfigure.exclude` entry to update it; the row's existing mention of the old name is left alone, since it documents the removed `constraintsEvaluator` API rather than the current class. `grails-domain-class`, `grails-controllers`, `grails-cache` and the uber, web and persistence test suites all pass. -- 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]
