Enhancing the auditable interceptor

We can also specify types of audit messages. We can choose to intercept the request based on its type:

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Documented
annotation class Auditable(val value: Auditor.AuditType)

The AuditType is defined in the Auditor class. We have defined CREATE, READ, UPDATE, and DELETE as audit types in this case:

class Auditor {
fun audit(message: String) {
println(message)
}

enum class AuditType () {
CREATE, READ, UPDATE, DELETE
}
}

We might want to use the @Auditable annotation in cases where we need to perform an audit event based on the type of operation.

Let's say we are going to carry out an audit on the CREATE type:

@Stateless
class App {
@Inject
private lateinit var identityCreator: IdentityCreator
@Inject
private lateinit var identityRepository: IdentityRepository

@Auditable(Auditor.AuditType.CREATE)
fun createResource(inputData: InputData): Identity {
val person = identityCreator.createPerson(inputData)
identityRepository.store(person)
return person
}
}

Now, in the AuditInterceptor class, we can define the @Auditable interceptor binding annotation for any type. In this case, we will do this for CREATE:

@Interceptor
@Auditable(Auditor.AuditType.CREATE)
class AuditInterceptor {
@Inject
private lateinit var auditor: Auditor

@AroundInvoke
fun handle(context: InvocationContext) {
auditor.audit("message")
context.proceed()
}
}

The handle() function should always be invoked, once the @Auditable interceptor binding is annotated. We can also retrieve the @Auditable annotation from the context to get the value and do something with it. Let's say we want to use the value that comes from the annotation in the audit message that we process:

@Interceptor
@Auditable(Auditor.AuditType.CREATE)
class AuditInterceptor {
@Inject
private lateinit var auditor: Auditor

@Inject
private lateinit var auditProcessor: AuditProcessor

@AroundInvoke
fun handle(context: InvocationContext) {
auditor.audit("message")
auditProcessor
.processMessage(context.method.getAnnotation(Auditable::class.java).value)
context.proceed()
}
}

The AuditProcessor class defines a function that takes AuditType as argument and prints it to console. The code looks like:

class AuditProcessor {
fun processMessage(type: Auditor.AuditType) {
println("Audit message type$type")
}
}

 The interceptor binding can also be specified at the class:

@Stateless
@Auditable(Auditor.AuditType.CREATE)
class App {
@Inject
private lateinit var identityCreator: IdentityCreator
@Inject
private lateinit var identityRepository: IdentityRepository

fun createIdentity(inputData: InputData): Identity {
val person = identityCreator.createPerson(inputData)
identityRepository.store(person)
return person
}
}

In this way, we can retrieve the annotations of the invocation context that has been invoked by the binding of the interceptor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset