Today Envers 1.1.0.beta2 has been released. This release focuses on supporting persistent collections. In earlier versions, it was only possible to version collections belonging to one-to-many bidirectional relations. Right now Envers supports (almost: see here which and why) all persistent collections supported by Hibernate:
@MapKey, @MapKeyManyToMany, …)Moreover, there is preliminary support for custom user types. Please test! :) Detailed release notes can be found here.
You can head straight to the downloads, and then, if you have any problems or questions, to the forums.
I’ve also pushed 1.1.0.beta2 to JBoss’s Maven2 repository, and 1.0.0.GA made it to the central maven repository.
Enjoy!
Adam
Post to del.icio.us
Yesterday I came back from Herbstcampus 2008 in Nürnberg. I gave there a talk on Envers. Thanks to all who attended! I’d also like to thank the organisers, everything went smoothly and I felt really welcome there :).
You can find the slides here. They lack of course the added value of “live comments”, but if you’ve got any questions, please write on the forum.
Adam
Post to del.icio.us
Hello,
after a vacation break, Envers is back with a 1.1.0.beta1 release. You can find the release notes here .
There’s quite a lot of changes and improvements in this release. Firstly, Envers now only works with Hibernate 3.2.6 or Hibernate 3.3.0. That is because support (not yet complete) for persistent collections is added - and that requires collection event listeners, which were introduced in Hibernate 3.2.6.
However, thanks to the new listeners, you can now version many-to-many relations and unidirectional one-to-many relations (except for the mapping @OneToMany+@JoinColumn
, which will be supported later).
Other improvements include:
org.jboss.envers.unversionedOptimisticLockingField
) to automatically unversion fields in entities annotated with @Version, contributed by Nicolás Doroskevich@Unversioned
annotation, which lets you exclude some fields from versioning, while keeping the entity-wide @Versioned annotation, contributed by Sebastian KomanderI’d like to welcome and thank two new contributors: Nicolás and Sebastian. Don’t hesitate to follow their way :). As always, all forum users were very helpful in finding bugs and suggesting new ideas.
Finally, some updates on configuration. The Envers home page doesn’t yet reflect this (as it’s still a beta release). To use the new collection listeners, be sure that your persistence.xml
includes the following:
<property name="hibernate.ejb.event.post-insert" value="org.jboss.envers.event.VersionsEventListener" /> <property name="hibernate.ejb.event.post-update" value="org.jboss.envers.event.VersionsEventListener" /> <property name="hibernate.ejb.event.post-delete" value="org.jboss.envers.event.VersionsEventListener" /> <property name="hibernate.ejb.event.pre-collection-update" value="org.jboss.envers.event.VersionsEventListener" /> <property name="hibernate.ejb.event.pre-collection-remove" value="org.jboss.envers.event.VersionsEventListener" /> <property name="hibernate.ejb.event.post-collection-recreate" value="org.jboss.envers.event.VersionsEventListener" />
Or if you are using Envers directly with Hibernate:
<event type="post-insert"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event> <event type="post-update"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event> <event type="post-delete"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event> <event type="pre-collection-update"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event> <event type="pre-collection-remove"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event> <event type="post-collection-recreate"> <listener class="org.jboss.envers.event.VersionsEventListener"/> </event>
If you are using Envers with JBoss AS 4.2.x, you’ll have either to bundle the hibernate jars with your application, or upgrade hibernate in the lib
directory of the AS, as the versioned used there is 3.2.4.SP1.
As always, waiting on the forums for your opinions and for bug reports in JIRA .
Adam
Post to del.icio.us
Today the first general availability version of Envers has been released (downloads, release notes).
This is a stable version containig all the features found in the preview and beta versions. It doesn’t contain any major new additions, only some minor bug fixes and the possibility to generate revisions on collections change.
What does it mean? Imagine you have a Person and Address entities in a bidirectional many-to-one relation (each person has exactly one address and many people can live at the same address). Now you change an address of a person - hence, the content of the collection of persons for the new and old addresses change. In the preview and beta versions of Envers, no revision will be generated for the Addresses (only for Person), as data in the database tables is not modified (but data in the java beans is modified). Now, however, a revision will be created for all three entities.
You can switch to the old behaviour by setting the org.jboss.envers.revisionOnCollectionChange configuration option to false (see more on configuration).
There is also now a separate build for Hibernate 3.3.0.CR1.
If you’re an Ohloh user and like Envers, you can click on the “I use this” link on the project profile page.
Thanks to talios, aamonten, genman, liuxiaodu, andrewwheeler and other forum users for very valuable feedback, ideas, testing and bug reports.
Hope you enjoy this release,
Adam
Post to del.icio.us
With the recent addition of queries to Envers, it is now possible to easily retrieve data in a bi-temporal way. If you are not familiar with bi-temporal versioning, a good introduction by Martin Fowler can be found here.
Suppose we want to store information about Persons and Addresses, at which these persons live. Moreover, we also want to store dates: when a Person registered the fact that he/she moved, and when did he/she actually move - these may be different, as a person may have first moved, and only registered the fact after a week. Storing the two dates: registered and actual, for some entity, is the basis of bi-temporal versioning.
We can store this information in a Registration entity, which is in a one-to-one relationship with Person, and one-to-many with Address. (Each Person can have at most one Registration, and therefore also Address; each Address can have many Registrations, and therefore many Persons living there.) The Registration entity can also store the registered and actual dates. Additionally, it can be versioned, so that all historical information is remembered.
Using queries, we can, for example, answer this question: “What did we know about the address of person X in the state of the database from date Y?”. To do this, we have to select a registration, which has the actual date as big (recent) as possible, but both the registration and actual dates must be before Y. Hence, the query can look like this:
versionsReader.createQuery()
.forRevisionsOfEntity(Registration.class, true)
.add(VersionsRestrictions.maximizeProperty("actualDate")
.add(VersionsRestrictions.relatedIdEq("person", personXId))
.add(VersionsRestrictions.le("registrationDate", dateY))
.add(VersionsRestrictions.le("actualDate", dateY)))
.getSingleResult();
You may experiment with bi-temporal versioning using the updated Envers+Seam demo. To run the demo, you’ll need JBoss AS 4.2. After downloading, unzip and deploy the -ds.xml and .ear files, start the server, and go to http://localhost:8080/envers_seam_demo. A screenshot from the demo:

