You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by jd...@apache.org on 2025/07/13 00:51:06 UTC

(grails-core) branch micronautTests created (now 8149e31d09)

This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a change to branch micronautTests
in repository https://gitbox.apache.org/repos/asf/grails-core.git


      at 8149e31d09 WIP: restore micronaut code (needs adjusted for SpringApplicationBuilder)

This branch includes the following new commits:

     new f54f4d2bbf fix: update type to remove CompileDynamic
     new ba04bfd90c chore: update minimum grails version
     new 8149e31d09 WIP: restore micronaut code (needs adjusted for SpringApplicationBuilder)

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(grails-core) 02/03: chore: update minimum grails version

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch micronautTests
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit ba04bfd90c5e25b32d27246cc1062d7ae9be49f3
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Sat Jul 12 20:08:36 2025 -0400

    chore: update minimum grails version
---
 .../org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy   | 2 +-
 .../src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy       | 2 +-
 .../main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy   | 2 +-
 .../src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy  | 2 +-
 .../main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy  | 2 +-
 grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy    | 3 ++-
 .../groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy    | 2 +-
 .../src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy           | 2 +-
 .../loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy   | 2 +-
 .../src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy           | 2 +-
 .../main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy    | 2 +-
 .../groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy     | 2 +-
 12 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy
