Help

Inactive Bloggers
31. Mar 2015, 22:36 CET, by Steve Ebersole

We just got done releasing Hibernate O/RM 5.0.0.Beta1. I will follow up later with a more in depth blog post for 5.0.0.Final, but this first Beta implements all new APIs and most new features. Specifically in this Beta include:

  • New bootstrapping API - better determinism, better integration
  • Java 8 Support (though still compatible with Java 6). Just add hibernate-java8 to your classpath.
  • Ability to handle additional Java types for id attributes marked as GenerationType#AUTO. Built-in support for Number and UUID. Expandable via new org.hibernate.boot.model.IdGeneratorStrategyInterpreter extension
  • scanning support for non-JPA usage
  • NamingStrategy has been removed in favor of a better designed API. 2 actually: org.hibernate.boot.model.naming.ImplicitNamingStrategy and org.hibernate.boot.model.naming.PhysicalNamingStrategy

Additionally, support for AttributeConverters has been expanded and more fully realized:

  • fully supported for non-@Enumerated enum values
  • applicable in conjunction with @Nationalized support
  • called to handle null values
  • settable in hbm.xml by using type="converter:fully.qualified.AttributeConverterName"
  • integrated with hibernate-envers
  • collection values, map keys

See http://hibernate.org/orm/downloads/ for information on obtaining Hibernate ORM.

NOTE: 5.0 is expected to be compatible with Java 6 (aside from the hibernate-java8 module naturally). However, Beta1 will not work with Java 6 due to something with JAXB that I have not yet had time to investigate. Beta1 requires Java 7. Again, the expectation is to have it be compatible with Java 6 by the next release if possible.

Célébrons l'open source et le partage (English version below).

Place pour Devoxx France à gagner

Devoxx France vous offre une place: je ne suis que le messager :) Elle sera gagnée par l'un d'entre vous. La règle est simple.

Contribuer à un projet open source (code, doc, etc) entre maintenant et dimanche 29 mars 2015 et tweeter le lien vers la pull request ou le patch à @Hibernate.

  • Quel projet ? N'importe pourvu que la licence soit open source. Donc pas limité à Hibernate.
  • Comment sera choisi le vainqueur ? La contribution que je préfère sera choisie. Super bonus si c'est votre première contribution à ce projet : il faut que ça brasse :)
  • Mais si on contribue à un projet Red Hat, on a plus de chance ? Non, tous les projets open source sont (libres et) égaux.
  • Je suis employé Red Hat, je peux gagner? Non. Contacte-moi directement.
  • Et ? C'est tout.

Devoxx France se déroule du 8 au 10 avril à Paris (Palais des Congrès). J'y parlerai entre autre des sujets Object Mappers dans le NoSQL et une BoF Hibernate.

Aller au boulot !

Free pass for Devoxx France

Devoxx France is giving away a free pass through me. I am just the messenger :) One of you will win it. The rule is simple.

Contribute to an open source project (code, doc, etc) between now and Sunday evening 29th of March 2015 and tweet the link to the pull request or the patch to @Hibernate.

  • Which project? Any project released under an open source license. Not limited to Hibernate.
  • How will you chose the winner? The contribution I prefer will be chosen. Extra bonus if that's your first contribution on that project: let's exchange!
  • But if I contribute to a Red Hat project, I have a better chance? No, all open source projects are equals.
  • I am a Red Hat employee, can I win? No. Contact me directly instead.

Devoxx France happens in Paris from the 8th to the 10th of April. I will be speaking about a few topics including Object Mappers and NoSQL and an Hibernate BoF.

Now go contribute!

PS légal: cette place est offerte par Devoxx France et Emmanuel Bernard à titre personnel, pas par Red Hat. Bref, je fais ce que je veux, avec mes cheveux. Legal PS: this pass if given away by Devoxx France and Emmanuel Bernard as an individual and free human being, not Red Hat.

We released Hibernate Search 5.1.1.Final, a micro update for version 5.1: our latest best release ever which we described early this month.

Special thanks to:

Török László for fixing a subtle bug in NullEncodingTwoWayFieldBridge

Russell Dickenson for fixing many typos in the documentation

Thach Hoang for improving javadoc of the @Spatial annotation

Besides the above fixes, a good reason to publish this release already was HSEARCH-1824. This problem won't affect you as Hibernate user but was a blocker to update the Infinispan Query engine to Hibernate Search 5.1.x.

Remember you can annotate any Java pojo - even not Hibernate entities - and have them indexed and queried as usual when you store them in Infinispan.

Get updated!

Everything you need is available on Hibernate Search's web site. Download the full distribution from here, or get it from Maven Central, and don't hesitate to reach us in our forums.

Stackoverflow

If you prefer to use stackoverflow.com, please use the tag hibernate-search. And if you have a moment to help other users, some please consider registering to the hibernate-search tag to help us answering all the questions.

If you are new to Hibernate Search, best is to start with our getting started guide. And remember: feedback, comments and/or pull-requests are welcome on the website too.