Moreover, the second beta release of Envers is available. It contains minor feature additions (release notes).
Adam
Post to del.icio.us
So far Envers made it easy to store historical data; now, with version 1.0.0.beta1 (download here), you can also query it, in two “dimensions”: for entities at a given revision and for revisions, at which an entity changed. The implementation mostly follows Hibernate Criteria, with some features removed, and some added.
For example the following query returns all persons with the name “John”, sorted by their surname, which lived at the address with the given id at revision 12:
List personsAtAddress =
getVersionsReader().createQuery()
.forEntitiesAtRevision(Person.class, 12)
.addOrder(Order.asc("surname"))
.add(VersionsRestrictions.relatedIdEq(
"address", addressId))
.add(VersionsRestrictions.eq("name", "John"))
.getResultList();
You can find more information about creating queries on this page.
Warning - the schema generated by this version of Envers is incompatible with the schema generated by the preview versions. If you have any data to migrate, please write on the forum. As this is the beta release, there will be no more schema changes until the 1.0 final release.
Thanks to the forum users: talios, aamonten, genman, liuxiaodu and others for bug reports, patches, testing and ideas!
Finally, the release notes for this release are located here.
As always, waiting for comments and bug reports :)
Adam
Post to del.icio.us
Hello,
I’ve posted a poll on what data should be stored in versions tables in Envers, see here and cast your vote:
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=136764
The results will determine the future implementation, so votes really count. And as always, comments & ideas are very welcome.
The two options, in short, are:
Adam
Post to del.icio.us
With the preview 3 release of Envers, you can easily associate additional data with revisions. This could be, for example, the name of the user making the change. You simply need to annotate an entity with @RevisionEntity: an instance of this entity will be persisted with each new revision. To provide a way to fill the entity with custom data, you need to implement an interface, and pass it as a parameter to the annotation.
For example, to store the name of the currently logged in user in a JBoss Seam application, the implementation of the listener would look as follows:
public class ExampleListener
implements RevisionListener {
public void newRevision(Object revisionEntity) {
ExampleRevEntity exampleRevEntity =
(ExampleRevEntity) revisionEntity;
Identity identity =
(Identity) Component.getInstance(
"org.jboss.seam.security.identity");
exampleRevEntity.setUsername(
identity.getUsername());
}
}
For more details see here.
There is also a demo Envers+Seam application: a very simple wiki. It allows users to create and edit pages, view their history and see which users made the changes.
And, as always, waiting for your comments on the forums! Thanks to the current forum members for the bug reports and ideas!
Adam
Post to del.icio.us
You can now download a second preview version of the Envers library!
As a quick reminder, the library enables you to easily version your JPA entities, by simply annotating their properties with @Versioned; it works as an extension to Hibernate and Hibernate Entity Manager.
In this release, in addition to versioning simple properties, like strings, numbers, dates, you can also version the most common type of relations, namely:
@OneToOne@OneToOne(mappedBy="...")@ManyToOne@OneToMany(mappedBy="...")Envers has now a growing test suite, which already helped to eliminate some bugs. Moreover, here you will find a description on how to generate a database schema of your entities together with the versions tables.
If you’d like to share your opinion, you can now use the forum. Waiting for your posts there :).
Adam
Post to del.icio.us
Hello,
Envers is a project which enables you to version your entities, simply by annotating them with @Versioned! It is still very young, and far from a mature project, but some basic functionalities already work.
The project’s web page can be found here: www.jboss.org/envers. There you can download a preview version, a short console demo as well as find a “quick start” guide.
I’d really like to know your opinion on this project, if you find it useful, what features would you expect and so on. So please comment! :)
Adam
Post to del.icio.us