Posts Tagged ‘Criteria

07
Aug
10

Fluent Interfaces for Searching Hibernate Entities

Recently I changed my job, I am now at my previous employee… the reasons are out of scope for this post so let’s get back to the real point… in the process of developing the software that is scope of this new project a colleague suggested that we should adopt fluent interfaces for the creation of our entities. Sincerely, the term fluent interfaces was new to me but I’ve been a Hibernate user since two dot something (a long time ago) and since Hibernate makes extensive usage of fluent interfaces it turned out not to be that much news. In fact I have to admit that fluent interfaces increase code readability a lot!

Fluent Interfaces for POJOs

The code for the POJOs fluent interfaces was based on a post on Code Monkeyism blog. After adopting this code we started to think about further improvements to that class that made this handle collections, direct access for public fields whenever possible and we crafted an extension to JavaBeans style that let us hide the setter for collections, make the getter return an immutable list and added an addSomething method (all following further good practices that were also on Code Monkeyism).
Project development went on then we hit the point in where we needed to develop our entity search infrastructure. Our first conclusion was that we would probably need a counting facility for our queries and this would probably rule out the usage of NamedQueries since we would need two for each of them (one for counting and one for returning the data – anyways we are still considering if we’ll ever use counting queries for pagination), next obvious point: pagination. But the key point for our search infrastructure was that we had DAOs and we weren’t willing to expose HibernateSession or EntityManagers and we are going to have predefined searches that could have different parameters (some mandatory, some optional). This predefined search scenario is one of the ideal applications for something similar to the fluent interface idea for creating POJOs except that if we resorted to dynamically creating queries this could turn to a huge effort (not to mention a huge wheel reinvention since Hibernate has the incredible Criteria API).

The Solution for Searching Hibernate Entities

The trick for having fluent interfaces on top of hibernate criterias is based around two things:

  1. Basing the solution on top of Criteria ability of expressing constraints and the most important part: creating subcriterias upon entity association navigation
  2. Providing an way of composing the fluent interfaces for expressing collections and integrating this with the concept of the subcriteria

The first point is to implement the InvocationHandler class and making it able to store a Criteria instance which will be responsible for storing the Root Criteria instance and also the SubCriterias (see Subcriteria class) when InvocationHandlers are created for the entity associations.

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
	try {
		String name = m.getName();
      		if ("list".equals(name)) {
        		return criteria.list();
		}
		else if ("count".equals(name)) {
			return criteria.setProjection(Projections.rowCount());
		}
		else {
			if (args == null || args.length == 0) {
				Criteria subCriteria = criteria.createCriteria(name);
				//create another InvocationHandler instance enclosing the newly created subCriteria and pass it to Proxy.newProxyInstance	and return the just created proxy
			}
			else {
				criteria.add(Restrictions.eq(name, args[0]));
			}
		}
    return proxy;
}

The next step is to develop the interfaces, in order to make it easier to understand the idea I’ll provide a sample domain model to make things clearer.

Sample Domain Model

We are going to use the well known Order, OrderItem, Product model in order to make things clearer. Below is a class diagram for our model:

Sample Domain Model

Sample Domain Model


Our fluent interfaces for those classes would (hugely simplified) be:

public interface OrderFluentSearch {
	OrderFluentSearch code(String code);
	OrderItemFluentSearch items();
	List<Order> list();
	long count();
}

The OrderItemFluentSearch would be as follows:

public interface OrderItemFluentSearch {
	OrderItemFluentSearch quantity(int quantity);
	ProductFluentSearch product();
	List<OrderItem> list();
	long count();
}

And finally our ProductFluentSearch interface would be similar to the one below:

public interface ProductFluentSearch {
	ProductFluentSearch code(String code);
	List<Product> list();
	long count();
}

Suppose now that you had a with() method in your Order DAO similar to the one on the Code Monkeyism blog post a search for Orders with an item that references a product with code “10” would be as easy as:

	OrderFluentSearch search = orderDAO.with();
	search.items().product().code("10");
	search.list();

Pretty readable isn’t it? But it still has some drawbacks…
One obvious is that it isn’t possible to express it into a single line. The other one is that we still have an extra interface that wont get automatically renamed when we rename the entity class but I feel like there is one way of fixing this.

Future improvements

Although this idea presents a great improvement regarding code readability of Criteria queries expressed in an application it is still vulnerable to renames on classes attributes. One possibility that I’ll give a try is to use a DSL similar to the one employed on JMock that uses a combination of custom crafted CGLIB classes based on entity classes and a ThreadLocal composition process that allows methods that have no linking between them to share context.

Advertisements
21
Mar
10

Replacing Persistence Caching with In Memory DataGrids

Anyone that designed an enterprise system in Java with non-functional requirements that demanded tight response times faced the challenge of tuning the overall solution. If you are using Hibernate for persistence your first idea is to turn on Hibernate Caching but unfortunately it only Caches loads through Entity Id and sometimes you need to lookup through a secondary unique key. Another solution you might think is turning on Query Cache but as this post points out is more harmful to scalability and latency than you can ever imagine. Although Hibernate Docs and the post referenced above suggest that using @NaturalId annotation and Querying using Criteria API and a specially crafted Restriction through naturalId method would alleviate much of that problem it turns out that updates on related tables hugely undermines the improvements NaturalId queries may bring as this post suggest:

[…] Even though the objects are essentially static, the query cache takes the safe route and says any change to a related table invalidates any and all queries that reference that table. This makes sense, from a generic cache standpoint. […]

