samedi 14 septembre 2019

How to change the entity field before saving by using AspectJ?

I have some entities that implement the Auditable interface:

public interface Auditable {
    Audit getAudit();
    void setAudit(Audit audit);
}

Audit encapsulates some common information such as date of creation, date of updating, etc. For example, the document entity:

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "document")
public class Document implements Auditable {

    @Embedded
    private Audit audit;

    // SKIPPED

}

I want to use AspectJ to set Audit before saving the Document entity. I do it by this way:

@Aspect
@Component
public class AuditSetterAspect {

    private final String DEFAULT_USER_NAME = "admin";

    @Autowired
    private UserService userService;

    @Pointcut("execution(* whitepappers.dao.repositories.*.save(*))")
    public void savePointcut() { }

    @SneakyThrows
    @Around("savePointcut()")
    public Object addCommonData(final ProceedingJoinPoint proceedingJoinPoint) {
        final int affectedEntityIndex = 0;
        String userName = DEFAULT_USER_NAME;
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (nonNull(auth)) {
            Object obj = auth.getPrincipal();
            if (obj instanceof UserDetails) {
                userName = ((UserDetails)obj).getUsername();
            }
        }

        User currentUser = userService.findByLogin(userName);

        Object[] affectedEntities = proceedingJoinPoint.getArgs();
        if (Auditable.class.isAssignableFrom(
                affectedEntities[affectedEntityIndex].getClass())) {
            Auditable entity = (Auditable) affectedEntities[affectedEntityIndex];
            Audit audit = ofNullable(entity.getAudit()).orElse(new Audit());

            if (isUpdateAction(audit)) {
                audit.setDateUpdate(now());
                audit.setUserUpdate(currentUser);
            } else {
                audit.setUserCreate(currentUser);
                audit.setDateCreate(now());
            }
            entity.setAudit(audit);
        }

        return proceedingJoinPoint.proceed(affectedEntities);
    }

    private boolean isUpdateAction(Audit audit) {
        return !isNull(audit.getUserCreate());
    }
}

When I create a Document entity, the audit is set correctly. But when I update an entity, the audit doesn't change. Here I always get a new audit object:

Audit audit = ofNullable(entity.getAudit()).orElse(new Audit());

How can I get an existing audit object from a previously created entity for further updating?

I would be very grateful for the information.

Thanks to all.





Aucun commentaire:

Enregistrer un commentaire