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

   The `grails-core` conversion (6986f0cc12, with the follow-up fix in 
100b9dbf77), same pattern. This is the first one where the plugin keeps its 
legacy `doWithSpring()` — the bean builder closure is isolated with 
`@CompileDynamic` so the class itself can carry `@CompileStatic`, which the 
transform copies onto the generated sibling — and the first where the sibling 
does not land on the deleted class's exact package. Imports and comments are 
trimmed here; each linked filename is the verbatim, commit-pinned source.
   
   Before, 
[`CoreAutoConfiguration.java`](https://github.com/codeconsole/grails-core/blob/5c71d9e88ceae522071f724681b5de2baafdb43a/grails-core/src/main/groovy/org/grails/plugins/core/CoreAutoConfiguration.java#L41-L69)
 (since deleted):
   
   ```java
   @AutoConfiguration(before = { PropertyPlaceholderAutoConfiguration.class })
   @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
   public class CoreAutoConfiguration {
   
       @Value("${" + Settings.SPRING_PLACEHOLDER_PREFIX + ":#{null}}")
       private String placeholderPrefix;
   
       @Bean
       @Primary
       public ClassLoader classLoader(GrailsApplication grailsApplication) {
           return grailsApplication.getClassLoader();
       }
   
       @Bean
       @Primary
       public ConfigProperties grailsConfigProperties(GrailsApplication 
grailsApplication) {
           return new ConfigProperties(grailsApplication.getConfig());
       }
   
       @Bean
       @Primary
       PropertySourcesPlaceholderConfigurer 
propertySourcesPlaceholderConfigurer() {
           GrailsPlaceholderConfigurer grailsPlaceholderConfigurer = new 
GrailsPlaceholderConfigurer();
           if (placeholderPrefix != null) {
               
grailsPlaceholderConfigurer.setPlaceholderPrefix(placeholderPrefix);
           }
           return grailsPlaceholderConfigurer;
       }
   }
   ```
   
   After — 
[`CoreGrailsPlugin.groovy`](https://github.com/codeconsole/grails-core/blob/100b9dbf77d65a32cef2f1698113052fa9f59ac7/grails-core/src/main/groovy/org/grails/plugins/CoreGrailsPlugin.groovy#L67-L103)'s
 class declaration and `beans` block (the plugin's metadata properties between 
them are elided below, unchanged by the conversion; `doWithSpring()` and 
`onChange()` further down the file are pre-existing plugin logic, untouched):
   
   ```groovy
   @CompileStatic
   @GrailsBeans
   @AutoConfiguration(before = [PropertyPlaceholderAutoConfiguration])
   @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
   class CoreGrailsPlugin extends Plugin {
   
       // ... pre-existing plugin metadata properties, unchanged ...
   
       def beans = {
           bean('classLoader', ClassLoader).primary() { GrailsApplication 
grailsApplication ->
               grailsApplication.classLoader
           }
   
           bean('grailsConfigProperties', ConfigProperties).primary() { 
GrailsApplication grailsApplication ->
               new ConfigProperties(grailsApplication.config)
           }
   
           bean('propertySourcesPlaceholderConfigurer', 
PropertySourcesPlaceholderConfigurer).primary().staticMethod() { Environment 
environment ->
               def configurer = new GrailsPlaceholderConfigurer()
               String prefix = 
environment.getProperty(Settings.SPRING_PLACEHOLDER_PREFIX)
               if (prefix != null) {
                   configurer.placeholderPrefix = prefix
               }
               configurer
           }
       }
   ```
   
   `CoreGrailsPlugin` lives in `org.grails.plugins` while the deleted class was 
in `org.grails.plugins.core`, and the sibling is always emitted into the 
plugin's own package, so the class becomes 
`org.grails.plugins.CoreAutoConfiguration` and the single hand-maintained 
`AutoConfiguration.imports` entry moves with it. Nothing else in the repository 
referenced the old package, and the `org.grails` prefix filter in 
`grails-testing-support-core` still matches. `@AutoConfiguration(before = ...)` 
and `@AutoConfigureOrder` move onto the sibling at compile time, and javap 
confirms the rest is equivalent to the deleted Java class: the same three 
method signatures, the same `@Bean`/`@Primary` pairs, and no `invokedynamic` 
call sites, with the `beans` closure not surviving on the plugin class.
   
   The `.staticMethod()` on the placeholder configurer is a behaviour fix 
rather than a like-for-like port, and it is worth calling out because the DSL 
made it visible. `grails.spring.placeholder.prefix` never had any effect: the 
configurer is a `BeanFactoryPostProcessor`, so its configuration class is 
instantiated during `invokeBeanFactoryPostProcessors`, before 
`AutowiredAnnotationBeanPostProcessor` is registered, and the `@Value` field 
the original instance method read was therefore always `null` — confirmed by 
reflection against a refreshed context, where the field held `null` and the 
configurer kept the default `${` prefix. A `static` factory method needs no 
enclosing instance and can take the `Environment` directly, which is the shape 
Boot's own `PropertyPlaceholderAutoConfiguration` uses, so the configured 
prefix now actually applies.
   
   The auto-configuration previously had no test coverage at all; the new 
`CoreAutoConfigurationSpec` asserts the three beans and their types, the class 
loader identity, `@Primary` winning against a competing `ClassLoader` 
candidate, the config properties read-through to the application config, Boot's 
`PropertyPlaceholderAutoConfiguration` ordering after this one and backing off, 
default-prefix placeholder resolution in bean definitions, an unresolvable 
placeholder being left in place rather than failing the context, and — newly 
possible — a configured prefix both resolving `@{foo.bar}` and displacing the 
default so `${foo.bar}` is left literal. One dependency note for anyone writing 
similar specs: `spring-boot-test` alone is not enough, because 
`ApplicationContextRunner`'s signatures reach AssertJ through 
`ApplicationContextAssertProvider`; without `assertj-core` on the test 
classpath Groovy cannot introspect the runner at all — its metaclass degrades 
to `Object`'s methods and
  every call fails to dispatch with `MissingMethodException`.
   


-- 
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