We are slowly trying to introduce Micronaut into our code base and one of the first questions I asked myself was if there is any way how…


How to Create a Library Suitable for Grails with Micronaut

Configuration using GrailsMicronautBeanProcessor

We are slowly trying to introduce Micronaut into our code base and one of the first questions I asked myself was if there is any way how to share code between Micronaut microservices and Grails application.

To be more specific, the question is how to share bean definitions so the beans are automatically injected into both — Micronaut microservices and the Grails applications. There is an excellent blog post from Hubert Klein Ikkink (aka Mr. Haki) showing how to integrate Micronaut beans into Spring application but for Grails application, this is useless as Grails applications inject beans by names and Micronaut’s Spring integration uses fully qualified names of the type of the bean such as foo.bar.MyService for the name of the bean whereas Grails expects property name such as myService. Therefore beans injected using Micronaut’s Spring integration will never be found by Grails autowiring mechanism.

[Micronaut Mastery: Use Micronaut Beans In Spring Applications

mrhaki.blogspot.com

To workaround this problem we have created another Micronaut library which can be used to inject Micronaut beans into Grails’s application context.

[agorapulse/micronaut-libraries

github.com

New GrailsMicronautBeanProcessor works in a similar way as original MicronautBeanProcess with the focus of the names of the injected beans:

package com.example.mn4grails

@Configuration
class GrailsConfig {

    @Bean
GrailsMicronautBeanProcessor widgetProcessor() {  
    GrailsMicronautBeanProcessor  
        ._builder_()  
        .addByType(Widget)  
            .addByType('someInterface', SomeInterface)
            .addByStereotype('prototype', Prototype)
            .addByName('gadget')            .build()
    }

}

interface SomeInterface { }

@Singleton
class SomeImplementation implements SomeInterface { }

@Singleton
class Widget {}

@Singleton
@Requires(notEnv = 'test')
class TestWidget extends Widget { }


interface Minion {}

@Prototype
class PrototypeBean {

    final String redisHost
    final Integer redisPort
    final Integer redisTimeout    PrototypeBean(
        @Value('${redis.host}') String redisHost,
        @Value('${redis.port}') Integer redisPort,
        @Value('${redis.timeout:10000}') Integer redisTimeout
    ) {
        this.redisHost = redisHost
        this.redisPort = redisPort
        this.redisTimeout = redisTimeout
    }
}

@Singleton
@Named('gadget')
class SomeGadget { }

If the name can be easily guessed, you don’t have to specify it manually. You have to always narrow the micronaut bean qualification down to single bean otherwise the processor will throw an exception. @Primary annotation does not help here but using @Requires does.

Apart from guaranteeing the expected name [GrailsMicronautBeanProcessor](https://github.com/agorapulse/micronaut-libraries/blob/master/micronaut-grails/src/main/groovy/com/agorapulse/micronaut/grails/GrailsMicronautBeanProcessor.java) also helps with reusing existing properties. If your Grails application is already using for example Grails Redis plugin you may already have Redis properties such as grails.redis.host set in your configuration file. [GrailsMicronautBeanProcessor](https://github.com/agorapulse/micronaut-libraries/blob/master/micronaut-grails/src/main/groovy/com/agorapulse/micronaut/grails/GrailsMicronautBeanProcessor.java) and its companion [PropertyTranslatingCustomizer](https://github.com/agorapulse/micronaut-libraries/blob/master/micronaut-grails/src/main/groovy/com/agorapulse/micronaut/grails/PropertyTranslatingCustomizer.java) will automatically strip the grails. prefix for you.

The last step to allow Grails (and other Spring application) to automatically load the Micronaut beans based on the configuration provided above is to add following lines into file META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.mn4grails.GrailsConfig