Skip to content

Commit

Permalink
Merge pull request #8 from agorapulse/fix/no-hibernate-session
Browse files Browse the repository at this point in the history
Fixed issue with Micronaut context reused in postprocessor
  • Loading branch information
musketyr committed Nov 30, 2020
2 parents 3b37fbf + f2726c7 commit 451144d
Show file tree
Hide file tree
Showing 17 changed files with 328 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import groovy.transform.CompileStatic
abstract class ManagerService {

abstract Manager get(Long id)
abstract Number count()
abstract Manager save(Manager manager)
abstract List<Manager> list()
abstract List<Manager> findAllByName(String name)

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import com.agorapulse.micronaut.grails.example.DirectlyInjected
import com.agorapulse.micronaut.grails.example.InjectedUsingBridge
import com.agorapulse.micronaut.grails.example.InjectedUsingBridgeWithDifferentName
import com.agorapulse.micronaut.grails.example.InjectedWithQualifier
import grails.compiler.GrailsCompileStatic
import grails.converters.JSON
import groovy.transform.CompileStatic

import javax.inject.Inject
import javax.inject.Named

@CompileStatic
@GrailsCompileStatic
class TestController {

// micronaut beans requires @Inject but can have any name
Expand Down Expand Up @@ -69,4 +69,11 @@ class TestController {
] as JSON)
}

