Help

I'm member of the Hibernate Team at Red Hat, currently working on Hibernate Validator, the reference implementation of JSR 349 (Bean Validation). I'm also serving in the JSR 349 expert group.

Location: Hamburg, Germany
Occupation: Hibernate team member
Archive

It's my great pleasure to announce the release of Hibernate OGM 4.1.0.Beta3. This release is focused on an improved experience when working with the Neo4j graph datastore and several improvements in the field of querying (the complete change log can be found here).

As always, you can either download a release bundle from SourceForge or retrieve the JARs from the JBoss Nexus repository server using Maven, Gradle etc. The GAV coordinates are:

  • org.hibernate.ogm:hibernate-ogm-core:4.1.0.Beta3 for the Hibernate OGM engine and
  • org.hibernate.ogm:hibernate-ogm-<datastore>:4.1.0.Beta3, depending on the backend you want to use.

Improved support for Neo4j

We now take advantage of labels - a new feature of Neo4J 2.x - to map entities in a more natural way. We use these labels to tag all the nodes belonging to one entity type. This does not only remove the need to put additional properties to the nodes but also will allow us to query for all the nodes of one entity type in an efficient manner.

We also support the execution of native Cypher queries now. You can either create them ad-hoc via EntityManager#createNativeQuery() or using the @NamedNativeQuery annotation on your entities:

@Entity
@NamedNativeQuery(
    name = "AnimalsBySpecies",
    query = "MATCH ( n: Animal { species: {species} } ) RETURN n",
    resultClass = Animal.class 
)
public class Animal { ... }
    
EntityManager em = ...
List<Animal> giraffes = em.createNamedQuery( "AnimalsBySpecies", Animal.class )
    .setParameter( "species", "Giraffe" )
    .getResultList();

As you can see in the example, native queries for Neo4j also support named parameters via the native Cypher parameter syntax.

The work on the Neo4j dialect is in full swing these days and you can expect to see further improvements in this field in the Beta4 release.

Query improvements

When working with queries you can now make use of setFirstResult() and setMaxResults() to page through a result set. This works for JP-QL as well as native MongoDB queries:

EntityManager em = ...;
List<Animal> giraffes = em.createQuery( "FROM Animal WHERE species = 'Giraffe'" )
    .setFirstResult( 51 )
    .setMaxResults( 100 )
    .getResultList();

Furthermore there is support for ORDER BY clauses in JP-QL queries now:

List<Animal> giraffes = em.createQuery( "FROM Animal WHERE species = 'Giraffe' ORDER BY name DESC" )
    .getResultList();

These two things together should be of great help when using Hibernate OGM to implement typical CRUD use cases (create, read, update, delete) on top of your NoSQL store.

What's next?

For Beta4 we plan to translate JP-QL queries into native Cypher queries for the Neo4j backend. We also got some ideas for performance improvements and will take a look into a more natural mapping of assocations to Neo4j relationships.

The MongoDB dialect should see some improvements around querying as well and we plan on investigating an error report and compensation API. This will offer the ability to collect errors on partially executed units of work on stores without full transactional semantics and the ability to react to these errors.

Needless to say, your feedback matters very much to us. So you're very welcome to raise your voice on the mailing list, ask questions in the forum or report any bugs or feature requests in the issue tracker.

19. Feb 2014, 20:59 CET, by Gunnar Morling

It's my great pleasure to announce the release of Hibernate OGM 4.1.0.Beta1! This version shines with:

  • support for CouchDB
  • query execution via JPA
  • new Option API
  • and much more, including a version bump

But wait, hasn't the last released version been 4.0.0.Beta4? That's true indeed, and in case you were wondering, we did not forget to do a final release of the 4.0 line. The reason for the version bump is that Hibernate OGM is now compatible with JPA 2.1 and Hibernate ORM 4.3. To reflect this we thought it'd be a good idea to jump to a new minor version as well.

As usual, you can get the release from SourceForge (ZIP, TAR.GZ) or retrieve it from the JBoss Nexus repository server using your favorite dependency management tool. The GAV coordinates are:

  • org.hibernate.ogm:hibernate-ogm-core:4.1.0.Beta1 for the OGM engine and
  • org.hibernate.ogm:hibernate-ogm-<datastore>:4.1.0.Beta1, depending on the backend you want to use.

