Goodbye Grails, Hello Micronaut #6: Domain Classes

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

This is the sixth 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.

Domain classes are usually the essential part of any Grails application, therefore the most difficult part to migrate. First of all, we need to migrate every database-related calls to use Data Services instead of any instance or static magic methods and properties.

We can very easily create the data service for the domain class Vehicle we were mentioning earlier:

This service was already used in the controller in the previous step.

Finding GORM Method using VCS

The most difficult part is to find all usages of the GORM instance and static API.

First, find all the usages of the given entity. The easiest way is to commit all your work to the VCS and let your IDE do the difficult part of finding references. Select one of your entities and move into a different package. I'm usually simply adding .legacy at the end of the current package name so for example, the Vehicle domain class will in hello package any longer but it will be located in hello.legacy.

Don't forget to move the data service as well.

Now visit the list of the VCS-changed files. The list should show all the classes referring to the specific domain class.

Then you need to replace all the instance and static GORM method calls in these files. For example, change Vehicle.get(id) to vehicleDataService.findById(id). You can either mock the vehicleDataService in your tests or you can use this article to use the real implementation against the test datastore:

Let's summarise the steps required for each domain class:

  1. Commit all your changes into VCS
  2. Move the domain class into a different package such as original.legacy
  3. Create a data service for the given domain or move the existing one into the same package
  4. Review all VCS-changed files
  5. Replace GORM methods with data service calls
  6. Back to step 1 unless you migrate all the domain classes

Finding GORM Methods at the Compile Time

Once you complete the steps above, there might still be some well-hidden calls to the GORM instance and static methods. You can use Groovy Code Check for GORM to find these statements:

compileOnly 'com.agorapulse:groovy-code-checks-gorm:0.9.0'

This library is very strict and it will create compilation failures wherever it finds any GORM-related method. This is very useful for indirect usages such as user.vehicle.save() where the GORM methods are not called directly on the entity object but a reference one.

Yet another set of compilation issues can be triggered by changing the convention.groovy Enterprise Groovy configuration file.

If you comment out or remove the checking extensions related to GORM then you should get compilation errors wherever you use any GORM magic.

Extracting Domain Classes into a Library

Let's extract the domain classes into the separate subproject to allow modularization of the other parts of the application. There is a dedicated article that can help you achieve this:

If you have applied Kordamp layout you simply create a new folder under libs such as hello-data containing hello-data.gradle build file.

You will also need to declare Grails Central repository in the root build.gradle file for all projects:

allprojects {
repositories {
mavenCentral()
maven { url 'https://repo.grails.org/grails/core/' }
}
}

And add two now properties into root gradle.properties file:

gorm.hibernate.version = 7.0.5
micronautVersion = 1.3.7

We will also need a fake Grails plugin descriptor in src/main/groovy directory:

Next, create folders grails-app/domains and grails-app/services within the new data library.

Then add the new library as a dependency of your Grails application in hello.gradle:

implementation project(':hello-data')

If you are using IntelliJ IDEA you should be able to simply move the packages containing the domain entities into the new library. Select the original package and select Refactor / Move Package or Directory … option from the top menu (default shortcut F6).

Then select Move directory … to another source root

And select grails-app/domain source folder as the destination:

Now revisit every domain in the new data library and add grails.gorm.annotation.Entity annotation.

Last but not least, move the related GORM data services into the grails-app/services folder so all the domain classes' related code is now within its own library.

Extracting Test Data into Library

As a next step, you should create another library that will hold the test data to ensure you can use them from everywhere.

Create a new folder hello-data-test-data containing a new build file hello-data-test-data.gradle.

Move the test data classes such as HelloDataSetsinto src/main/groovy.

Move the test data such as vehicle.json into src/main/resources.

Move the tests for the data sets such as HelloDataSetsSpec into src/test/groovy to keep the data sets properly tested.

Don't forget to add the dependency to the new test data library into your application's build file hello.gradle

testCompile project(':hello-data-test-data')

Having the domain classes extracted, we can also extract the services into a separate library in the next step.

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

--

--