MethodInterceptor Example
MethodInterceptor Example
import io.micronaut.aop.MethodInterceptor
import io.micronaut.aop.MethodInvocationContext
import io.micronaut.core.type.MutableArgumentValue
import javax.inject.Singleton
@Singleton
class NotNullInterceptor implements MethodInterceptor<Object, Object> { (1)
@Override
Object intercept(MethodInvocationContext<Object, Object> context) {
Optional<Map.Entry<String, MutableArgumentValue<?>>> nullParam = context.getParameters()
.entrySet()
.stream()
.filter({entry ->
MutableArgumentValue<?> argumentValue = entry.getValue()
return Objects.isNull(argumentValue.getValue())
})
.findFirst() (2)
if (nullParam.isPresent()) {
throw new IllegalArgumentException("Null parameter [" + nullParam.get().getKey() + "] not allowed") (3)
} else {
return context.proceed() (4)
}
}
}
MethodInterceptor Example
import io.micronaut.aop.MethodInterceptor
import io.micronaut.aop.MethodInvocationContext
import io.micronaut.core.type.MutableArgumentValue
import javax.inject.Singleton
import java.util.Objects
import java.util.Optional
@Singleton
class NotNullInterceptor : MethodInterceptor<Any, Any> { (1)
override fun intercept(context: MethodInvocationContext<Any, Any>): Any {
val nullParam = context.parameters
.entries
.stream()
.filter { entry ->
val argumentValue = entry.value
Objects.isNull(argumentValue.value)
}
return if (nullParam.isPresent) {
throw IllegalArgumentException("Null parameter [" + nullParam.get().key + "] not allowed") (3)
} else {
}
}
}
To put the new MethodInterceptor
to work the next step is to define an annotation that will trigger the MethodInterceptor
:
import io.micronaut.context.annotation.Type;
import io.micronaut.aop.Around;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Retention(RUNTIME) (1)
@Target({ElementType.TYPE, ElementType.METHOD}) (2)
@Around (3)
@Type(NotNullInterceptor.class) (4)
public @interface NotNull {
}
Around Advice Annotation Example
Around Advice Annotation Example
import io.micronaut.aop.Around
import io.micronaut.context.annotation.Type
import java.lang.annotation.Documented
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy.RUNTIME
@Documented
@Retention(RUNTIME) (1)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) (2)
@Around (3)
@Type(NotNullInterceptor::class) (4)
annotation class NotNull
With the interceptor and annotation implemented you can then simply apply the annotation to the target classes:
Around Advice Usage Example
@Singleton
public class NotNullExample {
@NotNull
void doWork(String taskName) {
System.out.println("Doing job: " + taskName);
}
}
@Singleton
class NotNullExample {
@NotNull
void doWork(String taskName) {
println("Doing job: " + taskName)
}
}
Around Advice Usage Example
Whenever the type NotNullExample
is injected into any class, a compile time generated proxy will instead be injected that decorates the appropriate method calls with the @NotNull
advice defined earlier. You can verify that the advice works by writing a test. The following test uses a JUnit ExpectedException
rule to verify the appropriate exception is thrown when an argument is null
:
Around Advice Test
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testNotNull() {
try (ApplicationContext applicationContext = ApplicationContext.run()) {
NotNullExample exampleBean = applicationContext.getBean(NotNullExample.class);
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Null parameter [taskName] not allowed");
exampleBean.doWork(null);
}
}
Around Advice Test
void "test not null"() {
when:
ApplicationContext applicationContext = ApplicationContext.run()
NotNullExample exampleBean = applicationContext.getBean(NotNullExample.class)
exampleBean.doWork(null)
then:
IllegalArgumentException ex = thrown()
ex.message == 'Null parameter [taskName] not allowed'
cleanup:
applicationContext.close()
}
@Test
fun testNotNull() {
val applicationContext = ApplicationContext.run()
val exampleBean = applicationContext.getBean(NotNullExample::class.java)
val exception = shouldThrow<IllegalArgumentException> {
exampleBean.doWork(null)
}
exception.message shouldBe "Null parameter [taskName] not allowed"
applicationContext.close()
}