Note that we did move some packages around, so make sure to look at our migration guide.

Enough of the introductory words, let's have a closer look at some of the new features.

Support for CouchDB

Based on a huge contribution of community member Andrea Boriero (thanks again, Andrea!), Hibernate OGM comes now with support for Apache CouchDB. CouchDB is a scalable document datastore which persists data as JSON documents and offers an HTTP API, fully embracing REST principles.

The storage strategy of the new dialect resembles that used for MongoDB. In particular we aimed for a very natural mapping of entities to documents in the datastore. E.g. properties are mapped as document fields, embeddables are mapped as nested documents etc. We're also leveraging CouchDB's built-in optimistic locking mechanism to detect concurrent updates, just as you would expect it.

The listing belows shows an entity and how it is represented as JSON document in CouchDB:

@Entity
public class News {

    @Id
    private String id;

    @Version
    @Generated
    @Column(name="_rev")
    private String revision;

    private String title;

    @Column(name="desc")
    private String description;

    //getters, setters ...
}

# JSON document
{
    "_id": "News:id_:news-1_",
    "_rev": "1-d1cd3b00a677a2e31cd0480a796e8480",
    "$type": "entity",
    "$table": "News",
    "title": "On the merits of NoSQL",
    "desc": "This paper discuss why NoSQL will save the world for good"
}

As you can see, the @Id attribute is mapped to CouchDB's reserved _id field, the same applies for the revision attribute which is mapped to _rev. The @Version and @Generated annotations advice OGM to handle the revision property as version attribute and use it for optimistic concurrency control. The @Column annotation can be used to map a property to a document field with another name.

To learn more about the CouchDB dialect and how to use it, refer to the reference guide. Note that the dialect is considered experimental at this time, so don't expect everything to work perfectly yet. Of course any feedback is highly welcome; maybe you even want to tackle one of the open issues) in this field?

Query improvements

We're very pleased to have progressed in the field of queries, addressing several long standing feature requests.

It's possible now to issue JP-QL queries via the EntityManager API which is great news for you if you're preferring JPA over using the native Hibernate API:

EntityManager em = ...;
List<Animal> giraffes = em.createQuery( "FROM Animal WHERE species = :species" )
    .setParameter( "species", "Giraffe" )
    .getResultList();

You also can work with named queries now:

@Entity
@NamedQuery(name = AnimalQueries.BY_SPECIES, query = "FROM Animal WHERE species = :species")
public class Animal { ... }

EntityManager em = ...;
List<Animal> giraffes = em.createNamedQuery( AnimalQueries.BY_SPECIES, Animal.class )
    .setParameter( "species", "Giraffe" )
    .getResultList();

Depending on the chosen backend, these queries will either be translated into Lucene Queries via Hibernate Search or into native queries of the backend (currently the case for MongoDB).

Option API

One big challenge Hibernate OGM has to deal with is how to expose store-specific functionality and configuration options in case the JPA semantics are not sufficient. Taking MongoDB as example, you might want to configure the write concern or a strategy for persisting association information.

Hibernate OGM now provides an extendible, type-safe and comprehensible mechanism for declaring such options. You can use annotations and a programmatic API. Dialect authors can plug in store-specific configuration options very easily, allowing users to specify these options in an intuitive and type-safe fashion. The following shows an example:

@Entity
@AssociationStorage(AssociationStorageType.ASSOCIATION_DOCUMENT)
public class Zoo {

    @OneToMany
    private Set<Animal> animals;

    @OneToMany
    private Set<Person> employees;

    @OneToMany
    @AssociationStorage(AssociationStorageType.IN_ENTITY)
    private Set<Person> visitors;

    //...
}

The @AssociationStorage annotation on the entity level expresses that all associations of the Zoo class should be persisted as separate association documents. Only the visitors association will be stored embedded within the corresponding Zoo document, as the local @AssociationStorage annotation takes precedence.

We try to share such configuration options between stores of one kind where feasible. E.g. the @AssocationStorage annotation is applicable to all document datastores (while e.g. an option such as @WriteConcern would be specific to MongoDB), simplifying the migration between stores. Neat, isn't it?

Now let's have a look at how you'd apply the same configuration using the programmatic API:

public class MyOptionConfigurator extends OptionConfigurator {

    @Override
    public void configure(Configurable configurable) {
        configurable.configureOptionsFor( MongoDB.class )
            .associationStorage( AssociationStorageType.ASSOCIATION_DOCUMENT )
            .entity( Zoo.class )
                .associationStorage( AssociationStorageType.IN_ENTITY )
                .property( "visitors", ElementType.FIELD )
                    .associationStorage( AssociationStorageType.ASSOCIATION_DOCUMENT )
                    .associationDocumentStorage( AssociationDocumentType.COLLECTION_PER_ASSOCIATION );
    }
}

All you need to do is to create an OptionConfigurator implementation, which provides access to the fluent configuration API. You can apply settings on a global level and then use entity() and property() to navigate to single entities and properties and apply options to the same. Again you can declare options specific to the store as well as options common to the family of store. Just don't forget to register your configurator when bootstrapping Hibernate OGM.

The work on options has been mainly behind the scenes in this release, with the shown options only being the first few examples for leveraging this new mechanism. You can expect to see more options specific to single stores or store families in future releases, providing you with all the flexibility you need to configure your datastore.

Streamlined configuration properties

The new option mechanism is an elegant way for specifying many options in a type-safe way. But plain properties in persistence.xml are just more appropriate for settings such as the host name of the store, user name etc. When working on the option API, it became apparent that several of our backend modules had the same or very similar configuration properties, but partly with different names and adhering to different naming conventions. So we took the chance to clean up the mess and re-organized the properties.

Properties common to all/most stores are named hibernate.ogm.datastore.* now, so e.g. there is hibernate.ogm.datastore.host, hibernate.ogm.datastore.username, hibernate.ogm.datastore.database etc. Properties specific to a single store are named hibernate.ogm.<datastore>.*, e.g. hibernate.ogm.mongodb.connection_timeout. Note that when programmatically bootstrapping a session factory or entity manager factory, you should refer to the properties using the constants declared on OgmProperties, InfinispanProperties etc.

While this change greatly increases consistency and removes redundancies, it requires existing applications to be adapted. So check out the reference guide to make sure you use the right names.

As always, your feedback around the new release is highly welcome. The complete change log can be found here. You can file bugs or feature requests in the issue tracker, ask questions in the forum or discuss ideas around the development of Hibernate OGM on our mailing list.

It's my pleasure to announce the first alpha release of Hibernate Validator 5.1. This release brings you several new features based on top of the Bean Validation 1.1 APIs, substantial performance improvements as well as some bug fixes.

As usual, you can obtain this release either as distribution bundle (ZIP or TAR.GZ) from SourceForge or retrieve it using your preferred dependency management tool under the GAV coordinates org.hibernate:hibernate-validator:5.1.0.Alpha1. The binaries have been pushed to the JBoss Maven repository and should soon be synched to Maven Central as well.

What's in it?

The features added in this release are centered around the new APIs and functionality provided by Bean Validation 1.1, such as method validation and expression based message interpolation. Let's have a closer look at some of them.

With HV-714 we added a new constraint, @ParameterScriptAssert which allows to validate the parameters of a method or constructor using a script expression:

@ParametersScriptAssert(script = "arg0.before(arg1)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

Similar to @ScriptAssert (which applies to the class level) this constraint can be used with every scripting language for which a JSR 223 compatible engine exists. You can choose between a wide variety of options such as JavaScript (for which the JDK provides an engine out of the box), Groovy, JRuby and many others.

As shown in the example, the names arg0, arg1 etc. are used by default to refer to the parameters of the validated method or constructor. This does not read very well, but unfortunately Java doesn't provide a standardized way to obtain parameter names at runtime (this will change with Java 8 where parameter names can be accessed via reflection).

To address this issue, Bean Validation defines an SPI which allows to plug in custom parameter name providers. Hibernate Validator offers now an implementation of that SPI (HV-802) which is based on the ParaNamer project. ParaNamer is a nice little library which provides several ways for obtaining parameter names at runtime:

  • based on debug symbols created by the Java compiler,
  • constants with the parameter names woven into the bytecode in a post-compile step or
  • annotations such as the @Named annotation from JSR 330.

To use this parameter name provider, add the ParaNamer library to the classpath and configure the provider like this when bootstrapping a validator:

Validator validator = Validation.byDefaultProvider()
    .configure()
    .parameterNameProvider( new ParanamerParameterNameProvider() )
    .buildValidatorFactory()
    .getValidator();

With the parameter name provider configured, you can refer to the parameters using their actual names from within the @ParameterScriptAssert constraint (the names will also be used by constraint violations for invalid parameter constraints):

@ParametersScriptAssert(script = "start.before(end)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

Refer to the ParaNamer documentation to learn more about the different ways it provides for accessing parameter names.

Message interpolation

Another nice new feature is an extension of the ConstraintValidatorContext API which allows to add arbitrary objects to constraint violation messages (HV-701). As an example, let's consider this custom validator for the @Future constraint:

public class MyFutureValidator implements ConstraintValidator<Future, Date> {

    public void initialize(Future constraintAnnotation) {}

    public boolean isValid(Date value, ConstraintValidatorContext context) {
        if ( value == null ) { return true; }

        Date now = GregorianCalendar.getInstance().getTime();

        if ( value.before( now ) ) {
            HibernateConstraintValidatorContext hibernateContext =
                context.unwrap( HibernateConstraintValidatorContext.class );

            hibernateContext.disableDefaultConstraintViolation();
            hibernateContext.addExpressionVariable( "now", now )
                .buildConstraintViolationWithTemplate( 
                    "Must be after ${formatter.format( '%1$te.%1$tm.%1$tY %1$tH:%1$tM', now ) }"
                )
                .addConstraintViolation();

            return false;
        }

        return true;
    }
}

Instead of just using "Must be in the future" as constraint violation message, this validator adds the current time to the message. For that purpose an expression variable with the name "now" is added to the validation context, holding a Date object representing the current time. Using the variable name, it can be accessed from within the violation message and formatted as shown in the example.

Performance improvements

Besides adding new functionality, we also worked hard to make sure that Hibernate Validator gives you the performance you deserve. Throughout extensive profiling sessions we identified and addressed several performance bottlenecks, e.g. around message interpolation (HV-637). Performance tuning - with respect to memory consumption as well as execution speed - is an ongoing effort and you can look forward to further improvements in that area in the next releases.

This concludes our tour through the new features of Hibernate Validator 5.1.0.Alpha1. You can find the complete list of all fixed issues in the release notes. The reference guide describes all added functionality in detail.

Let us know how you like the new release by adding a comment or posting to the forum. If you have found a bug be sure to file a JIRA issue for it. Or, even better, fork the code base and submit a pull request with the required fix. To discuss any development related issues, just send a message to the hibernate-dev list.

It has been a couple of weeks since Bean Validation 1.1 has gone final. In the mean time, the Java EE 7 platform spec has been finalized as well, so it's about time to have a closer look at what you can expect from these updates in relation to Bean Validation and its reference implementation, Hibernate Validator 5.

Over the following weeks, we'll dive into the most exciting new features in a series of blog posts, starting today with the usage of expression language in error messages.

Executive summary

Many users relate the Unified Expression Language (EL) only to JSF and JSP. But it doesn't stop there. Actually, EL has matured over time into an independent language with it's own specification and nice features such as Lambda expressions. It can be used in any application layer, in Java EE as well as Java SE based applications.

Bean Validation 1.1 makes use of EL to offer advanced functionality around constraint violation messages such as conditional messages and customizable message formatting.

Using EL expressions in constraint messages

As an example, let's take a look at the built-in @DecimalMax constraint. As of Bean Validation 1.1, this constraint has a new flag named inclusive which specifies whether the given maximum value is inclusive or not. Depending on the flag's value, the constraint's error message should either be must be less than {value} or must be less than or equal to {value}.

This kind of behaviour was not easily achievable in Bean Validation 1.0 but it is straight-forward using an EL expression which conditionally adds the or equal to part:

must be less than ${inclusive == true ? 'or equal to ' : ''}{value}"

EL expressions are given in the form ${expression}. You can use them to implement conditional logic as in the example, perform calculations, nicely format values etc. Refer to the EL specification to learn more about the provided functionality and the syntax.

As the {value} expression from the example shows, the Bean Validation 1.0 syntax for referencing attributes is still supported and takes precedence over expression evaluation. So for instance the message ${amount} would be interpolated into something like $50.

Referring to the validated value

Besides all attributes of the validated constraint (such as inclusive) you can access the value to which the constraint is applied using the name validatedValue as shown in the following example:

@ValidCustomer( message = "Not a valid customer: ${validatedValue.getName()}" )
public class Customer {

    //...

    public String getName() {
        return name;
    }
}

Here, a violation of the @ValidCustomer constraint would produce a message such as Not a valid customer: Bob.

Doing some formatting

Finally, a helper for formatting strings is exposed under the name formatter, providing a var-args method format(String format, Object... args) which exactly behaves like java.util.Formatter.format(String format, Object... args). This comes in handy if you e.g. want to format number values in a special way:

public class Order {

    @DecimalMin(value="20.00", message="Order value too low: € ${formatter.format('%08.2f', validatedValue)}")
    private final BigDecimal value;

    //...
}

The shown format expression causes the value to be padded with leading zeros, so if the @DecimalMin constraint is violated, you would get a message such as Order value too low: € 00017.89.

EL and the classpath

In order to use the expression language feature, you need an EL implementation on your classpath. That's usually the case when running in a Java EE container such as WildFly, but you'll have to add an implementation by yourself if your application runs in a plain Java SE environment. Two implementations known to work with Hibernate Validator are the EL reference implementation and JUEL.

Finally a special tip to all the Tomcat users out there. Hibernate Validator requires at least EL 2.2. This is part of Tomcat 7, so you should be all set there. Tomcat 6 only comes with an EL 2.1 implementation, though. So does this mean you can't experience all the Bean Validation 1.1 goodness on Tomcat 6 then? Luckily not, it just requires a little preparation. Check out the Hibernate Validator FAQ to learn how to update the Tomcat EL libraries.

Trying it out yourself

If you'd like to give the expression language feature a spin, just grab the latest Hibernate Validator release from here. If you work with Maven, Gradle or similar, you can pull it into your project using its GAV coordinates org.hibernate.hibernate-validator.5.0.1.Final. And if you feel adventurous and like playing with the latest bits, you even may build WildFly yourself from its sources. It has been updated to Hibernate Validator 5 a couple of days ago.

The recently revamped reference guide has all the information you need, and we're happy to help you with any questions in the forum.

Recently I had the chance to give a talk on Bean Validation 1.1 at Berlin Expert Days (BED-Con), a nice mid-sized conference (2 days, 500 attendees) hosted at Freie Universität in Berlin. As in the last years, BED-Con was a great experience with awesome people and many insightful talks in the fields of Java EE, NoSQL, Continuous Delivery etc. I really can recommend this event which is planned to take place next year again.

My talk on Bean Validation went very well and I got lots of questions on the new functionality. In particular the possibility to use constraints on method parameters and return values (method validation) seems to be a helpful feature for many. You can find my slides which discuss the new features on the conference web site (in German, though).

I also used the opportunity to listen to some talks around client side web applications using HTML 5 and REST. There's a lot of activity going on in this field right now, and it appears like a new framework is released every day.

An interesting question to me is how Bean Validation as Java based technology fits into this picture. Bean Validation provides an API for retrieving constraint meta-data from models which could be used to perform a client-side validation of data entered by the user. It would surely be interesting to see how this could be leveraged to expose constraint meta-data e.g. via a REST service and use it on the client with frameworks such as AngularJS. Maybe this is even done by some frameworks already?

Showing 1 to 5 of 7 blog entries