index f6b20c9850..3cb10d0eac 100644
--- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy
+++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy
@@ -30,7 +30,7 @@ import org.grails.plugins.web.async.spring.PromiseFactoryBean
  * @since 2.0
  */
 class ControllersAsyncGrailsPlugin extends Plugin {
-    def grailsVersion = "7.0.0 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     def loadAfter = ['controllers']
     Closure doWithSpring() {{->
         asyncPromiseResponseActionResultTransformer(AsyncActionResultTransformer)
diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy
index 86d57e2029..45a0c84a59 100644
--- a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy
+++ b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy
@@ -28,7 +28,7 @@ import org.springframework.cache.Cache
 @Slf4j
 class CacheGrailsPlugin extends Plugin {
 
-    def grailsVersion = "7.0.0 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     def observe = ['controllers', 'services']
     def loadAfter = ['controllers', 'services']
     def authorEmail = 'brownj@objectcomputing.com'
diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy
index 902df43498..9dea58c1b5 100644
--- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy
+++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy
@@ -45,7 +45,7 @@ class HibernateGrailsPlugin extends Plugin {
 
     public static final String DEFAULT_DATA_SOURCE_NAME = HibernateDatastoreSpringInitializer.DEFAULT_DATA_SOURCE_NAME
 
-    def grailsVersion = '7.0.0 > *'
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
 
     def author = 'Grails Core Team'
     def title = 'Hibernate 5 for Grails'
diff --git a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy
index 8484ac385d..5a53f94c46 100644
--- a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy
+++ b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy
@@ -38,7 +38,7 @@ class MongodbGrailsPlugin extends Plugin {
     def organization = [name: 'Grails', url: 'https://grails.org/']
     def issueManagement = [system: 'Github', url: 'https://github.com/grails/gorm-mongodb']
     def scm = [url: 'https://github.com/grails/gorm-mongodb']
-    def grailsVersion = '7.0.0 > *'
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     def observe = ['services', 'domainClass']
     def loadAfter = ['domainClass', 'hibernate', 'hibernate5', 'hibernate6', 'services']
     def title = 'GORM MongoDB'
diff --git a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy
index 5cb71ef75d..71f349696e 100644
--- a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy
+++ b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy
@@ -34,7 +34,7 @@ import reactor.bus.EventBus
  */
 class EventBusGrailsPlugin extends Plugin {
 
-    def grailsVersion = "7.0.0 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
 
     /**
      * Whether to translate GORM events into reactor events
diff --git a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy
index 67df92d889..05b0f98658 100644
--- a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy
+++ b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy
@@ -26,7 +26,8 @@ import groovy.transform.CompileStatic
 @PluginSource
 @CompileStatic
 class GebGrailsPlugin extends Plugin {
-    def grailsVersion = "7.0.0 > *"
+
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     def pluginExcludes = []
     def title = "Grails Geb Plugin"
     def author = "Graeme Rocher"
diff --git a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy b/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy
index e8cf73a282..8160dafe1c 100644
--- a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy
+++ b/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy
@@ -26,7 +26,7 @@ import grails.util.Metadata
 class ScaffoldingGrailsPlugin extends Plugin {
 
    // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "4.0.0.BUILD-SNAPSHOT > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     // resources that are excluded from plugin packaging
     def pluginExcludes = [
         "grails-app/views/error.gsp"
diff --git a/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy b/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy
index 89e1b8a384..483ae73e80 100644
--- a/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy
+++ b/grails-test-examples/plugins/issue11005/src/main/groovy/issue11005/Issue11005GrailsPlugin.groovy
@@ -24,7 +24,7 @@ import grails.plugins.*
 class Issue11005GrailsPlugin extends Plugin {
 
     // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "3.3.6 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
     // resources that are excluded from plugin packaging
     def pluginExcludes = [
         "grails-app/views/error.gsp"
diff --git a/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy b/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy
index c259f87c8f..75fd29d1be 100644
--- a/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy
+++ b/grails-test-examples/plugins/loadfirst/src/main/groovy/loadfirst/LoadfirstGrailsPlugin.groovy
@@ -24,7 +24,7 @@ import grails.plugins.*
 class LoadfirstGrailsPlugin extends Plugin {
 
    // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "3.0.0.BUILD-SNAPSHOT > *"
+    def grailsVersion = '7.0.0.SNAPSHOT > *'
     // resources that are excluded from plugin packaging
     def pluginExcludes = [
         "grails-app/views/error.gsp"
diff --git a/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy b/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy
index 2dce052fb0..9a288a267a 100644
--- a/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy
+++ b/grails-test-examples/plugins/loadsecond/src/main/groovy/loadsecond/LoadsecondGrailsPlugin.groovy
@@ -24,7 +24,7 @@ import grails.plugins.*
 class LoadsecondGrailsPlugin extends Plugin {
 
    // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "3.0.0.BUILD-SNAPSHOT > *"
+    def grailsVersion = '7.0.0.SNAPSHOT > *'
     // resources that are excluded from plugin packaging
     def pluginExcludes = [
         "grails-app/views/error.gsp"
diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy b/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy
index 34b22a9cf5..8b6ca0e0bb 100644
--- a/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy
+++ b/grails-views-gson/src/main/groovy/grails/plugin/json/view/JsonViewGrailsPlugin.groovy
@@ -29,7 +29,7 @@ import grails.views.resolve.PluginAwareTemplateResolver
 class JsonViewGrailsPlugin extends Plugin {
 
     // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "7.0.0 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
 
     def title = "JSON Views" // Headline display name of the plugin
     def author = "Graeme Rocher"
diff --git a/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy b/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy
index 9c7320d605..5141f2d17f 100644
--- a/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy
+++ b/grails-views-markup/src/main/groovy/grails/plugin/markup/view/MarkupViewGrailsPlugin.groovy
@@ -33,7 +33,7 @@ import grails.views.resolve.PluginAwareTemplateResolver
 class MarkupViewGrailsPlugin extends Plugin {
 
     // the version or versions of Grails the plugin is designed for
-    def grailsVersion = "7.0.0 > *"
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
 
     def title = "Markup Views" // Headline display name of the plugin
     def author = "Graeme Rocher"


(grails-core) 01/03: fix: update type to remove CompileDynamic

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch micronautTests
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit f54f4d2bbfd75f6faa6533a6c4fe3b022f2ab714
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri Jul 11 21:37:22 2025 -0400

    fix: update type to remove CompileDynamic
---
 grails-core/src/main/groovy/grails/boot/GrailsApp.groovy | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
index e219f3b27f..52e7a6d01b 100644
--- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
+++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
@@ -26,7 +26,6 @@ import grails.plugins.GrailsPlugin
 import grails.plugins.GrailsPluginManager
 import grails.util.BuildSettings
 import grails.util.Environment
-import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
 import org.codehaus.groovy.control.CompilationFailedException
@@ -143,7 +142,6 @@ class GrailsApp extends SpringApplication {
         configuredEnvironment = environment
     }
 
-    @CompileDynamic // TODO: Report Groovy VerifierError
     protected void enableDevelopmentModeWatch(Environment environment, ConfigurableApplicationContext applicationContext, String... args) {
         def location = environment.getReloadLocation()
 
@@ -235,8 +233,7 @@ class GrailsApp extends SpringApplication {
 
                 while (isDevelopmentModeActive()) {
                     // Workaround for some IDE / OS combos - 2 events (new + update) for the same file
-                    def uniqueChangedFiles = changedFiles as Set
-
+                    def uniqueChangedFiles = changedFiles as Set<File>
 
                     def i = uniqueChangedFiles.size()
                     try {


(grails-core) 03/03: WIP: restore micronaut code (needs adjusted for SpringApplicationBuilder)

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch micronautTests
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 8149e31d0983b315082f745782f14e589385ac7f
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Sat Jul 12 20:50:44 2025 -0400

    WIP: restore micronaut code (needs adjusted for SpringApplicationBuilder)
---
 gradle.properties                                  |   8 +-
 gradle/publish-root-config.gradle                  |   1 +
 .../boot/ApplicationContextCustomizer.groovy       |  15 ++-
 .../src/main/groovy/grails/boot/GrailsApp.groovy   |  59 ++++++++----
 .../config/GrailsApplicationPostProcessor.groovy   |   1 +
 grails-micronaut/build.gradle                      |  71 ++++++++++++++
 .../micronaut/GrailsMicronautGrailsPlugin.groovy   |  80 +++++++++++++++
 .../micronaut/MicronautParentContextAdder.groovy   |  88 +++++++++++++++++
 .../micronaut/MicronautShutdownListener.groovy     |  22 +++--
 .../MicronautGroovyPropertySourceLoader.groovy     | 107 +++++++++++++++++++++
 .../MicronautYamlPropertySourceLoader.groovy       |  74 ++++++++++++++
 .../io.micronaut.context.env.PropertySourceLoader  |  20 ++++
 .../grails/spring/GrailsApplicationContext.java    |   8 +-
 grails-test-examples/micronaut/build.gradle        |  38 +++-----
 .../grails-app/init/micronaut/Application.groovy   |   5 +-
 .../grails-app/init/micronaut/BootStrap.groovy     |   2 +
 .../context/GrailsWebApplicationContext.java       |  14 ++-
 settings.gradle                                    |   8 +-
 18 files changed, 551 insertions(+), 70 deletions(-)

diff --git a/gradle.properties b/gradle.properties
index 84a4d121d3..ad5ac00be8 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -55,10 +55,14 @@ org.gradle.daemon=true
 # this is a future TODO see groovydoc-tool-rewrite branch for experiementations with this
 org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx5G
 
+# micronaut libraries not in the bom due to the potential for spring mismatches
+micronautVersion=4.9.7
+micronautCacheVersion=5.3.0
+micronautSpringVersion=5.11.0
+micronautSerdeJacksonVersion=2.11.0
+
 # libraries only specific to test apps, these should not be exposed
 jbossTransactionApiVersion=2.0.0.Final
-micronautVersion=4.6.5
-micronautSerdeJacksonVersion=2.11.0
 grailsSpringSecurityVersion=7.0.0-SNAPSHOT
 
 # This prevents the Grails Gradle Plugin from unnecessarily excluding slf4j-simple in the generated POMs
diff --git a/gradle/publish-root-config.gradle b/gradle/publish-root-config.gradle
index 728b364111..fb711095d0 100644
--- a/gradle/publish-root-config.gradle
+++ b/gradle/publish-root-config.gradle
@@ -63,6 +63,7 @@ def publishedProjects = [
         'grails-interceptors',
         'grails-logging',
         'grails-mimetypes',
+        'grails-micronaut',
         'grails-rest-transforms',
         'grails-scaffolding',
         'grails-services',
diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy b/grails-core/src/main/groovy/grails/boot/ApplicationContextCustomizer.groovy
similarity index 70%
copy from grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
copy to grails-core/src/main/groovy/grails/boot/ApplicationContextCustomizer.groovy
index 0524a40ab2..ad695014a7 100644
--- a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
+++ b/grails-core/src/main/groovy/grails/boot/ApplicationContextCustomizer.groovy
@@ -17,16 +17,13 @@
  *  under the License.
  */
 
-package micronaut
+package grails.boot
 
-import grails.boot.GrailsApp
-import grails.boot.config.GrailsAutoConfiguration
+import org.springframework.context.ConfigurableApplicationContext
+import org.springframework.core.env.ConfigurableEnvironment
 
-import groovy.transform.CompileStatic
+interface ApplicationContextCustomizer {
+
+    void customizeContext(ConfigurableApplicationContext context, ClassLoader applicationClassLoader, ConfigurableEnvironment configuredEnvironment)
 
-@CompileStatic
-class Application extends GrailsAutoConfiguration {
-    static void main(String[] args) {
-        GrailsApp.run(Application, args)
-    }
 }
\ No newline at end of file
diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
index 52e7a6d01b..73db55d501 100644
--- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
+++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
@@ -65,6 +65,8 @@ class GrailsApp extends SpringApplication {
     private static boolean developmentModeActive = false
     private static DirectoryWatcher directoryWatcher
 
+    private ApplicationContextCustomizer applicationContextCustomizer
+
     boolean enableBeanCreationProfiler = false
     ConfigurableEnvironment configuredEnvironment
 
@@ -72,10 +74,10 @@ class GrailsApp extends SpringApplication {
      * Create a new {@link GrailsApp} instance. The application context will load
      * beans from the specified sources (see {@link SpringApplication class-level}
      * documentation for details. The instance can be customized before calling
-     * {@link #run(String...)}.
+     * {@link #run(String ...)}.
      * @param sources the bean sources
-     * @see #run(Object, String[])
-     * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class<?>...)
+     * @see #run(Class [ ], String [ ])
+     * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class <?> ...)
      */
     GrailsApp(Class<?>... sources) {
         super(sources)
@@ -85,11 +87,11 @@ class GrailsApp extends SpringApplication {
      * Create a new {@link GrailsApp} instance. The application context will load
      * beans from the specified sources (see {@link SpringApplication class-level}
      * documentation for details. The instance can be customized before calling
-     * {@link #run(String...)}.
+     * {@link #run(String ...)}.
      * @param resourceLoader the resource loader to use
      * @param sources the bean sources
-     * @see #run(Object, String[])
-     * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class<?>...)
+     * @see #run(Class [ ], String [ ])
+     * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class <?> ...)
      */
     GrailsApp(ResourceLoader resourceLoader, Class<?>... sources) {
         super(resourceLoader, sources)
@@ -100,12 +102,12 @@ class GrailsApp extends SpringApplication {
         ConfigurableApplicationContext applicationContext = super.run(args)
         Environment environment = Environment.getCurrent()
 
-        log.info("Application starting in environment: {}", environment.getName())
-        log.debug("Application directory discovered as: {}", IOUtils.findApplicationDirectory())
-        log.debug("Current base directory is [{}]. Reloading base directory is [{}]", new File("."), BuildSettings.BASE_DIR)
+        log.info('Application starting in environment: {}', environment.getName())
+        log.debug('Application directory discovered as: {}', IOUtils.findApplicationDirectory())
+        log.debug('Current base directory is [{}]. Reloading base directory is [{}]', new File('.'), BuildSettings.BASE_DIR)
 
         if (environment.isReloadEnabled()) {
-            log.debug("Reloading status: {}", environment.isReloadEnabled())
+            log.debug('Reloading status: {}', environment.isReloadEnabled())
             enableDevelopmentModeWatch(environment, applicationContext)
             environment.isDevtoolsRestart()
         }
@@ -119,6 +121,10 @@ class GrailsApp extends SpringApplication {
         setAllowBeanDefinitionOverriding(true)
         setAllowCircularReferences(true)
         ConfigurableApplicationContext applicationContext = super.createApplicationContext()
+        if (applicationContextCustomizer) {
+            ClassLoader applicationClassLoader = this.classLoader
+            applicationContextCustomizer.customizeContext(applicationContext, applicationClassLoader, configuredEnvironment)
+        }
 
         if (enableBeanCreationProfiler) {
             def processor = new BeanCreationProfilingPostProcessor()
@@ -152,6 +158,7 @@ class GrailsApp extends SpringApplication {
             Queue<File> newFiles = new ConcurrentLinkedQueue<>()
 
             directoryWatcher.addListener(new FileExtensionFileChangeListener(['groovy', 'java']) {
+
                 @Override
                 void onChange(File file, List<String> extensions) {
                     changedFiles << file.canonicalFile
@@ -162,7 +169,7 @@ class GrailsApp extends SpringApplication {
                     changedFiles << file.canonicalFile
                     // For some bizarre reason Windows fires onNew events even for files that have
                     // just been modified and not created
-                    if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) {
+                    if (System.getProperty('os.name').toLowerCase().indexOf('windows') != -1) {
                         return
                     }
                     newFiles << file.canonicalFile
@@ -225,7 +232,6 @@ class GrailsApp extends SpringApplication {
                 }
             }
 
-
             developmentModeActive = true
             Thread.start {
                 CompilerConfiguration compilerConfig = new CompilerConfiguration()
@@ -302,12 +308,12 @@ class GrailsApp extends SpringApplication {
         }
         def baseFileLocation = appDir?.absolutePath ?: location
         compilerConfig.setTargetDirectory(new File(baseFileLocation, BuildSettings.BUILD_CLASSES_PATH))
-        println "File $changedFile changed, recompiling..."
+        printf('File %s changed, recompiling...%n', changedFile)
         if (changedFile.name.endsWith('.java')) {
             if (JavaCompiler.isAvailable()) {
                 JavaCompiler.recompile(compilerConfig, changedFile)
             } else {
-                log.error("Cannot recompile [$changedFile.name], the current JVM is not a JDK (recompilation will not work on a JRE missing the compiler APIs).")
+                log.error('Cannot recompile [{}], the current JVM is not a JDK (recompilation will not work on a JRE missing the compiler APIs).', changedFile.name)
             }
         } else {
             compileGroovyFile(compilerConfig, changedFile)
@@ -335,6 +341,7 @@ class GrailsApp extends SpringApplication {
     protected static DirectoryWatcher.FileChangeListener createPluginManagerListener(ConfigurableApplicationContext applicationContext) {
         def pluginManager = applicationContext.getBean(GrailsPluginManager)
         return new DirectoryWatcher.FileChangeListener() {
+
             @Override
             void onChange(File file) {
                 if (!file.name.endsWith('.groovy') && !file.name.endsWith('.java')) {
@@ -352,9 +359,9 @@ class GrailsApp extends SpringApplication {
     }
 
     protected void configureDirectoryWatcher(DirectoryWatcher directoryWatcher, String location) {
-        directoryWatcher.addWatchDirectory(new File(location, "grails-app"), ['groovy', 'java'])
-        directoryWatcher.addWatchDirectory(new File(location, "src/main/groovy"), ['groovy', 'java'])
-        directoryWatcher.addWatchDirectory(new File(location, "src/main/java"), ['groovy', 'java'])
+        directoryWatcher.addWatchDirectory(new File(location, 'grails-app'), ['groovy', 'java'])
+        directoryWatcher.addWatchDirectory(new File(location, 'src/main/groovy'), ['groovy', 'java'])
+        directoryWatcher.addWatchDirectory(new File(location, 'src/main/java'), ['groovy', 'java'])
     }
 
     protected printRunStatus(ConfigurableApplicationContext applicationContext) {
@@ -363,11 +370,11 @@ class GrailsApp extends SpringApplication {
             String protocol = app.config.getProperty('server.ssl.key-store') ? 'https' : 'http'
             String contextPath = app.config.getProperty('server.servlet.context-path', '')
             String hostName = app.config.getProperty('server.address', 'localhost')
-            int port
+            int port = 0
             if (applicationContext instanceof WebServerApplicationContext) {
                 port = applicationContext.webServer.port
             }
-            println("Grails application running at ${protocol}://${hostName}:${port}${contextPath} in environment: ${Environment.current.name}")
+            printf('Grails application running at %s://%s:%s%s in environment: %s%n', protocol, hostName, port, contextPath, Environment.current.name)
 
         } catch (ignore) {
         }
@@ -389,10 +396,24 @@ class GrailsApp extends SpringApplication {
      * specified sources using default settings and user supplied arguments.
      * @param sources the sources to load
      * @param args the application arguments (usually passed from a Java main method)
+     * @param applicationContextCustomizer optional logic to customize the created application context, such as adding a parent context
      * @return the running {@link org.springframework.context.ApplicationContext}
      */
     static ConfigurableApplicationContext run(Class<?>[] sources, String[] args) {
+        run(sources, args, null)
+    }
+
+    /**
+     * Static helper that can be used to run a {@link GrailsApp} from the
+     * specified sources using default settings user supplied arguments.
+     * @param sources the sources to load
+     * @param args the application arguments (usually passed from a Java main method)
+     * @param applicationContextCustomizer optional logic to customize the created application context, such as adding a parent context
+     * @return the running {@link org.springframework.context.ApplicationContext}
+     */
+    static ConfigurableApplicationContext run(Class<?>[] sources, String[] args, ApplicationContextCustomizer applicationContextCustomizer) {
         GrailsApp grailsApp = new GrailsApp(sources)
+        grailsApp.applicationContextCustomizer = applicationContextCustomizer
         grailsApp.banner = new ResourceBanner(new ClassPathResource(GRAILS_BANNER))
         return grailsApp.run(args)
     }
diff --git a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy
index 91bdd5d0d7..e8510c0fb2 100644
--- a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy
+++ b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy
@@ -39,6 +39,7 @@ import org.grails.config.PropertySourcesConfig
 import org.grails.core.exceptions.GrailsConfigurationException
 import org.grails.core.lifecycle.ShutdownOperations
 import org.grails.datastore.mapping.model.MappingContext
+import org.grails.plugins.core.CoreAutoConfiguration
 import org.grails.spring.DefaultRuntimeSpringConfiguration
 import org.grails.spring.RuntimeSpringConfigUtilities
 import org.springframework.beans.BeansException
diff --git a/grails-micronaut/build.gradle b/grails-micronaut/build.gradle
new file mode 100644
index 0000000000..95bfce91a5
--- /dev/null
+++ b/grails-micronaut/build.gradle
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+plugins {
+    id 'groovy'
+    id 'java-library'
+    id 'project-report'
+}
+
+version = projectVersion
+group = 'org.apache.grails'
+
+dependencies {
+    implementation platform(project(':grails-bom'))
+
+    annotationProcessor "io.micronaut.cache:micronaut-cache-core:$micronautCacheVersion"
+    annotationProcessor "io.micronaut.spring:micronaut-spring-annotation:$micronautSpringVersion"
+    annotationProcessor "io.micronaut.spring:micronaut-spring-boot-annotation:$micronautSpringVersion"
+    annotationProcessor "io.micronaut:micronaut-inject-java:$micronautVersion"
+
+    implementation "io.micronaut.spring:micronaut-spring-annotation:$micronautSpringVersion"
+    implementation "io.micronaut:micronaut-inject-groovy:$micronautVersion"
+    implementation "io.micronaut:micronaut-inject-java:$micronautVersion"
+
+    api "io.micronaut:micronaut-inject:$micronautVersion"
+    api "io.micronaut:micronaut-runtime:$micronautVersion"
+    api "io.micronaut.spring:micronaut-spring-context:$micronautSpringVersion", {
+        exclude group:"org.slf4j", module: "slf4j-simple"
+    }
+
+    api "io.micronaut.cache:micronaut-cache-core:$micronautCacheVersion", {
+        exclude group:"org.slf4j", module: "slf4j-simple"
+    }
+
+    compileOnly project(':grails-core')
+
+    // Logging
+    compileOnly 'org.slf4j:slf4j-api'
+    compileOnly 'org.slf4j:jcl-over-slf4j'
+
+    // Testing
+    testImplementation 'org.slf4j:slf4j-simple'
+    testImplementation('org.spockframework:spock-core') { transitive = false }
+    // Required by Spock's Mocking
+    testRuntimeOnly 'net.bytebuddy:byte-buddy'
+    testImplementation 'org.objenesis:objenesis'
+}
+
+apply {
+    // java-configuration must be applied first since tasks are now lazy registered
+    from rootProject.layout.projectDirectory.file('gradle/java-config.gradle')
+    from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle')
+    from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle')
+    from rootProject.layout.projectDirectory.file('gradle/test-config.gradle')
+}
\ No newline at end of file
diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy
new file mode 100644
index 0000000000..0d3199a94c
--- /dev/null
+++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/GrailsMicronautGrailsPlugin.groovy
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.grails.micronaut
+
+import grails.plugins.GrailsPlugin
+import grails.plugins.GrailsPluginManager
+import grails.plugins.Plugin
+import groovy.util.logging.Slf4j
+import io.micronaut.context.env.AbstractPropertySourceLoader
+import io.micronaut.context.env.Environment
+import io.micronaut.context.env.PropertySource
+import io.micronaut.spring.context.env.MicronautEnvironment
+import org.springframework.context.ConfigurableApplicationContext
+import org.springframework.core.env.ConfigurableEnvironment
+
+@Slf4j
+class GrailsMicronautGrailsPlugin extends Plugin {
+
+    def grailsVersion = '7.0.0-SNAPSHOT > *'
+    def title = ''
+
+    @Override
+    void doWithApplicationContext() {
+        String[] beanNames = applicationContext.getBeanNamesForType(GrailsPluginManager)
+        GrailsPluginManager pluginManagerFromContext = beanNames.length ?
+                applicationContext.getBean(GrailsPluginManager) :
+                null
+
+        if (!pluginManagerFromContext && !pluginManager) {
+            // No plugin managers to search for plugin configurations
+            return
+        }
+
+        ConfigurableApplicationContext parentApplicationContext = (ConfigurableApplicationContext) applicationContext.parent
+        if (!parentApplicationContext) {
+            // No Micronaut parent context to load configurations to
+            return
+        }
+
+        ConfigurableEnvironment parentContextEnv = parentApplicationContext.getEnvironment()
+        if (parentContextEnv instanceof MicronautEnvironment) {
+            if (log.isDebugEnabled()) {
+                log.debug("Loading configurations from the plugins to the parent Micronaut context")
+            }
+            final Environment micronautEnv = ((Environment) parentContextEnv.getEnvironment())
+            final GrailsPlugin[] plugins = pluginManager.allPlugins
+            final GrailsPlugin[] pluginsFromContext = pluginManagerFromContext ? pluginManagerFromContext.allPlugins : new GrailsPlugin[] {}
+            Integer priority = AbstractPropertySourceLoader.DEFAULT_POSITION
+            [plugins, pluginsFromContext].each { GrailsPlugin[] pluginsToProcess ->
+                Arrays.stream(pluginsToProcess)
+                        .filter({ GrailsPlugin plugin -> plugin.propertySource != null })
+                        .forEach({ GrailsPlugin plugin ->
+                            if (log.isDebugEnabled()) {
+                                log.debug("Loading configurations from {} plugin to the parent Micronaut context", plugin.name)
+                            }
+                            micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.source, --priority))
+                        })
+            }
+            micronautEnv.refresh()
+            applicationContext.setParent(parentApplicationContext)
+        }
+    }
+}
diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautParentContextAdder.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautParentContextAdder.groovy
new file mode 100644
index 0000000000..6466fc8b98
--- /dev/null
+++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautParentContextAdder.groovy
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.grails.micronaut
+
+import grails.boot.ApplicationContextCustomizer
+import groovy.transform.CompileStatic
+import groovy.util.logging.Slf4j
+import io.micronaut.context.ApplicationContextConfiguration
+import io.micronaut.context.DefaultApplicationContext
+import io.micronaut.core.reflect.ClassUtils
+import io.micronaut.spring.context.factory.MicronautBeanFactoryConfiguration
+import org.springframework.context.ConfigurableApplicationContext
+import org.springframework.core.convert.ConversionService
+import org.springframework.core.env.ConfigurableEnvironment
+import org.springframework.core.env.Environment
+import org.springframework.core.env.PropertyResolver
+
+/**
+ * Helper class to set the micronaut context as the parent to the Grails applicationContext
+ */
+@Slf4j
+@CompileStatic
+class MicronautParentContextAdder implements ApplicationContextCustomizer {
+
+    @Override
+    void customizeContext(ConfigurableApplicationContext applicationContext, ClassLoader applicationClassLoader, ConfigurableEnvironment configuredEnvironment) {
+        def now = System.currentTimeMillis()
+        ApplicationContextConfiguration micronautConfiguration = new ApplicationContextConfiguration() {
+
+            @Override
+            List<String> getEnvironments() {
+                if (configuredEnvironment != null) {
+                    return configuredEnvironment.getActiveProfiles().toList()
+                } else {
+                    return Collections.emptyList()
+                }
+            }
+
+            @Override
+            Optional<Boolean> getDeduceEnvironments() {
+                return Optional.of(false)
+            }
+
+            @Override
+            ClassLoader getClassLoader() {
+                return applicationClassLoader
+            }
+        }
+
+        List beanExcludes = []
+        beanExcludes.add(ConversionService.class)
+        beanExcludes.add(Environment.class)
+        beanExcludes.add(PropertyResolver.class)
+        beanExcludes.add(ConfigurableEnvironment.class)
+        def objectMapper = ClassUtils.forName('com.fasterxml.jackson.databind.ObjectMapper', applicationClassLoader).orElse(null)
+        if (objectMapper != null) {
+            beanExcludes.add(objectMapper)
+        }
+        def micronautContext = new DefaultApplicationContext(micronautConfiguration);
+        micronautContext
+                .environment
+                .addPropertySource('grails-config', [(MicronautBeanFactoryConfiguration.PREFIX + '.bean-excludes'): (Object) beanExcludes])
+        micronautContext.start()
+        ConfigurableApplicationContext parentContext = micronautContext.getBean(ConfigurableApplicationContext)
+        applicationContext.setParent(
+                parentContext
+        )
+        applicationContext.addApplicationListener(new MicronautShutdownListener(micronautContext))
+        log.info('Started Micronaut Parent Application Context in {}ms', System.currentTimeMillis() - now)
+    }
+}
diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautShutdownListener.groovy
similarity index 58%
copy from grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
copy to grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautShutdownListener.groovy
index 0524a40ab2..f7c71659fd 100644
--- a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
+++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/MicronautShutdownListener.groovy
@@ -16,17 +16,23 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
-package micronaut
-
-import grails.boot.GrailsApp
-import grails.boot.config.GrailsAutoConfiguration
+package org.apache.grails.micronaut
 
 import groovy.transform.CompileStatic
+import io.micronaut.context.ApplicationContext
+import org.springframework.context.ApplicationListener
+import org.springframework.context.event.ContextStoppedEvent
 
 @CompileStatic
-class Application extends GrailsAutoConfiguration {
-    static void main(String[] args) {
-        GrailsApp.run(Application, args)
+class MicronautShutdownListener implements ApplicationListener<ContextStoppedEvent> {
+    final ApplicationContext micronautApplicationContext
+
+    MicronautShutdownListener(ApplicationContext micronautApplicationContext) {
+        this.micronautApplicationContext = micronautApplicationContext
+    }
+
+    @Override
+    void onApplicationEvent(ContextStoppedEvent event) {
+        this.micronautApplicationContext.stop()
     }
 }
\ No newline at end of file
diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautGroovyPropertySourceLoader.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautGroovyPropertySourceLoader.groovy
new file mode 100644
index 0000000000..3a7ce891de
--- /dev/null
+++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautGroovyPropertySourceLoader.groovy
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.grails.micronaut
+
+import grails.plugins.GrailsPlugin
+import grails.util.Environment
+import grails.util.Metadata
+import groovy.transform.CompileStatic
+import io.micronaut.context.env.AbstractPropertySourceLoader
+import io.micronaut.context.env.MapPropertySource
+import io.micronaut.context.env.PropertySource
+import io.micronaut.context.exceptions.ConfigurationException
+import io.micronaut.core.io.ResourceLoader
+import org.grails.config.NavigableMap
+
+import java.util.stream.Stream
+
+/**
+ * Loads properties from a Groovy script.
+ *
+ * @author Puneet Behl
+ * @since 4.0.3
+ */
+@CompileStatic
+class MicronautGroovyPropertySourceLoader extends AbstractPropertySourceLoader {
+
+    @Override
+    int getOrder() {
+        return DEFAULT_POSITION + 1
+    }
+
+    @Override
+    protected void processInput(String name, InputStream input, Map<String, Object> finalMap) throws IOException {
+        def env = Environment.current.name
+        if (input.available()) {
+            ConfigSlurper configSlurper = env ? new ConfigSlurper(env) : new ConfigSlurper()
+            configSlurper.setBinding(
+                    userHome: System.getProperty('user.home'),
+                    appName: Metadata.getCurrent().getApplicationName(),
+                    appVersion: Metadata.getCurrent().getApplicationVersion())
+            try {
+                def configObject = configSlurper.parse(input.getText("UTF-8"))
+                final Map<String, Object> propertySource = new org.grails.config.NavigableMap()
+                propertySource.merge(configObject.flatten(), false)
+                finalMap.putAll(propertySource)
+                processEnvironmentSpecificProperties(finalMap, propertySource)
+            } catch (Throwable e) {
+                throw new ConfigurationException("Exception occurred reading configuration [" + name + "]: " + e.getMessage(), e)
+            }
+        }
+    }
+
+    @Override
+    protected Optional<InputStream> readInput(ResourceLoader resourceLoader, String fileName) {
+        Stream<URL> urls = resourceLoader.getResources(fileName)
+        Stream<URL> urlStream = urls.filter({url -> !url.getPath().contains("src/main/groovy")})
+        Optional<URL> config = urlStream.findFirst()
+        if (config.isPresent()) {
+            return config.flatMap( {url ->
+                try {
+                    return Optional.of(url.openStream())
+                } catch (IOException e) {
+                    throw new ConfigurationException("Exception occurred reading configuration [" + fileName + "]: " + e.getMessage(), e)
+                }
+            })
+        }
+        return Optional.empty()
+    }
+
+    @Override
+    Set<String> getExtensions() {
+        return Collections.singleton("groovy")
+    }
+
+    @Override
+    protected MapPropertySource createPropertySource(String name, Map<String, Object> map, int order, PropertySource.Origin origin) {
+        return super.createPropertySource("grails.$name", map, order, origin)
+    }
+
+    void processEnvironmentSpecificProperties(finalMap, Map<String, Object> propertySource) {
+        final String environmentName = Environment.current.name
+        if (environmentName != null) {
+            final String environmentPrefix = GrailsPlugin.ENVIRONMENTS + '.' +  environmentName + '.'
+            propertySource.keySet().stream()
+                    .filter(k -> k.startsWith(environmentPrefix))
+                    .forEach(propertyName -> { finalMap[propertyName.substring(environmentPrefix.length())] = propertySource.get(propertyName) })
+        }
+    }
+
+}
diff --git a/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautYamlPropertySourceLoader.groovy b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautYamlPropertySourceLoader.groovy
new file mode 100644
index 0000000000..9b51523959
--- /dev/null
+++ b/grails-micronaut/src/main/groovy/org/apache/grails/micronaut/config/MicronautYamlPropertySourceLoader.groovy
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.grails.core.cfg
+
+import grails.plugins.GrailsPlugin
+import grails.util.Environment
+import groovy.transform.CompileStatic
+import io.micronaut.context.env.MapPropertySource
+import io.micronaut.context.env.PropertySource
+import io.micronaut.context.env.yaml.YamlPropertySourceLoader
+
+/**
+ * Load properties from a YAML file. This class extends the Micronaut default implementation {@link io.micronaut.context.env.yaml.YamlPropertySourceLoader} where it adds support for Micronaut beans receive configuration from environments block.
+ *
+ * @author Puneet Behl
+ * @since 6.0.0
+ */
+@CompileStatic
+class MicronautYamlPropertySourceLoader extends YamlPropertySourceLoader {
+
+    @Override
+    int getOrder() {
+        return super.getOrder() + 1
+    }
+
+    @Override
+    protected MapPropertySource createPropertySource(String name, Map<String, Object> map, int order, PropertySource.Origin origin) {
+        return super.createPropertySource("grails.$name" as String, map, order, origin)
+    }
+
+    /**
+     * Only process environment specific entries as the other entries are already processed by Micronaut default {@link io.micronaut.context.env.yaml.YamlPropertySourceLoader}
+     *
+     * @param finalMap The map with all the properties processed
+     * @param map The map to process
+     * @param prefix The prefix for the keys
+     */
+    @Override
+    protected void processMap(Map<String, Object> finalMap, Map map, String prefix) {
+        final String env = Environment.current.name
+        if (env != null) {
+            final String grailsEnvironmentPrefix = GrailsPlugin.ENVIRONMENTS + '.' + env + '.'
+            ((Map<String, Object>) map).entrySet().stream()
+                    .filter(e -> e.key instanceof String && (((String) e.key).startsWith(GrailsPlugin.ENVIRONMENTS) || prefix.startsWith(GrailsPlugin.ENVIRONMENTS)))
+                    .forEach(e -> {
+                        Map.Entry entry = (Map.Entry) e
+                        String key = entry.getKey().toString()
+                        Object value = entry.getValue()
+                        if (value instanceof Map && !((Map) value).isEmpty()) {
+                            processMap(finalMap, (Map) value, prefix + key + '.')
+                        } else if ((prefix + key).startsWith(grailsEnvironmentPrefix)) {
+                            finalMap.put((prefix + key).substring(grailsEnvironmentPrefix.length()), value)
+                        }
+                    })
+        }
+    }
+}
diff --git a/grails-micronaut/src/main/resources/META-INF/services/io.micronaut.context.env.PropertySourceLoader b/grails-micronaut/src/main/resources/META-INF/services/io.micronaut.context.env.PropertySourceLoader
new file mode 100644
index 0000000000..bc6d38d45f
--- /dev/null
+++ b/grails-micronaut/src/main/resources/META-INF/services/io.micronaut.context.env.PropertySourceLoader
@@ -0,0 +1,20 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#
+org.grails.core.cfg.MicronautYamlPropertySourceLoader
+org.grails.core.cfg.MicronautGroovyPropertySourceLoader
\ No newline at end of file
diff --git a/grails-spring/src/main/groovy/org/grails/spring/GrailsApplicationContext.java b/grails-spring/src/main/groovy/org/grails/spring/GrailsApplicationContext.java
index 32563b2f7a..e338f3c3f8 100644
--- a/grails-spring/src/main/groovy/org/grails/spring/GrailsApplicationContext.java
+++ b/grails-spring/src/main/groovy/org/grails/spring/GrailsApplicationContext.java
@@ -71,7 +71,13 @@ public class GrailsApplicationContext extends GenericApplicationContext implemen
 
     @Override
     public boolean containsBeanDefinition(String beanName) {
-        return super.containsBeanDefinition(beanName);
+        if(super.containsBeanDefinition(beanName)) {
+            return true;
+        } else if (getParent() != null && "grailsApplication".equals(beanName)) {
+            return getParent().containsBeanDefinition(beanName);
+        } else {
+            return false;
+        }
     }
 
     public MetaClass getMetaClass() {
diff --git a/grails-test-examples/micronaut/build.gradle b/grails-test-examples/micronaut/build.gradle
index a9f9d22001..91760fc76f 100644
--- a/grails-test-examples/micronaut/build.gradle
+++ b/grails-test-examples/micronaut/build.gradle
@@ -28,22 +28,15 @@ apply plugin:'cloud.wondrify.asset-pipeline'
 // for production does not fail during build task.
 apply plugin: 'org.apache.grails.gradle.grails-gsp'
 
-configurations {
-    developmentOnly
-    runtimeClasspath {
-        extendsFrom developmentOnly
-    }
-}
-
 dependencies {
     implementation platform(project(':grails-bom'))
 
-    developmentOnly('org.springframework.boot:spring-boot-devtools')
     implementation 'org.springframework.boot:spring-boot-starter-logging'
     implementation 'org.springframework.boot:spring-boot-autoconfigure'
     implementation 'org.apache.grails:grails-core'
     implementation 'org.springframework.boot:spring-boot-starter-actuator'
     implementation 'org.springframework.boot:spring-boot-starter-tomcat'
+    implementation 'org.apache.grails:grails-micronaut'
     implementation 'org.apache.grails:grails-web-boot'
     if(System.getenv('SITEMESH3_TESTING_ENABLED') == 'true') {
         implementation 'org.apache.grails:grails-sitemesh3'
@@ -64,17 +57,17 @@ dependencies {
     implementation 'org.apache.grails:grails-events'
     implementation 'org.apache.grails:grails-data-hibernate5'
     implementation 'org.apache.grails:grails-gsp'
-    compileOnly 'io.micronaut:micronaut-inject-groovy'
+    compileOnly "io.micronaut:micronaut-inject-groovy:$micronautVersion"
 
     testAndDevelopmentOnly platform(project(':grails-bom'))
     testAndDevelopmentOnly 'org.webjars.npm:bootstrap'
     testAndDevelopmentOnly 'org.webjars.npm:jquery'
+    testAndDevelopmentOnly "io.micronaut:micronaut-inject-groovy:$micronautVersion"
 
     console 'org.apache.grails:grails-console'
     profile 'org.apache.grails.profiles:web'
     runtimeOnly 'com.h2database:h2'
     runtimeOnly 'org.apache.tomcat:tomcat-jdbc'
-    runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api'
     runtimeOnly 'cloud.wondrify:asset-pipeline-grails'
     testImplementation 'org.apache.grails:grails-testing-support-datamapping'
     testImplementation 'org.mockito:mockito-core'
@@ -83,21 +76,16 @@ dependencies {
     integrationTestImplementation testFixtures('org.apache.grails:grails-geb')
 }
 
-bootRun {
-    jvmArgs(
-        '-Dspring.output.ansi.enabled=always', 
-        '-noverify', 
-        '-XX:TieredStopAtLevel=1',
-        '-Xmx1024m')
-    sourceResources sourceSets.main
-    String springProfilesActive = 'spring.profiles.active'
-    systemProperty springProfilesActive, System.getProperty(springProfilesActive)
-}
-
-tasks.named('assetCompile').configure {
-    // No need to compile assets in functional tests
-    enabled = false
-}
+//bootRun {
+//    jvmArgs(
+//        '-Dspring.output.ansi.enabled=always',
+//        '-noverify',
+//        '-XX:TieredStopAtLevel=1',
+//        '-Xmx1024m')
+//    sourceResources sourceSets.main
+//    String springProfilesActive = 'spring.profiles.active'
+//    systemProperty springProfilesActive, System.getProperty(springProfilesActive)
+//}
 
 apply {
     from rootProject.layout.projectDirectory.file('gradle/functional-test-config.gradle')
diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy b/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
index 0524a40ab2..8f1da48215 100644
--- a/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
+++ b/grails-test-examples/micronaut/grails-app/init/micronaut/Application.groovy
@@ -19,14 +19,17 @@
 
 package micronaut
 
+import grails.boot.ApplicationContextCustomizer
 import grails.boot.GrailsApp
 import grails.boot.config.GrailsAutoConfiguration
+import org.apache.grails.micronaut.MicronautParentContextAdder
 
 import groovy.transform.CompileStatic
 
 @CompileStatic
 class Application extends GrailsAutoConfiguration {
     static void main(String[] args) {
-        GrailsApp.run(Application, args)
+        def adder = new MicronautParentContextAdder()
+        GrailsApp.run([Application] as Class[], args, adder as ApplicationContextCustomizer)
     }
 }
\ No newline at end of file
diff --git a/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy
index 92f85ecbd7..0c494b2e89 100644
--- a/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy
+++ b/grails-test-examples/micronaut/grails-app/init/micronaut/BootStrap.groovy
@@ -19,6 +19,8 @@
 
 package micronaut
 
+import jakarta.servlet.ServletContext
+
 class BootStrap {
 
     ServletContext servletContext
diff --git a/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java b/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java
index 04916cf41e..83e1885c25 100644
--- a/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java
+++ b/grails-web-core/src/main/groovy/grails/web/servlet/context/GrailsWebApplicationContext.java
@@ -103,8 +103,18 @@ public class GrailsWebApplicationContext extends GrailsApplicationContext
     }
 
     private GrailsApplication getGrailsApplication() {
-        if (grailsApplication == null && containsBean(GrailsApplication.APPLICATION_ID)) {
-            grailsApplication = getBean(GrailsApplication.APPLICATION_ID, GrailsApplication.class);
+        if(grailsApplication==null) {
+            ApplicationContext parent = getParent();
+            if (parent != null) {
+                if(parent instanceof GrailsWebApplicationContext) {
+                    grailsApplication = ((GrailsWebApplicationContext)parent).getGrailsApplication();
+                } else if (parent.containsBean(GrailsApplication.APPLICATION_ID)) {
+                    grailsApplication = parent.getBean(GrailsApplication.APPLICATION_ID, GrailsApplication.class);
+                }
+            }
+            if (grailsApplication == null && containsBean(GrailsApplication.APPLICATION_ID)) {
+                grailsApplication = getBean(GrailsApplication.APPLICATION_ID, GrailsApplication.class);
+            }
         }
         return grailsApplication;
     }
diff --git a/settings.gradle b/settings.gradle
index fbca82c3a4..63cb1dbfbe 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -169,7 +169,9 @@ include(
         'grails-data-test-report',
 
         // wrapper
-        'grails-wrapper'
+        'grails-wrapper',
+
+        'grails-micronaut',
 )
 
 // Instead of using : to separate nested projects, fix the project directories by setting the projectDir explicitly
@@ -352,7 +354,7 @@ include(
         'grails-test-examples-issue-views-182',
         'grails-test-examples-issue-11102',
         'grails-test-examples-demo33',
-        // 'grails-test-examples-micronaut', // micronaut has been removed from Grails can be restored based on https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter
+        'grails-test-examples-micronaut', // micronaut has been removed from Grails can be restored based on https://micronaut-projects.github.io/micronaut-spring/latest/guide/#springBootStarter
         'grails-test-examples-plugins-loadfirst',
         'grails-test-examples-plugins-loadsecond',
         'grails-test-examples-plugins-loadafter',
@@ -380,7 +382,7 @@ project(':grails-test-examples-hyphenated').projectDir = file('grails-test-examp
 project(':grails-test-examples-issue-views-182').projectDir = file('grails-test-examples/issue-views-182')
 project(':grails-test-examples-issue-11102').projectDir = file('grails-test-examples/issue-11102')
 project(':grails-test-examples-demo33').projectDir = file('grails-test-examples/demo33')
-// project(':grails-test-examples-micronaut').projectDir = file('grails-test-examples/micronaut')
+project(':grails-test-examples-micronaut').projectDir = file('grails-test-examples/micronaut')
 project(':grails-test-examples-plugins-loadfirst').projectDir = file('grails-test-examples/plugins/loadfirst')
 project(':grails-test-examples-plugins-loadsecond').projectDir = file('grails-test-examples/plugins/loadsecond')
 project(':grails-test-examples-plugins-loadafter').projectDir = file('grails-test-examples/plugins/loadafter')