Image for post
Image for post

GitHub Actions are a great tool for automation. I'm currently creating workflows to manage changelog for a BOM file based on releases of included. On the library side, I was sending a releasepayload as a part of repository_dispatch action and then I wanted to add it to the changelog.

sed -i "2 a### $description\n\n$release_body\n" CHANGELOG.md

The problem was how to populate the request_body variable. The obvious option would be to extract the value from the event using ${{ ... }} notation. …


One of our Micronaut application started to fail to respond to the predefined route. We were getting one of the well-known errors which signalise that there's and CORS issue:

Access to XMLHttpRequest at 'https://backend.local:9997/upload' from origin 'https://frontend.local:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Be sure you are using the latest version of Chrome because between versions 79 to 83 the CORS preflight requests were not visible by default. Once you identify the failing OPTIONS request then you can copy it as acURL command. …


Image for post
Image for post

Our architecture, originally built with Grails 3.3.x semi-monoliths, is currently leaning toward using more Micronaut functions in situations where it makes much more sense such as jobs, queue consumers or AWS DynamoDB triggers. The biggest obstacle seems to be a handful of GORM domain classes which spreads across Grails application and which blocks extracting logic into Micronaut functions. Let's take a look at how to share domain classes between Grails and Micronaut applications.

In theory, you can use GORM without Grails. Actually Micronaut comes with out-of-the-box support of GORM, so it seemed to be quite a simple task. Basically, you just copy & paste your domain class and add @Entity annotation. This works great for standalone applications and Micronaut but then you will have many difficulties including the domain classes into Grails. The only suitable way I have figured out is to let the library pretend to be a Grails plugin but without including unnecessary dependencies or using any Grails Gradle plugins. …


Image for post
Image for post

Micronaut is a very extensible framework which allows you to easily create new libraries. Generally speaking, you can create a set of beans which will be injected into your application and ship them as a separate JAR. The problem may arise when you are also using configurations and you want to preset some default values. There is one recommended way — use default values in the configuration class. If you for any reason can't use this approach I will show you two other approaches — each of them must be used with caution.

Setting Default Values in Configuration Object

Setting default values in the configuration class or interface is the recommended way. If you use plain classes then you can simply set the default value as a default value of the fields. …


Gradle is a great build tool which allows you to write versatile build code to achieve whatever you want. The biggest drawback for me is the velocity of the Gradle releases and the corresponding breaking changes. You may say that one major release a year is ok but I currently manage tens of small open-sourced projects for me build script is something I should barely be touched except adding dependencies and new subprojects. …


Image for post
Image for post

I have noticed that many great frameworks such as Spring Boot, Grails or Micronaut are using Maven bill-of-material (BOM) to manage versions of their dependencies aligned. Using BOM you can constraint the versions of transitive dependencies as well as it allows you to specify just the group and name of the module ane let the version be determined by BOM.

I wanted to bring the same smooth versions' management into our project so I've created a seed project to generate the BOM files easily. Although there is a java-platform Gradle plugin which is designed for generating BOM files I got inspired by the approach taken by Micronaut team and created a project which generated the BOM from a simple properties file and publishes it into GitHub Maven repository using GitHub Actions. …


Image for post
Image for post

If you are not familiar with Micronaut then you may not understand how important the upgrade to Grails 4 is. But if you already discovered the productivity of Micronaut then you know there is a whole new world of tools and best practises to take advantage of. Let’s start with mentioning some of the issues which may occur during the upgrade and then I will share some of the ways how to benefit from having Micronaut parent context.

Grails 4 Upgrade Gotchas

There are detailed upgrade notes for Grails and GORM which you should read first:


Image for post
Image for post

Micronaut has great out-of-box support for GraalVM. I've tried a simple task to create a Micronaut function to be handled by Amazon API Gateway which connects to Amazon RDS PostgreSQL. The following command generates the skeleton of the function handling API Gateway Proxy using GraalVM:

mn create-app graalvm-function --features aws-api-gateway-graal

See Custom GraalVM Native Runtimes for more information about API Gateway and GraalVM functions.

Next, we create a domain class, controller and repository using Micronaut Data JDBC. Feel free to copy from Pet Clinic example. How to use Micronaut Data JDBC goes beyond this post but there is one important part of the documentation which is Going Native with GraalVM. …


Image for post
Image for post

The controllers in any web framework should reduce their code to the bare minimum which only bridges web input and output into platform-independent business code. The problem arises when you have a code with different outcomes which you would like to represent with different HTTP status codes.

Typical examples are security and parameter checks like the following:

  • Is the endpoint authorized properly?
  • Are some of the parameters missing?
  • Does the referred item exist?

Following CommentController shows some of the problems. Usually, there is even more code between the method's points of return.

class CommentController {

def securityService
def commentService

def
updateComment(String id, String newText) {
if (!securityService.authorized(request)) {
respond status: HttpStatus.FORBIDDEN
return
}

if (!securityService.hasRole(request, 'EDITOR')) {
respond status: HttpStatus.UNAUTHORIZED
return
}

if (!id || !newText) {
respond status: HttpStatus.BAD_REQUEST
return
}

Comment comment = commentService.findById(id)

if (!comment) {
respond status: HttpStatus.NOT_FOUND
return
}

comment = commentService.updateComment(comment, …

Image for post
Image for post

Time to time I find a code with the uninitialized variable declaration before if-else or if-elseif-else statements where the variable is initialized inside the conditional blocks. See the typical example with the full name:

Original Method

Quite often the conditional blocks are even larger giving the developer even less chance to understand what will be the value of the variable after evaluation. There is a very simple solution to this situation which is moving the code inside a separate method:

Extracted Method to Get the Full Name

As we call all the methods on the Person object the method should actually belong to the Person

About

Vladimír Oraný

Full Stack Developer and Test Facilitator at @agorapulse

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store