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; | |
} |
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
Your can see the code of this project in GitHub