Auditing tables with Spring Boot

Development

Posted by Neto Deolino on May 31, 2020

Why use Auditing?

Auditing provide informations that we can use for averiguate our data. This specific method of auditoring provide the anotations @CreatedBy, @CreatedDate, @LastModifiedDate and @LastModifiedBy. Attention: this informations is retrieved from the user authenticated with Spring Security.

package com.example.auditing.model;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class Auditing {
@CreatedDate
@Column(nullable = false, updatable = false)
private Long createdDate;
@LastModifiedDate
private Long modifiedDate;
@CreatedBy
@Column(nullable = false, updatable = false)
private String createdBy;
@LastModifiedBy
private String modifiedBy;
}
view raw auditing.java hosted with ❤ by GitHub

Settings

Auditing only need spring-boot-data-jpa dependency. So, let's go to configs:

package com.example.auditing.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@Configuration
@EnableJpaAuditing(auditorAwareRef="auditorProvider")
public class PersistenceConfig {
@Bean("auditorProvider")
AuditorAware<String> auditorProvider() {
return new AuditorAwareImpl();
}
}
package com.example.auditing.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.AuditorAware;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
public class AuditorAwareImpl implements AuditorAware<String> {
private static final String USER_AUDITOR = "USER";
private static final String UNDEFINED = "UNDEFINED";
@Autowired
private HttpServletRequest request;
@Value("${auditing.uri-user-auditor:}")
private String uriUserAuditor;
@Override
public Optional<String> getCurrentAuditor() {
String URI = this.request.getRequestURI();
if (URI.contains(uriUserAuditor)) {
return Optional.ofNullable(USER_AUDITOR);
}
return Optional.ofNullable(UNDEFINED);
// TODO: use this code for get username authenticated in your filter!
// return Optional.ofNullable(SecurityContextHolder.getContext())
// .map(e -> e.getAuthentication())
// .map(Authentication::getName);
}
}

For this example I didn't add Spring Security, so I commented the code that takes the username of the authenticated user and added the String UNDEFINED!

In the line 24 I also handle /user endpoints, which can be added without being authenticated!

Persisting data

Now, to test our auditing, persirt your object data with the method save of the spring-boot-data-jpa. See my code example!

package com.example.auditing.service;
import com.example.auditing.model.User;
import com.example.auditing.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Optional<User> login(User user) {
return this.userRepository.findByEmailAndPassword(user.getEmail(), user.getPassword());
}
public User save(User user) {
return this.userRepository.save(user);
}
public List<User> findAll() {
return this.userRepository.findAll();
}
}

User

Book

Your can see the code of this project in GitHub


Comentários: