Skip to content

Commit

Permalink
Merge pull request #11403 from j-be/hibernate-envers-store-data-at-de…
Browse files Browse the repository at this point in the history
…lete

Hibernate-Envers: Support store_data_at_delete
  • Loading branch information
Sanne authored Aug 27, 2020
2 parents a2351c3 + 64980d2 commit 7ab0f1e
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.hibernate.envers.HibernateEnversBuildTimeConfig;
import io.quarkus.hibernate.envers.HibernateEnversRecorder;

public final class QuarkusHibernateEnversProcessor {

Expand All @@ -22,4 +26,10 @@ public void registerEnversReflections(BuildProducer<ReflectiveClassBuildItem> re
new ReflectiveClassBuildItem(false, false, "org.hibernate.tuple.component.DynamicMapComponentTuplizer"));
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
public void applyConfig(HibernateEnversRecorder recorder,
HibernateEnversBuildTimeConfig buildTimeConfig) {
recorder.registerHibernateEnversIntegration(buildTimeConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.hibernate.orm.envers;

import static org.hamcrest.Matchers.is;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class EnversStoreDataAtDeleteTestCase {

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(MyAuditedEntity.class, MyRevisionEntity.class, MyRevisionListener.class,
EnversTestStoreDataAtDeleteResource.class)
.addAsResource("application-with-store-data-at-delete.properties", "application.properties"));

@Test
public void testStoreDataAtDelete() {
RestAssured.when().delete("/envers-store-data-at-delete").then()
.body(is("OK"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.quarkus.hibernate.orm.envers;

import java.util.List;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.resource.spi.IllegalStateException;
import javax.transaction.UserTransaction;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;

import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;

@Path("/envers-store-data-at-delete")
@ApplicationScoped
public class EnversTestStoreDataAtDeleteResource {
private static final String NAME = "deleted";

@Inject
EntityManager em;

@Inject
UserTransaction transaction;

@DELETE
public String delete() {
try {
transaction.begin();
MyAuditedEntity entity = new MyAuditedEntity();
entity.setName(NAME);
em.persist(entity);
transaction.commit();

transaction.begin();
em.remove(em.find(MyAuditedEntity.class, entity.getId()));
em.flush();
transaction.commit();

AuditReader auditReader = AuditReaderFactory.get(em);
List<Number> revisions = auditReader.getRevisions(MyAuditedEntity.class, entity.getId());
if (revisions.size() != 2) {
throw new IllegalStateException(String.format("found {} revisions", revisions.size()));
}

for (Number revision : revisions) {
System.out.println(revision);
MyAuditedEntity revEntity = auditReader.find(MyAuditedEntity.class, MyAuditedEntity.class.getName(),
entity.getId(), revision, true);
if (revEntity == null) {
throw new IllegalStateException("failed to find delete revision");
}
if (!NAME.equals(revEntity.getName())) {
throw new IllegalStateException("revision listener failed to persist data on delete");
}
}

return "OK";
} catch (Exception exception) {
return exception.getMessage();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:test

quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-envers.store-data-at-delete=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.hibernate.envers;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;

@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class HibernateEnversBuildTimeConfig {
/**
* Enable store_data_at_delete feature.
*/
@ConfigItem(defaultValue = "false")
public boolean storeDataAtDelete;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.hibernate.envers;

import java.util.function.BiConsumer;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.envers.configuration.EnversSettings;

import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationListener;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrations;
import io.quarkus.runtime.annotations.Recorder;

@Recorder
public class HibernateEnversRecorder {

public void registerHibernateEnversIntegration(HibernateEnversBuildTimeConfig buildTimeConfig) {
HibernateOrmIntegrations.registerListener(new HibernateEnversIntegrationListener(buildTimeConfig));
}

private static final class HibernateEnversIntegrationListener implements HibernateOrmIntegrationListener {

private HibernateEnversBuildTimeConfig buildTimeConfig;

private HibernateEnversIntegrationListener(HibernateEnversBuildTimeConfig buildTimeConfig) {
this.buildTimeConfig = buildTimeConfig;
}

@Override
public void contributeBootProperties(BiConsumer<String, Object> propertyCollector) {
addConfig(propertyCollector, EnversSettings.STORE_DATA_AT_DELETE, buildTimeConfig.storeDataAtDelete);
}

public static <T> void addConfig(BiConsumer<String, Object> propertyCollector, String configPath, T value) {
propertyCollector.accept(configPath, value);
}

@Override
public void onMetadataInitialized(Metadata metadata, BootstrapContext bootstrapContext,
BiConsumer<String, Object> propertyCollector) {
}

@Override
public void contributeRuntimeProperties(BiConsumer<String, Object> propertyCollector) {
}
}
}

0 comments on commit 7ab0f1e

Please sign in to comment.