def managers() {
render([
someDirectlyInjected: someDirectlyInjected?.managerCount,
injectedUsingBridge : injectedUsingBridge?.managerCount,
] as JSON)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,24 @@
*/
package micronaut.grails.example

import com.agorapulse.micronaut.grails.domain.Manager
import com.agorapulse.micronaut.grails.domain.ManagerService

class BootStrap {

ManagerService managerService

def init = { servletContext ->
try {
Manager.withTransaction {
if (managerService.count() == 0) {
managerService.save(new Manager(name: 'Superuser'))
}
}
} catch (Exception e) {
log.error("Error preloading Managers", e)
}

}
def destroy = {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2020 Vladimir Orany.
*
* Licensed 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 micronaut.grails.example

import com.agorapulse.micronaut.grails.domain.Manager
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType
import groovy.util.logging.Slf4j
import io.micronaut.context.ApplicationContextConfiguration
import io.micronaut.context.DefaultApplicationContext
import io.micronaut.context.env.DefaultEnvironment
import io.micronaut.context.env.Environment
import io.micronaut.core.reflect.ClassUtils
import io.micronaut.spring.context.factory.MicronautBeanFactoryConfiguration
import org.grails.core.util.BeanCreationProfilingPostProcessor
import org.springframework.beans.BeanUtils
import org.springframework.boot.Banner
import org.springframework.boot.WebApplicationType
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.core.convert.ConversionService
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.env.PropertyResolver
import org.springframework.core.io.ResourceLoader

import javax.annotation.Nonnull

class DefaultApplication extends GrailsAutoConfiguration {

static ConfigurableApplicationContext context

static void main(String[] args) {
context = CustomGrailsApp.run(DefaultApplication, args) { env ->
env.addPackage(Manager.package)
}
}

@Slf4j
static class CustomGrailsApp extends GrailsApp {

private final Closure<Environment> configureMicronautEnvironment

// copy pasted

/**
* Static helper that can be used to run a {@link GrailsApp} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link org.springframework.context.ApplicationContext}
*/
static ConfigurableApplicationContext run(
Class<?> source,
String[] args,
@ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment')
Closure<Environment> configureMicronautEnvironment
) {
return run([source] as Class[], args, configureMicronautEnvironment)
}


/**
* Static helper that can be used to run a {@link GrailsApp} from the
* 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)
* @return the running {@link org.springframework.context.ApplicationContext}
*/
static ConfigurableApplicationContext run(
Class<?>[] sources,
String[] args,
@ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment')
Closure<Environment> configureMicronautEnvironment
) {
CustomGrailsApp grailsApp = new CustomGrailsApp(configureMicronautEnvironment, sources)
grailsApp.bannerMode = Banner.Mode.OFF
return grailsApp.run(args)
}

CustomGrailsApp(@ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment') Closure<Environment> configureMicronautEnvironment, Class<?>... sources) {
super(sources)
this.configureMicronautEnvironment = configureMicronautEnvironment
}

CustomGrailsApp(ResourceLoader resourceLoader, @ClosureParams(value = SimpleType.class, options = 'io.micronaut.context.env.Environment') Closure<Environment> configureMicronautEnvironment, Class<?>... sources) {
super(resourceLoader, sources)
this.configureMicronautEnvironment = configureMicronautEnvironment
}


/**
* Strategy method used to create the {@link org.springframework.context.ApplicationContext}. By default this
* method will respect any explicitly set application context or application context
* class before falling back to a suitable default.
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
protected ConfigurableApplicationContext createSpringApplicationContext() {
Class<?> contextClass = null
try {
switch (this.webApplicationType) {
case WebApplicationType.SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS)
break
case WebApplicationType.REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS)
break
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS)
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex)
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass)
}

@Override
protected ConfigurableApplicationContext createApplicationContext() {
setAllowBeanDefinitionOverriding(true)
ConfigurableApplicationContext applicationContext = createSpringApplicationContext()
def now = System.currentTimeMillis()

ClassLoader applicationClassLoader = GrailsApp.classLoader
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(org.springframework.core.env.Environment.class)
beanExcludes.add(PropertyResolver.class)
beanExcludes.add(ConfigurableEnvironment.class)
def objectMapper = ClassUtils.forName("com.fasterxml.jackson.databind.ObjectMapper", classLoader).orElse(null)
if (objectMapper != null) {
beanExcludes.add(objectMapper)
}
def micronautContext = new DefaultApplicationContext(micronautConfiguration) {

@Override
protected DefaultEnvironment createEnvironment(@Nonnull ApplicationContextConfiguration configuration) {
return configureMicronautEnvironment.call(super.createEnvironment(configuration)) as DefaultEnvironment
}
}

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 ${System.currentTimeMillis() - now}ms")


if (enableBeanCreationProfiler) {
def processor = new BeanCreationProfilingPostProcessor()
applicationContext.getBeanFactory().addBeanPostProcessor(processor)
applicationContext.addApplicationListener(processor)
}
return applicationContext
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ config {
}
}

version "0.1"
group "micronaut.grails.example"

apply plugin:"eclipse"
apply plugin:"idea"
apply plugin:"war"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.agorapulse.micronaut.grails.example

import com.agorapulse.micronaut.grails.domain.ManagerService
import grails.gorm.transactions.ReadOnly
import groovy.transform.CompileStatic
import io.micronaut.context.ApplicationContext
import io.micronaut.context.annotation.Value
Expand Down Expand Up @@ -54,6 +55,11 @@ class DirectlyInjected {
return "DirectlyInjected"
}

@ReadOnly
Number getManagerCount() {
return managerService?.count()
}

ApplicationContext getMicronautContext() {
return micronautContext
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.agorapulse.micronaut.grails.example

import com.agorapulse.micronaut.grails.domain.ManagerService
import groovy.transform.CompileStatic
import io.micronaut.context.ApplicationContext
import io.micronaut.context.annotation.Value
Expand All @@ -28,24 +29,31 @@ import javax.inject.Singleton
@CompileStatic
class InjectedUsingBridge {

private final ManagerService managerService
private final ApplicationContext micronautContext
private final String valueWithMicronautPrefix
private final String valueWithoutPrefix
private final String ignoredvalue

InjectedUsingBridge(
ManagerService managerService,
ApplicationContext micronautContext,
@Nullable @Value('${micronaut.foo.bar}') String valueWithMicronautPrefix,
@Nullable @Value('${bar.foo}') String valueWithoutPrefix,
@Nullable @Value('${ex.foo.bar}') String ignoredvalue

) {
this.managerService = managerService
this.micronautContext = micronautContext
this.valueWithMicronautPrefix = valueWithMicronautPrefix
this.valueWithoutPrefix = valueWithoutPrefix
this.ignoredvalue = ignoredvalue
}

Number getManagerCount() {
return managerService?.count()
}

ApplicationContext getMicronautContext() {
return micronautContext
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,14 @@ abstract class AbstractApplicationSpec extends Specification {
}
}

void 'check managers are loaded and can be fetched'() {
expect:
gru.test {
get '/test/managers'
expect {
json 'managers.json'
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2020 Vladimir Orany.
*
* Licensed 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 micronaut.grails.example

class DefaultApplicationSpec extends AbstractApplicationSpec {

@Override
Class<?> getApplicationClass() {
return DefaultApplication
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"someDirectlyInjected": 1,
"injectedUsingBridge": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"someDirectlyInjected": 1,
"injectedUsingBridge": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"someDirectlyInjected": "micronaut.grails.example.DefaultApplication$CustomGrailsApp$2",
"injectedUsingBridge": "com.agorapulse.micronaut.grails.GrailsPropertyTranslatingApplicationContext"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"someDirectlyInjected": 1,
"injectedUsingBridge": 1
}

0 comments on commit 451144d

Please sign in to comment.