in my app which is based on struts2, spring IoC and Transasctions, jpa, Hibernate i want to introduce an "audit log function" which will log all the important events, such as : a user has been created/updated, or a ticket was opened by somebody...
I want to keep this log in the database so for this i will have a DAO. I created also a service class for this purpose 'AuditLogService' which will have transactional behavior " propagation="REQUIRES_NEW" due to the fact that i want to log the event no matter if the logged event was successful or not.
The problem is that if i have something like this in my user service :
@Override
public boolean saveUser(UserDto userDto) {
User u = new User();
u.setFirstName(userDto.getFirstName());
u.setLastName(userDto.getLastName());
u.setUserName(userDto.getUserName());
u.setPassword(userDto.getPassword());
u.setIsLdapUser(userDto.getIsLdapUser());
u.setId(userDto.getId());
u.setAgentId(userDto.getAgentId());
Boolean eventStatus = true;
String event="";
try{
if (u.getId()!=null){
dao.update(u);
event = "UPDATE_USER";
}else{
dao.create(u);
event = "CREATE_USER";
}
}catch (Exception e) {
e.printStackTrace();
eventStatus = false;
return false;
}
finally {
AuditLogEvent ale = auditLogEventDao.getAuditLogEvent(event);
auditLogService.addAuditLogEvent(ale, eventStatus,u.toString());
}
return false;
}
the audit log method is executed before committing the save user method and reports that the event was true, but in fact the event was false.
Any idea how can i solve this ? or maybe this approach is not the best... ?
updates !
After Michael`s advices i have transformed my Service also into an Aspect@Aspect @Service class AuditLogAspectImpl implements AuditLogAspect { @Autowired private AuditLogDao dao; @Autowired private UserDao userDao; @Override @AfterReturning(pointcut = "execution(* xxx.yy.services..*.save*(..))", returning = "retVal") public boolean afterLogEvent(JoinPoint joinPoint,Object retVal){ }
}
and now i have my method signature like here. everything works ok, i can detect if a operation failed or was successful and i can log this into a log file, but if i want to log this into a table from database via a dao class, when the operations fail and the transaction is rolled back my audit entry is not inserted.
First i thought that this is happening because the both operations, the actual method that need to be audited and the audit event are running in the same transactional context, and if one of them is rolled back the entire transaction is, and i have created a new transaction for the aspect logging part. But this seems not to work.
Any ideea why ?