Spring Boot Audit Logging Example (2024)
In this tutorial, we'll look at how to set up Spring Boot JPA to automatically store auditing information for each entity, such as created by, created date, modified by, and modified date.
Spring Boot JPA Audit Logging Example
Spring Data helps you keep track of who created or modified an entity, as well as when it happened. To leverage this auditing functionality, you must provide auditing metadata to your entity classes, which can be defined using annotations or by implementing an interface.
Now create Spring Boot application from Spring Initializr.
Project Structure
Maven Dependency
Add spring-boot-starter-web
for RestController and
spring-boot-starter-data-jpa
for jpa starter.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.techgeeknext</groupId>
<artifactId>spring-boot-jp-auditing</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>spring-boot-jp-auditing</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Define Database Properties
We will use in memory h2 database.
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.url=jdbc:h2:mem:audittestdb
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
Spring JPA Auditing
There should be an entity class that corresponds to the database record table. It is preferable to maintain audit-related fields in a separate class, which can then be extended by entities that require audit information. Other entities can then use the super class as well.
So the Auditable
class that's marked as @MappedSuperclass
. There is no
separate table for a
mapped superclass. Its mapping data is applied to entities that inherit from it.
AuditingEntityListener
is an entity listener provided by Spring Data JPA that can be
used to trigger
the collection of auditing data. The AuditingEntityListener
class contains @PrePersist
and
@PreUpdate
annotations on callback methods that are triggered for the persist and
update events,
respectively.
The @EntityListeners
annotation can be used to activate the AuditingEntityListener
for each entity.
With the @EntityListeners
annotation, you can also define your own custom listener
class.
package com.techgeeknext.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
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;
import javax.persistence.Temporal;
import java.util.Date;
import static javax.persistence.TemporalType.TIMESTAMP;
@Data
@EqualsAndHashCode
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<T> {
@Column(name = "created_date", updatable = false)
@Temporal(TIMESTAMP)
@CreatedDate
protected Date creationDate;
@Column(name = "lastMod_date")
@LastModifiedDate
@Temporal(TIMESTAMP)
protected Date lastModifiedDate;
@CreatedBy
@Column(name="created_by")
protected T createdBy;
@LastModifiedBy
@Column(name="modified_by")
protected T modifiedBy;
}
@CreatedBy
: This field is used to record who created the entity.@LastModifiedBy
: Used to identify who last modified the entity.@CreatedDate
: To record the time when the entity was created.@LastModifiedDate
: Used to record when an entity was last modified.
Model Class
We can create User entity class and extends Auditable
class to record data about
creation and modification, which is then mapped to the appropriate columns.
package com.techgeeknext.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User extends Auditable<String> implements Serializable {
@Id
private int id;
private String name;
private String email;
}
Enable Jpa Auditing
To enable this feature, add the @EnableJpaAuditing
annotation to the top of the main class
(SpringBootJpaAuditingApplication)
, and you're done. Instead of writing boilerplate code in every
class to track/update time, simply extend the Auditable class
wherever you want to capture any
auditing information for any entity.
package com.techgeeknext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class SpringBootJpaAuditingApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaAuditingApplication.class, args);
}
}
Rest Controller
We will create the rest endpoints to test the audit log functionality.
package com.techgeeknext.controller;
import com.techgeeknext.model.User;
import com.techgeeknext.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/add/user")
public ResponseEntity<User> addUser(@RequestBody User user) {
return new ResponseEntity<>(userService.saveUser(user), HttpStatus.OK);
}
@GetMapping("/get/{userId}")
public ResponseEntity<User> getUserByUserId(@PathVariable(value = "userId") int userId) {
return new ResponseEntity<>(userService.getUserByUserId(userId).get(), HttpStatus.OK);
}
}
Take a look at our suggested posts:
Test Audit Log
- Start the Spring Boot Application by running
spring-boot:run
or by running main class. - Use the Postman and provide User details to add the user using rest endpoint http://localhost:8080/add/user.
As you can see that
AuditingEntityListener
has generated the audit information.
Download Source Code
The full source code for this article can be found on below.Download it here - Spring Boot Audit Logging Example