Source: Hibernate: Cache Queries the Natural Id Way
Add to this the fact that second level hibernate caches are data caches, not object caches so even on the best case of a cache miss you’d still have the cost of hydrating the object (as it is called on Hibernate terminology).

Object Caching

So, after giving up on all those previous attempts you’ll start considering taking the next obvious path: using/implementing an Object Caching. Have you noticed that I mentioned implementing? Yes, implementing. Now you’ll probably have to take care of the loading process in the case of cache misses, in fact you’ll be using a pattern called Side Caching.
But this can become a tedious code for maintaining and very prone to errors not to mention that implementing asynchronous write-behind won’t be an easy task.

In Memory DataGrids

Fortunately newer solutions marketed as In Memory DataGrids (or IMDG for short) provide an almost automagic way of plugging specially crafted classes that would be responsible for querying the underlying persistent storage on Cache misses, not to mention that they also provide improved partitioning and a great amount of other facilities usually not available on regular caches.
WebSphere eXtreme Scale Loaders and JBoss InfiniSpan CacheStore are examples of such specially crafted extensions for IMDGs. Those APIs also allow for updating the underlying storage (even asynchronously) with the changes that were passed to the in memory cache. One thing still missing (on different extents) on both solutions is the ability of querying the underlying store using a natural key. On eXtreme Scale there is already a framework for loading JPA entities but it lacks the ability of querying the underlying storage by anything different than the Cache Key that in those cases defaults to Entity Id (eXtreme Scale Query API is capable of querying the cache through any eXtreme Scale entity attribute but it only sees the data in memory). InfiniSpan on the other hand as of the 4.0.0 release does not provide anything similar to eXtreme Scale JPALoader or JPAEntityLoader it still sees the database (as on its JDBC Based CacheStore) as means of providing offloading and surviving reloads but never as means of querying data based on application defined format (eg.: application entities). Instead it uses its own format for storing data which limits its capability of loading from application storage in case of cache misses.

Querying IMDGs through Natural Keys

In summary, if you need to query through a natural key, in both cases you’ll need to roll your own Loader/CacheStore. And by querying through a natural key I mean something along the lines of what is described on Bill Burke’s EJB3 book:

The first way to define a primary-key class (and, for that matter, composite keys) is to use the @IdClass annotation. Your bean class
does not use this primary-key class internally, but it does use it to interact with the entity manager when finding a persisted object through
its primary key.
[…]
In your bean class, you designate one or more properties that make up your primary key, using the @Id annotation. These properties
must map exactly to properties in the @IdClass.

This way you can query the Cache using something in the lines of:

MyObjectNaturalKey key = new MyObjectNaturalKey("keyField1", "keyField2");
MyObject o = (MyObject) cache.get(key);

And you’ll have the guarantee that if this object exists either already on memory or in JPA EntityManager it’ll be returned.

Implementing a InfiniSpan CacheStore

Infinispan’s CacheStore interface has the following methods:

package org.infinispan.loaders;
public interface CacheStore extends CacheLoader {
   void store(InternalCacheEntry entry) throws CacheLoaderException;
   void fromStream(ObjectInput inputStream) throws CacheLoaderException;
   void toStream(ObjectOutput outputStream) throws CacheLoaderException;
   void clear() throws CacheLoaderException;
   boolean remove(Object key) throws CacheLoaderException;
   void removeAll(Set<Object> keys) throws CacheLoaderException;
   void purgeExpired() throws CacheLoaderException;
   void prepare(List<? extends Modification> modifications, GlobalTransaction tx, boolean isOnePhase) throws CacheLoaderException;
   void commit(GlobalTransaction tx) throws CacheLoaderException;
   void rollback(GlobalTransaction tx);
   public CacheStoreConfig getCacheStoreConfig();
}

If you need further explanation of what each method does, see its JavaDoc. InfiniSpan team suggests having a look on DummyInMemoryCacheStore in order to have a general idea of how should a CacheStore be implemented but still I have the feeling it misses an explanation of how InternalCacheEntries should be instantiated and in fact there is a factory class for it.
At last, if you need further information JBoss InfiniSpan Wiki has an overview of the builtin CacheStore classes.

Implementing an eXtreme Scale Loader

eXtreme Scale has plenty information on how to write a Loader as well. InfoCenter has two important pages: the first one presents a general overview on how to write a loader, the second one presents one important concept of eXtreme Scale: its tuples. If you implement a Loader that stores its data based on tuples you are free from having to have the stored classes (in case of custom application classes) in the same classloader as the container process.
WebSphere eXtreme Scale Wiki has a page dedicated to explaining how to write a Loader which presents the signature of a class that implements the Loader interface:

package com.ibm.websphere.objectgrid.plugins;
public interface Loader {
    static final SpecialValue KEY_NOT_FOUND;
    List get(TxID txid, List keyList, boolean forUpdate) throws LoaderException;
    void batchUpdate(TxID txid, LogSequence sequence) throws LoaderException, OptimisticCollisionException;
    void preloadMap(Session session, BackingMap backingMap) throws LoaderException;
}

Apart from the Wiki there’s a post on Billy New Port’s DevWebSphere blog
that has the source code available for what he calls the PureQuery Loader for eXtreme Scale. It is a loader capable of loading POJOs from SQL queries.
Finally if you need a starting guide for eXtreme Scale, have a look at ObjectGrid programming model guide and samples that although slighlty old is still a good starting guide for WebSphere eXtreme Scale.
Lastly I’d like to say that Packt Publishing book on eXtreme Scale is also a good reference for it.




ClustrMaps

Blog Stats

  • 361,304 hits since aug'08

%d bloggers like this: