Home » Java » Enterprise Java » Auditing infrastructure for your app using Spring AOP, Custom annotations and Reflection

About Idan Fridman

Idan Fridman
Idan is Software engineer with experience in Server side technologies. Idan is responsible for various infrastructure models in the software industry(Telecommunications, Finance).

Auditing infrastructure for your app using Spring AOP, Custom annotations and Reflection

The next post will demonstrate how to write simple auditing using Spring AOP and annotations. The auditing mechanism will be clean, efficient and easy to maintain (and Kewwl!).

I will demonstrate my example on a User management system (I assume you have general knowledge on reflection and AOP).

We start with simple DB table to hold our auditing data:


We need to populate 4 main fields(Username, UserType, Action, TargetUser)

*Username – the user who performs the action

*TargetUser – Target user the action is performed.

Now let’s create new annotation to mark our wanna-be-audit method. We’re going to be very “creative” and use: @AuditAble

public @interface Auditable {
AuditingActionType actionType();

Annotated @AuditAble method example:

 @Auditable(actionType = AuditingActionType.INTERNAL_USER_REGISTRATION)
 public void createInternalUser(UserDTO userDTO) {


Our future Aspect (aop) will collect some auditing data from the method param’s using DTO’s. In our case the target username and the actionType will be collected as our auditing info.

For that I created another annotation AuditingTargetUsername:

@Target({ElementType.FIELD, ElementType.TYPE})
public @interface AuditingTargetUsername {
String value() default "";

So inside UserDTO we got:

public abstract class UserDTO implements Serializable {

 private String userName;



We annotated the userName with @AuditingTargetUsername. That information will be collected later on.

Now let’s create our AOP’s aspect. Here all the auditing logic is collected and performed (Intercepting @Auditable methods, Extracting information from annotations, Using repository to save the final auditing record):

public class AuditingAspect {


 public void logAuditActivity(JoinPoint jp, Auditable auditable) {
 String targetAuditingUser;
 String actionType = auditable.actionType().getDescription();

 String auditingUsername = Authentication auth = SecurityContextHolder.getContext().getAuthentication().getName()
 role = userService.getCurrentUser(false).getPermissionsList().toString();
 auditingUsernameIp = request.getRemoteAddr();
 "Auditing information. auditingUsername=" + auditingUsername + ", actionType=" + actionType + ", role=" + role + ", targetAuditingUser="
 + targetAuditingUser + " auditingUsernameIp=" + auditingUsernameIp
 .save(new AuditingEntity(auditingUsername, role, actionType, targetAuditingUser, auditingUsernameIp,
 new Timestamp(new java.util.Date().getTime())));

ill explains the main code areas:

Pointcut – all @Auditable.annotations
Advice – Type @After (We want to audit after the method is invoked)

ActionType value is retrieved via the annotated method’s declaration:

@Auditable(actionType = AuditingActionType.INTERNAL_USER_REGISTRATION)

auditingUsername is the current user who performs the action (in our case the logged in user). I retrieved that via SecurityContext(Spring Security).

Now we will extract the @targetAuditingUser field via reflection on runtime:

targetAuditingUser = extractTargetAuditingUser(jp.getArgs());

public String extractTargetAuditingUserFromAnnotation(Object obj) {
 result = getTargetAuditingUserViaAnnotation(obj);



Thats the logic to extract the annotated fields via reflection:

private String getTargetAuditingUserViaAnnotation(Object obj) {
class cl=obj.getClass()
 String result = null;
 try {
 for (Field f : cl.getDeclaredFields())
 for (Annotation a : f.getAnnotations()) {
 if (a.annotationType() == AuditingTargetUsername.class) {
 Field annotatedFieldName = cl.getDeclaredField(f.getName());
 String annotatedFieldVal = (String) annotatedFieldName.get(obj);
 logger.debug("Found auditing annotation. type=" + a.annotationType() + " value=" + annotatedFieldVal.toString());
 result = annotatedFieldVal;
 } catch (Exception e) {
 logger.error("Error extracting auditing annotations from obj" + obj.getClass());
 return result;

Result on DB:


That’s it. We’ve got clean auditing infrastructure all you need is to annotate your method with @Auditable and annotate inside your DTO’s/Entities the desired information to be audited.


Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!


1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design


and many more ....




  1. Thanks Idan. This is what I am looking for. Would appreciate if you can upload archive of the project.

  2. Sure I will upload this into my github and modify this post shorty. thanks.

  3. That would be very helpful. Looking forward to it.

  4. where i found the source code?

  5. Have a get a chance to upload source code?

  6. The log will not be saved in case if exception occurs in the Adviced method, How to overcome this?

Leave a Reply

Your email address will not be published. Required fields are marked *


Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.