001 /*
002 * SPDX-License-Identifier: Apache-2.0
003 *
004 * Copyright 2020 Vladimir Orany.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package micronaut.grails.example
019
020 import com.agorapulse.micronaut.grails.MicronautGrailsApp
021 import com.agorapulse.micronaut.grails.domain.Manager
022 import grails.boot.GrailsApp
023 import grails.boot.config.GrailsAutoConfiguration
024 import groovy.transform.stc.ClosureParams
025 import groovy.transform.stc.SimpleType
026 import groovy.util.logging.Slf4j
027 import io.micronaut.context.ApplicationContextConfiguration
028 import io.micronaut.context.DefaultApplicationContext
029 import io.micronaut.context.env.DefaultEnvironment
030 import io.micronaut.context.env.Environment
031 import io.micronaut.core.reflect.ClassUtils
032 import io.micronaut.spring.context.factory.MicronautBeanFactoryConfiguration
033 import org.grails.core.util.BeanCreationProfilingPostProcessor
034 import org.springframework.beans.BeanUtils
035 import org.springframework.boot.Banner
036 import org.springframework.boot.WebApplicationType
037 import org.springframework.context.ConfigurableApplicationContext
038 import org.springframework.core.convert.ConversionService
039 import org.springframework.core.env.ConfigurableEnvironment
040 import org.springframework.core.env.PropertyResolver
041 import org.springframework.core.io.ResourceLoader
042
043 class DefaultApplication extends GrailsAutoConfiguration {
044
045 static ConfigurableApplicationContext context
046
047 static void main(String[] args) {
048 context = CustomGrailsApp.run(DefaultApplication, args) { env ->
049 env.addPackage(Manager.package)
050 }
051 }
052
053 @Slf4j
054 static class CustomGrailsApp extends GrailsApp {
055
056 private final Closure<Environment> configureMicronautEnvironment
057
058 // copy pasted
059
060 /**
061 * Static helper that can be used to run a {@link GrailsApp} from the
062 * specified source using default settings.
063 * @param source the source to load
064 * @param args the application arguments (usually passed from a Java main method)
065 * @return the running {@link org.springframework.context.ApplicationContext}
066 */
067 static ConfigurableApplicationContext run(
068 Class<?> source,
069 String[] args,
070 @ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment')
071 Closure<Environment> configureMicronautEnvironment
072 ) {
073 return run([source] as Class[], args, configureMicronautEnvironment)
074 }
075
076
077 /**
078 * Static helper that can be used to run a {@link GrailsApp} from the
079 * specified sources using default settings and user supplied arguments.
080 * @param sources the sources to load
081 * @param args the application arguments (usually passed from a Java main method)
082 * @return the running {@link org.springframework.context.ApplicationContext}
083 */
084 static ConfigurableApplicationContext run(
085 Class<?>[] sources,
086 String[] args,
087 @ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment')
088 Closure<Environment> configureMicronautEnvironment
089 ) {
090 CustomGrailsApp grailsApp = new CustomGrailsApp(configureMicronautEnvironment, sources)
091 grailsApp.bannerMode = Banner.Mode.OFF
092 return grailsApp.run(args)
093 }
094
095 CustomGrailsApp(@ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment') Closure<Environment> configureMicronautEnvironment, Class<?>... sources) {
096 super(sources)
097 this.configureMicronautEnvironment = configureMicronautEnvironment
098 }
099
100 CustomGrailsApp(ResourceLoader resourceLoader, @ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment') Closure<Environment> configureMicronautEnvironment, Class<?>... sources) {
101 super(resourceLoader, sources)
102 this.configureMicronautEnvironment = configureMicronautEnvironment
103 }
104
105
106 /**
107 * Strategy method used to create the {@link org.springframework.context.ApplicationContext}. By default this
108 * method will respect any explicitly set application context or application context
109 * class before falling back to a suitable default.
110 * @return the application context (not yet refreshed)
111 * @see #setApplicationContextClass(Class)
112 */
113 protected ConfigurableApplicationContext createSpringApplicationContext() {
114 Class<?> contextClass = null
115 try {
116 switch (this.webApplicationType) {
117 case WebApplicationType.SERVLET:
118 contextClass = Class.forName(MicronautGrailsApp.DEFAULT_SERVLET_WEB_CONTEXT_CLASS)
119 break
120 case WebApplicationType.REACTIVE:
121 contextClass = Class.forName(MicronautGrailsApp.DEFAULT_REACTIVE_WEB_CONTEXT_CLASS)
122 break
123 default:
124 contextClass = Class.forName(MicronautGrailsApp.DEFAULT_CONTEXT_CLASS)
125 }
126 }
127 catch (ClassNotFoundException ex) {
128 throw new IllegalStateException(
129 "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
130 ex)
131 }
132 return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass)
133 }
134
135 @Override
136 protected ConfigurableApplicationContext createApplicationContext() {
137 setAllowBeanDefinitionOverriding(true)
138 ConfigurableApplicationContext applicationContext = createSpringApplicationContext()
139 def now = System.currentTimeMillis()
140
141 ClassLoader applicationClassLoader = GrailsApp.classLoader
142 ApplicationContextConfiguration micronautConfiguration = new ApplicationContextConfiguration() {
143 @Override
144 List<String> getEnvironments() {
145 if (configuredEnvironment != null) {
146 return configuredEnvironment.getActiveProfiles().toList()
147 } else {
148 return Collections.emptyList()
149 }
150 }
151
152 @Override
153 Optional<Boolean> getDeduceEnvironments() {
154 return Optional.of(false)
155 }
156
157 @Override
158 ClassLoader getClassLoader() {
159 return applicationClassLoader
160 }
161 }
162
163 List beanExcludes = []
164 beanExcludes.add(ConversionService.class)
165 beanExcludes.add(org.springframework.core.env.Environment.class)
166 beanExcludes.add(PropertyResolver.class)
167 beanExcludes.add(ConfigurableEnvironment.class)
168 def objectMapper = ClassUtils.forName("com.fasterxml.jackson.databind.ObjectMapper", classLoader).orElse(null)
169 if (objectMapper != null) {
170 beanExcludes.add(objectMapper)
171 }
172 def micronautContext = new DefaultApplicationContext(micronautConfiguration) {
173
174 @Override
175 protected DefaultEnvironment createEnvironment(ApplicationContextConfiguration configuration) {
176 return configureMicronautEnvironment.call(super.createEnvironment(configuration)) as DefaultEnvironment
177 }
178 }
179
180 micronautContext
181 .environment
182 .addPropertySource("grails-config", [(MicronautBeanFactoryConfiguration.PREFIX + ".bean-excludes"): (Object) beanExcludes])
183 micronautContext.start()
184
185 ConfigurableApplicationContext parentContext = micronautContext.getBean(ConfigurableApplicationContext)
186 applicationContext.setParent(
187 parentContext
188 )
189 applicationContext.addApplicationListener(new MicronautShutdownListener(micronautContext))
190 log.info("Started Micronaut Parent Application Context in ${System.currentTimeMillis() - now}ms")
191
192
193 if (enableBeanCreationProfiler) {
194 def processor = new BeanCreationProfilingPostProcessor()
195 applicationContext.getBeanFactory().addBeanPostProcessor(processor)
196 applicationContext.addApplicationListener(processor)
197 }
198 return applicationContext
199 }
200 }
201
202 }
|