One of the fundamental principles of Hibernate/JPA is that any writes done through the Session/EntityManager APIs are collected in the persistence context and are only written to the database upon transaction commit. If needed, you can enforce the flushing of changes by explicitly invoking the flush() method. Also Hibernate may trigger a flush automatically, e.g. prior to executing a query. This strategy allows to perform many optimizations, e.g. only persisting the final state of an entity changed several times, make use of batched inserts and others.

Hibernate OGM follows this approach and uses transaction boundaries for demarcating units of work and triggering writes to the datastore. Naturally, this works just fine on transactional NoSQL stores such as Infinispan or Neo4j, but it poses some challenges on stores without full transactional semantics.

For instance consider a method of a stateless EJB (which automatically runs within a container-managed transaction) which inserts three entities. If an error occurs when inserting the last entity, the other two will already have been written. When using a non-transactional datastore, there is no way to rollback these already applied changes. Depending on the specific use case, this may be acceptable; But in other cases it is desirable to take some action, for example retrying the failed insertion or performing compensating writes for the succeeded insertions, effectively undoing them.

This is where our new error handling API comes in. It allows you to get notified upon failed datastore operations or transaction rollback attempts, providing you with the executed and failed operation(s). This e.g. enables you to:

  • log all applied operations
  • retry a failed operation (e.g. after timeouts)
  • make an attempt to compensate applied changes (by executing an inverse operation)

An example error handler

Let’s take a look at an example:

public class ExampleErrorHandler implements ErrorHandler {

    @Override
    public void onRollback(RollbackContext context) {
        // write all applied operations to a log file
        for ( GridDialectOperation appliedOperation : context.getAppliedGridDialectOperations() ) {
            switch ( appliedOperation.getType() ) {
                case INSERT_TUPLE:
                    EntityKeyMetadata entityKeyMetadata = appliedOperation.as( InsertTuple.class ).getEntityKeyMetadata();
                    Tuple tuple = appliedOperation.as( InsertTuple.class ).getTuple();

                    // write EKM and tuple to log file...
                    break;
                case REMOVE_TUPLE:
                    // ...
                    break;
                case ...
                    // ...
                    break;
            }
        }
    }

    @Override
    public ErrorHandlingStrategy onFailedGridDialectOperation(FailedGridDialectOperationContext context) {
        // Ignore this exception and continue
        if ( context.getException() instanceof TupleAlreadyExistsException ) {
            GridDialectOperation failedOperation = context.getFailedOperation();
            // write to log ...

            return ErrorHandlingStrategy.CONTINUE;
        }
        // But abort on all others
        else {
            return ErrorHandlingStrategy.ABORT;
        }
    }
}

The onRollback() method - which is called when the transaction (or unit of work) is rolled back (either by the user or by the container) - shows how to iterate over all datastore operations applied prior to the rollback attempt, examine their specific type and e.g. write them to a log file.

The onFailedGridDialectOperation() method is called for each specific datastore operation failing. It lets you decide whether to continue - ignoring the failure - or abort the operation. If ABORT is returned, the causing exception will be re-thrown, eventually causing the current transaction to be rolled back. If CONTINUE is returned, that exception will be ignored, causing the current transaction to continue.

