I have a Spring Data JPA project where the Bytecode Enhancement has been activated in the pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>5.6.14.Final</version>
<executions>
<execution>
<configuration>
<failOnError>true</failOnError>
<enableLazyInitialization>true</enableLazyInitialization>
<enableDirtyTracking>true</enableDirtyTracking>
</configuration>
<goals>
<goal>**enhance**</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
On top of that, I have also setup the Spring Audit mecanism. In order to do that, I have an abstract objet called Auditable
:
@Getter
@Setter
@MappedSuperclass
@EntityListeners({AuditingEntityListener.class})
public abstract class Auditable {
@CreatedBy
@Column(name = "created_by", length = 255, updatable = false)
protected String createdBy;
@CreatedDate
@Column(
name = "created_date",
columnDefinition = "timestamp default '2021-06-10 20:47:05.967394'",
updatable = false)
@Temporal(TemporalType.TIMESTAMP)
protected Date createdDate;
@LastModifiedBy
@Column(name = "modified_by", length = 255)
protected String modifiedBy;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(
name = "modified_date",
columnDefinition = "timestamp default '2021-06-10 20:47:05.967394'")
protected Date modifiedDate;
}
I have also a class that extends the Auditable
object:
@Entity
@Table(name = "dashboard")
@NamedQuery(name = "Dashboard.findAll", query = "SELECT d FROM Dashboard d")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Data
public class Dashboard extends Auditable implements Serializable {
...
}
Now, in order to activate the Audit mecanism in my project, I have a class AuditorAwareImpl
public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
var auth = SecurityContextHolder.getContext().getAuthentication();
var retVal = Optional.of("");
if (auth instanceof AnonymousAuthenticationToken) {
retVal = retVal.of("anonymous");
} else if (auth instanceof OAuth2AuthenticationToken) {
retVal = retVal.of(((DefaultOidcUser) auth.getPrincipal()).getPreferredUsername());
} else {
retVal = retVal.of(((HydrowebUserDetails) auth.getPrincipal()).getName());
}
return retVal;
}
}
And a bean of that class loaded in a @Configuration
class:
@Bean
AuditorAware<String> auditorProvider() {
return new AuditorAwareImpl();
}
Now the problem is that I can see the created_by
and created_date
fields updated in the database when I create a new data into the Dashboard
table. On the other hand there is no way to make both fields modified_date
and modified_by
to be updated when I modify a dashboard entity (nothig is updated/reflected into the Dashboard table).
The exciting point is that if I get rid off the Bytecode Enhancement, then I can make it works properly. All fields are updated as it should be (when creating an entity create fields are updated and when I editing an entity, update fields are also updated properly)...
So it seems that the Bytecode Enhancement interfere in some way with the Audit mecanism, but only for the modifying (_by and _date) columns. With or without bytecode enhancement, the create fields (_by and _date) are alwayds updated.
Is there a way to properly configure and make both concepts work together (bytecode enhancement and spring JPA Auditing)?
Have you already enconter this problem and if it the case, did you find an elegant way to make it works properly.
Or it is simply a bug?
From that point, I have found a workaround
that works well when both concept are installed (bytecode enhancement and Auditing). We added the following method within the Auditable
class:
@PreUpdate
void preUpdate(){
var tempModifiedBy = this.modifiedBy;
this.setModifiedBy(null);
this.setModifiedBy(tempModifiedBy);
}
Doing this seems to "stimulate" the auditing mecanism (when updating an JPA entity). And then both fields are updated with success within the audited table (modified_by and modified_date).