How to Write custom annotation in Micronaut

Introduction:

Micronaut, with its lightweight and reactive architecture, has become a popular choice for building microservices. While the framework offers a plethora of built-in annotations, there may be scenarios where you want to tailor the behavior of your application with custom annotations. In this blog post, we’ll delve into the exciting realm of crafting custom annotations in Micronaut.

Understanding Micronaut Annotations:

Micronaut’s annotations provide a powerful way to declare various aspects of your microservices, from dependency injection to HTTP routing. However, there are times when you need more fine-grained control or want to encapsulate certain behaviors within your codebase.

Crafting Your Custom Annotation:

Define Your Annotation:

Custom annotation can be declared in following ways.

import io.micronaut.aop.Around
import java.lang.annotation.Documented

@Documented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
@Around
annotation class NotNull

Let’s understand every line of the above code

  1. @Documented: This annotation, when applied to another annotation like @NotNull, ensures that when JavaDoc documentation is generated, this annotation will be included.
  2. @Retention(AnnotationRetention.RUNTIME): This annotation indicates the retention policy for @NotNull. In this case, it specifies that the @NotNull annotation should be retained at runtime. This is crucial for certain runtime processes, like reflection or annotation processing.
  3. @Target(AnnotationTarget.FUNCTION): This annotation specifies where the @NotNull annotation can be used. In this case, it is applicable only to function declarations (methods).
  4. @Around: This is a Micronaut-specific annotation. It is used in conjunction with Micronaut’s AOP system. When @Around is applied to an annotation, it means that the annotated annotation is an advice annotation. It is a marker for Micronaut to treat it as an advice that wraps around the annotated method.
  5. annotation class NotNull: This declares the NotNull annotation. It is a custom annotation that can be applied to functions (methods) in Micronaut applications. The presence of @Around indicates that this annotation is meant to be used in an AOP context.

Define Your Annotation Implementation

Now, you have to define the behaviour of your annotation. For the given example we will check if the method returns null or Not. Incase of Null an exceptions will be thrown.

@Singleton
@InterceptorBean(NotNull::class)
class NotNullInterceptor() : MethodInterceptor<Any, Any> {
    override fun intercept(context: MethodInvocationContext<Any, Any>?): Any? {
        var result: Any? = context?.proceed() ?: throw java.lang.Exception("Null value returned, kindly check")
        return result
    }
}

Explanation:

  1. @Singleton: This annotation is used to declare a class as a Singleton in the context of dependency injection. In Micronaut, a Singleton is a single instance of a class shared across the entire application.
  2. @InterceptorBean(NotNull::class):This annotation is specific to Micronaut AOP. Here we define the implementation belongs to NotNull class
  3. class NotNullInterceptor() : MethodInterceptor<Any, Any>: . It implements the MethodInterceptor interface provided by Micronaut. The MethodInterceptor interface allows you to define behavior that should be executed before or after method invocation.
  4. override fun intercept(context: MethodInvocationContext<Any, Any>?): Any?: This function is an override of the intercept method defined in the MethodInterceptor interface. It receives a MethodInvocationContext as a parameter, which contains information about the method being intercepted and its context.

Code: https://github.com/cw-bhanunadar/Micronaut-playground/pull/19/files

Result:

Related Post