About Audit

 Audit is a very popular feature, and every company I worked with implementing auditing in a different way. Other than JPA audit and using PLSQL trigger, I have done an audit event service which reading message from Message Queue and persist into DB, and also implement @Auditable using spring AOP. My current company prefers to use spring event to achieve the same goal, it's similar to the event service I built.

@Getter
@Setter
@ToString
@EqualsAndHashCode
public class AuditEvent extends ApplicationEvent{
private AuditType auditType;
private BaseEntity entity;
private String oldValue;
private String newValue;
private String moduleId;
private String sourceIp;
private String dataName;
}

@Component
@RequiredArgsConstructor
public class AuditPublisher{
final ApplicationEventPublisher publisher;

public void publishAudit(AuditEvent auditEvent) {
publisher.publishEvent(auditEvent);
}
}

@Service
public class SomeService{
private final AuditPublisher auditPublisher;

public void createSomething(){
AuditEvent auditEvent = new AuditEvent();
auditPublisher.publishAudit(auditEvent);
}
}

@Component
public class AuditListener implements ApplicationListener<AuditEvent> {
final AuditTrailRepository auditTrailRepository;

public void onApplicationEvent(AuditEvent auditEvent) {
AuditTrail auditTrail = AuditTrail.builder().build();

BeanUtils.copyProperties(auditEvent, auditTrail);
auditTrail.setCreatedBy(AuditContext.getCurrentUser);
auditTrailRepository.save(auditTrail);
}
}

@Component
public class AuditInterceptor implements WebRequestInterceptor {
public void preHandle(WebRequest request) {
String username = null;
if (request.getHeader("User") != null) {
username = request.getHeader("User");
}
AuditContext.setCurrentUser(username);
}

public void postHandle(WebRequest request, ModelMap modelMap) {
AuditContext.clear();
}
}

public final class AuditContext {
private static final InheritableThreadLocal<String> CURRENT_USER = new InheritableThreadLocal<>();
private AuditContext() {

}

public static void setCurrentUser(String username) {
CURRENT_USER.set(username);
}

public static String getCurrentUser(){
return CURRENT_USER.get();
}

public static void clear(){
CURRENT_USER.remove();
}
}

Comments