Micronaut/GORM Services

After another long evening of trying to get Micronaut to work as expected out of the box I’m beginning to think that the developers really don’t want anyone to use GORM!

Yesterday I was trying to convert one of my Grails apps to Micronaut. Moving the domain classes to entities was easy. Here is my Route entity (with unnecessary elements removed):

@Entity
class Route implements GormEntity<Route> {

    String grade
    Colour colour
    Date firstSeen
    Date removed

    static belongsTo = [line:Line]

}

Next we want a service. The pattern in latest versions of Grails and Micronaut is to define the service as an interface and then, optionally, provide an (abstract) implementation. Perhaps this is an underlying Hibernate pattern, see https://gorm.grails.org/latest/hibernate/manual/index.html#dataServices. A simple service might look something like this:

@Service(Route)
interface RouteService {

    List<Route> list() {}
    
    Route get(Serializable id) {}

}

This seemingly empty file gives hints to GORM to provide two methods. The first returns a list of all Routes, the second the Route with the given ID. In the controller then we can then write:

@Controller("/routes")
class RouteController {

    @Inject RouteService service

    @Get("/")
    def index() {
        return service.list()
    }

    @Get("/{id}")
    def get(Serializable id) {
         return service.get(id)
    }

}

At this point I expected to be able to run the app and be able to get a list of routes, or a single route, in JSON format. Instead, I got this exception:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: 
could not initialize proxy [uk.co.channele.uclimb.domain.Colour#65] - no Session 
(through reference chain: java.util.ArrayList[0]->
uk.co.channele.uclimb.domain.Route["colour"]->
uk.co.channele.uclimb.domain.Colour$HibernateProxy$y3jqGOWU["name"])

So my evening of searching the interwebs began. Coming from a Grails background I tried creating a service with actual methods, but this didn’t work. (Also, I found that replacing @Inject with @Autowired didn’t work.)

I found various Jackson annotations that allowed me to exclude the colour field but excluding line wasn’t obvious. I found some stuff about making fetches “eager” and about marking items as transient, but none of these helped.

Finally I did find a solution and that was to add in a dependency so that Jackson with work with Hibernate:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.10.2'

Why was this so difficult to find? Did I do something wrong when creating the application, there are lots of features available? I’d used the command:

mn create-app --features=hibernate-gorm,jdbc-hikari --lang=groovy uk.co.channele.uclimb

So I think it’s reasonable that I expected the application to render entities to JSON. Who knows?? As always, I hope that others might find this post useful.