The decision whether to abort or continue can be based on the specific exception type or on the grid dialect operation which caused the failure. In the example all exceptions of type TupleAlreadyExistsException are ignored (meaning we don't care about duplicate records being inserted into the datastore), whereas all other exceptions cause the current unit of work to be aborted. You also could react to datastore-specific exceptions such as MongoDB’s MongoTimeoutException, if needed.

Having created the ErrorHandler implementation, it needs to be registered with Hibernate OGM. You can do so for instance using a persistence unit property in META-INF/persistence.xml:

<property name="hibernate.ogm.error_handler" value="com.example.ExampleErrorHandler"/>

Feedback needed!

In its current form the API lays the ground for manually performing tasks such as retrying, logging and similar. But we envision a more automated approach in future versions, e.g. for automatic retries of failed operations.

Of course this API can and will not bring transactional guarantees to datastores which don't support them natively. If you find yourself frequently in a situation where you wish for transactional "all or nothing" semantics, you might consider to move to a datastore which actually provides this functionality. But you also may look into more suitable mapping approaches. For instance embeddables and element collections are a great way for ensuring atomicity of an entity and dependent structures on document stores such as MongoDB or CouchDB, as they will be mapped to a single, hierarchically structured document which can updated with a single datastore call.

At this point, the API is considered experimental and will evolve in future releases. For this, your input is very important to us! Let us know what you would like to do with such an API and what functionality should be added. Just tweet to @Hibernate or send a mail to our development list. If you like, you also may add comments to the JIRA issues addressing further development of the API: OGM-775 ("Introduce RETRY error handling strategy"), OGM-776 ("Provide means for executing compensating actions") and OGM-777 ("Expose more context information via error handler contexts").

Any feedback is greatly appreciated!

I am happy to announce the release of Hibernate OGM 4.1.3 Final and 4.2.0.Beta1!

The former brings several usability improvements, bug fixes and component upgrades, whereas the latter comes with new query features, an error handling API for non-transactional datastores and more.

The releases can be obtained as ZIP or TAR.GZ from SourceForge (4.1.3.Final, 4.2.0.Beta1) or via Maven, Gradle etc., using the following GAV coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:4.1.3.Final or org.hibernate.ogm:hibernate-ogm-core:4.2.0.Beta1 for the Hibernate OGM engine and
  • org.hibernate.ogm:hibernate-ogm-<%DATASTORE%>:4.1.3.Final or org.hibernate.ogm:hibernate-ogm-<%DATASTORE%>:4.2.0.Beta1, depending on the backend you want to use.

Note that from 4.2 onwards, Hibernate OGM requires Java 7. We aimed at Java 6 compatibility for as long as possible, but with more and more of our backends and components requiring Java 7 (e.g. Neo4j and Lucene), we felt that it was time to move on and take advantage of the Java 7 goodies for the Hibernate OGM code base as well.

Let's dive into some of the new functionality of the 4.2 Beta1 release.

Query improvements

We continued our quest for extensive query capabilities and enabled more JP-QL constructs, namely queries on element collections. For example consider the following entity Order which contains an element collection of its order lines:

@Entity
public class Order {

    @Id
    @GeneratedValue
    private long id;

    @ElementCollection
    private List<OrderLine> orderLines = new ArrayList<>();

    // getter, setters etc. ...
}

@Embeddable
public class OrderLine {

    private String item;
    private BigDecimal price;

    // getter, setters etc. ...
}

To obtain a list of all orders which contain a wooden toy train order line, you could run the following JP-QL query:

List<Order> toyTrainOrders = entityManager
    .createQuery( "FROM Order o JOIN o.orderLines ol WHERE ol.item LIKE '%wooden toy train%'" )
    .getResultList();

As with other JP-QL queries, Hibernate OGM will convert the query string into a native query for MongoDB and Neo4j. For the other backends a Lucene-based full-text query will be created.

Note that the JOIN syntax at this point is only supported for element collections, i.e. you cannot create join queries for arbitrary associations to other entities. The reason is that most NoSQL stores don't support joins between different tables/collections, therefore such query can't be translated in a sensible way. An exception are graph databases such as Neo4j where joins can be converted into queries based on relationships (which is what actually happens for the element collection case), but we are not quite there yet :)

API for retrieving all executed and failed datastore operations

Hibernate ORM collects all write operations internally and propagates them to the database in most cases only upon transaction commit (in addition, changes will also be flushed prior to query execution or upon explicite flush() calls). This enables many optimizations such as batched inserts. Hibernate OGM follows this approach and also uses transaction boundaries for demarcating units of work and triggering writes to the datastore.

While this naturally works great with transactional NoSQL stores such as Infinispan or Neo4j, it poses some challenges on non-transactional datastores. The 4.2 release therefore provides the initial draft of an API which notifies you upon failed datastore operations, letting you take appropriate action such as e.g. logging all previously applied operations or retrying a failed operation.

In order to not let this release announcement grow too big, there is a separate post just dedicated to this new API.

Support for Fongo

Fongo ("Fake Mongo") is a very nice tool when it comes to testing MongoDB applications. It provides a pure in-memory implementation of the MongoDB Java API which allows to test MongoDB-based applications without starting up an actual MongoDB instance.

Thanks to community member Alex Soto, you can use Fongo now also for testing your Hibernate OGM based application. To do so, simply add the following dependencies to your project (assuming you work with Maven and have added the Hibernate OGM BOM to the dependencyManagement block of your POM file):

<dependencies>
    <dependency>
        <groupId>org.hibernate.ogm</groupId>
        <artifactId>hibernate-ogm-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>com.github.fakemongo</groupId>
        <artifactId>fongo</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Then specify "fongodb" as the Hibernate OGM datastore provider, e.g. via a persistence unit property in META-INF/persistence.xml:

<persistence-unit name="example-PU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
    <properties>
        <property name="hibernate.ogm.datastore.provider" value="fongodb"/>
    </properties>
</persistence-unit>

Hibernate OGM will now use Fongo rather than a real MongoDB server as the backend. As said, this can be quite handy when testing your application, just do not forget to switch to a real datastore when deploying to production ;-)

Usability improvements

Finally, let's take a quick look at two nice usability improvements which you already get with the update to 4.1.3.

The first is a better support for the RESOURCE_LOCAL transaction type when working with stores such as MongoDB under Java SE. As described above, Hibernate OGM relies on transaction demarcation to gather data changes and write them to the datastore in an optimized way. This used to require a JTA implementation on the classpath, also if the underlying datastore actually is not transactional. This is obsolete now, i.e. you can work with RESOURCE_LOCAL and MongoDB, CouchDB etc. without any further dependencies.

If you work with Hibernate OGM and Hibernate Search, you will be happy to learn that the creation of full-text queries became easier. It is not necessary any longer to configure the database retrieval method for each and every FullTextQuery, instead this happens automatically on a global level now when bootstrapping the Hibernate OGM engine.

Showing 6 to 10 of 1251 blog entries