JBoss Envers
By: jeroen weelink, 30 December 2008Auditing is een van de belangrijkste onderdelen in ieder systeem. Er zijn al enkele manieren om dit te regelen. Het makkelijkste is een audit log, Gerry Noij is nu bezig met het beschrijven van het temporal object pattern.
JBoss heeft sinds dit jaar een nieuw project erbij: Envers. Annoteer je de classes of properties met @Versioned, dan wordt de rest voor je geregeld.
The Envers project aims to enable easy versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to version, with
@Versioned. For each versioned entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.
Om een voorbeeld te geven hoe je classes er in het vervolg uitzien, een klein stukje overgenomen van de quickstart.
Class Person:
import org.jboss.versions.Versioned;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;
@Entity
@Versioned // that's the important part
public class Person {
@Id
@GeneratedValue
private int id;
private String name;
private String surname;
@ManyToOne
private Address address;
// add getters, setters, constructors, equals and hashCode here
}
Class Address:
@Entity
@Versioned
public class Address {
@Id
@GeneratedValue
private int id;
private String streetName;
private Integer houseNumber;
private Integer flatNumber;
@OneToMany(mappedBy = "address")
private Set<Person> persons;
// add getters, setters, constructors, equals and hashCode here
}
Daarnaast moeten er 6 listeners worden geregistreerd. Als je het schema laat genereren, worden er 2 extra tabellen aangemaakt: address_versions en person_versions en deze worden automatisch gevuld met historische data. Het ophalen van een specifieke versie gebeurt met een VersionReader:
VersionsReader reader = VersionsReaderFactory.get(entityManager);
Person oldPerson = reader.find(Person.class, personId, revision);
Het is mij net bekend geworden dat dit bestaat, ik heb zelf geen ervaring met Envers. Misschien dat anderen dat wel hebben?

31 December 2008 om 1:49 pm
Ik ben afgelopen maand op DeVoxx bij een sessie over Envers geweest. Het oogde vrij compleet in mijn ogen. Ook integreert het vrij netjes met Hibernate en leek het vrij unobtrusive.
Twee dingen die ik jammer vond.
1 Het werkt momenteel alleen nog met Hibernate. Je kunt natuurlijk wel van Hibernate EntityManager gebruikmaken, zodat je code op JPA lijkt, maar het zijn de Hibernate specifieke listeners die het zware werk doen. Ik ben benieuwd of (en wanneer) er ondersteuning komt voor de andere JPA implementaties. JBoss kennende, zal dat wel niet zo snel gebeuren.
2 Het zorgt voor een vrij forse performance penalty. Hij liet een paar simpele benchmarks zien waarin je een factor 1,5 tot 2 vertraging kunt verwachten. Dan heb ik liever een database trigger.
Maar al met al oogt het wel als iets waarmee ik een keer wil gaan experimenteren.
Zie ook Adam Warski’s blog: http://www.warski.org/blog/
5 January 2009 om 12:34 pm
Dat valt me tegen. Ik had niet gedacht dat het een factor 1,5-2 zou zijn. Het is nog maar versie 1, dus wie weet wat de toekomst brengt.
Laat maar even weten als je ermee bezig bent geweest. Lijkt me wel interessant wat je ervaringen zijn.