Goodbye Grails, Hello Micronaut #7: Services

Vladimír Oraný
Stories by Agorapulse
3 min readAug 3, 2021

This is the seventh post in a series that will guide you through the migration from Grails to Micronaut. This guide requires your application to be based on Grails 4.x or later.

Within this series, we have already extracted the domain classes into a subproject. Now we can continue moving other services from the original Grails application. For a lack of good naming, let's call these simply -core libraries.

Let's create yet another directory hello-core within libs folder and add hello-core.gradle build file into it.

We will also have to move the dependencies from the original application. Once any extracted service cannot compile because of some missing dependencies, you need to move that one into hello-core.gradle.

From the Grails application project, you should be able to copy everything from

  • src/main/groovy
  • grails-app/services

directories into src/main/groovy of the new library.

Don't forget to add the new library as a dependency of the original application:

implementation project(':hello-core')

Micronaut beans prefer constructor injection instead of field-by-name injection in Grails.

Let's take a look at a simple Grails service here:

In this service, we are injecting VehicleDataService into VehicleService by name into a public property vehicleDataService. Naming is crucial for Grails.

We will move this class from hello/grails-app/services into hello-core/src/main/groovy.

Now, we need to convert it into Micronaut bean:

Micronaut declaration is more verbose but it's also more powerful. You need to annotate the class with javax.inject.Singleton annotation, declare the fields private final and initialize them in the constructor.

On the other hand, the name of the injected bean no longer matters and in general, the Micronaut dependency injection capabilities are more powerful than basic Grails one.

You need to update all the remaining injection points in the Grails application. This is similar to what we have done for the configuration objects. The only difference is the @Inject annotation before the field declaration.

Micronaut Grails Integration

As GORM is now called from Micronaut beans instead of Grails services and controllers, we need to let Micronaut know which packages should be scanned. Sadly, the default GrailsApp implementation does not propagate the packages into the Micronaut context but there is Micronaut Grails library for a rescue:

We need to add two more dependencies into the Grails application's build file hello.gradle:

implementation 'com.agorapulse:micronaut-grails:3.0.7'
implementation 'com.agorapulse:micronaut-grails-web-boot:3.0.7'

We also need to remove the following line

compile "org.grails:grails-web-boot"

Next, let's make some updates to the Application class which launches the application.

The class now extends MicronautGrailsAutoConfiguration and uses MicronautGrailsApp for running the application.

We will also have to update the tests. If we want to keep using the mocked data services then we need to create a factory which will create the mocks.

Then we can get the mock injected into the specification using Spring's Autowire and Grail's AutowiredTest. Spock's AutoAttach annotation guarantees that the mock will be correctly attached to the specification.

Grails Plugins and the Other Missing Parts

Even this step looks pretty simple, it is usually one of the most difficult tasks. of the migration process. Your services usually use some Grails plugins and you need to find their Micronaut counterparts. You can find inspiration in the Micronaut Documentation, Agorapulse OSS Hub, or Awesome Micronaut catalog:

In the next step, we will migrate the controllers themselves.

Table of Contents

  1. Multiproject
  2. Configuration
  3. Static Compilation
  4. Datasets
  5. Marshalling
  6. Domain Classes
  7. Services
  8. Controllers
  9. Micronaut Application
  10. Micronaut Data

Sources & Discussion

--

--