Moving from Grails to Spring Boot part 2: Spring Boot controllers

Thomas Martin
WhozApp
Published in
3 min readOct 21, 2022

After having migrated our Grails services to vanilla Spring Boot, let’s see some tips for migrating a Grails controller to a vanilla Spring Boot one.

Photo by Douglas Lopes on Unsplash

Define interfaces

The first step is to define interfaces on top of controllers. It’s a simple tip, but it will ensure our new controller is consistent with the former one. For example, if we have this controller

We define that interface

and make the Grails controller implement it.

Two things that stand out here. The @CompileStatic annotation that will fail at compile time if the interface is not fully implemented. And the return statement after the render one, which is necessary to comply with the return type defined in the interface because render returns void . However, it is still the render statement that will be returned by Grails to the client.

With this preliminary work, consistency with previous endpoint exposure is ensured when we implement our Spring Boot controller.

Unfortunately, it won’t cover path variables and query parameters. Let’s take this example with a POST, a GET with a query parameter, and a PUT with a path variable.

Here the list()signature has no parameter, and the update() signature has the body but not the path variable. In Grails, those are usually accessed through the params map. In Spring Boot, those would be in the signature, annotated by @RequestParam or @PathVariable. In that configuration, endpoints with path variables or query parameters cannot implement the same interface between Grails and Spring Boot controller.

Thankfully, declaring path variables and query parameters in controller methods’ signatures is possible since Grails 2, just name the argument the same as the query parameter or the same as the path variable defined in the UrlMappings file, and Grails will do the trick.

Going back to our example, to prepare your migration, you would define the following interface

and modify your Grails controller that way:

Change payload validation to javax.validation

Classes representing payloads are constrained with static declarations in Grails, exactly like GORM entities.

This must be changed to usejavax.validation annotations, and you’ll need to annotate your Spring Boot controller with @Validated and your request body parameter with @Valid.

I strongly recommend having automated tests that check validation errors before migrating, ensuring you have kept the same constraints.

Serialize with Jackson

Finally, assuming you’re using JSON data format, you’ll need to use Jackson instead of Grails to serialize and deserialize payloads.

If you have custom bindings (i.e classes implementing theValueConverter interface of Grails), you’ll need to change them to classes extending JsonDeserializer (or use an already available configuration, for instance, we had custom Grails bindings for Instant that became unnecessary with the JavaTimeModule of Jackson).

If you use the Grails rendering feature with gson files into the views directory, you’ll throw this away and just return objects that will be serialized by Spring thanks to Jackson.

If you would want to take smaller steps (Kaizen !), you could start using Jackson in your Grails controller. In the PersonController, you would keep the render but you would get rid of gson views and would just pass it a string serialized with Jackson.

Notice that you’ll need to set the contentType in the render method since Grails will only get a string and won’t be able to determine that the data type is JSON.

When you’re done with all steps, you’ll get this fancy vanilla Spring Boot controller.

Now that the controller is based on vanilla Spring Boot, the signature List<PersonOutput> list(String personIds) can be modified to List<PersonOutput> list(List<String> personIds) and the split statement can be dropped.

That’s it for our second part on migrating from Grails to vanilla Spring Boot, nothing revolutionary here but those reminders could be useful if you’re migrating too. The third and last part will be about migrating from GORM to Spring Data.

--

--