| Your Rating: |
![]() ![]() ![]() ![]()
|
Results: |
![]() ![]() ![]() ![]()
|
26 | rates |
This is the genesis of openutils-mgnlcriteria.
Criteria is a simplified API for retrieving JCR Nodes by composing Criterion objects. This is a very convenient approach for functionality like "search" screens where there is a variable number of conditions to be placed upon the result set.
The JCRCriteriaFactory is a factory for Criteria. Criterion instances are usually obtained via the factory methods on Restrictions.
openutils-mgnlcriteria API is blatantly inspired by Hibernate's Criteria API.
openutils-mgnlcriteria requires JDK 1.5.x or superior
Usage
People already familiar with Hibernate's Criteria will find almost no difference (type names and methods have been kept the same on purpose, whenever possible): you create a Criteria object with one of the static methods in JCRCriteriaFactory and start adding Restrictions and a final optional Order. Then you call the list() method to get your Collection of results (that is instances of info.magnolia.cms.core.Content). As in Hibernate's Criteria, method chaining is supported. Here is an example:
Calendar begin = Calendar.getInstance(); begin.set(2004, Calendar.JANUARY, 1); Calendar end = Calendar.getInstance(); end.set(2008, Calendar.DECEMBER, 1); Collection<Content> pets = JCRCriteriaFactory.createMgnlCriteria("//dogs//*", MgnlContext.getQueryManager("website"), "mgnl:content").add( Restrictions.contains("@name", "Nana")).add( Restrictions.gt("@weight", Float.valueOf(10))).add( Restrictions.between("@birthDate", begin, end).addOrder( Order.desc("@name")).list();
All this will be translated into the following xpath statement
//dogs//*[((jcr:contains(@name, 'Nana')) and (@weight>10.0) and (@birthDate >=xs:dateTime('2004-01-01T00:00:00.000+00:00') and @birthDate <=xs:dateTime('2008-12-01T23:59:59.000+00:00')))] order by @name descending
You can also specify a different type to be returned in the Collection of results. eg.
Collection<Pet> pets = JCRCriteriaFactory.createMgnlCriteria("//dogs//*", MgnlContext.getQueryManager("website"), "mgnl:content", Pet.class).add( Restrictions.contains("@name", "Nana")).add( Restrictions.gt("@weight", Float.valueOf(10))).add( Restrictions.between("@birthDate", begin, end).addOrder( Order.desc("@name")).list();
Internally, this will use info.magnolia.content2bean.Content2BeanUtil.toBean() to transform nodes into beans.
So, for example, if you have a domain Pet class like this
public class Pet { private String name; private Float weight; private Calendar birthDate; //getters and setters here... }
Content nodes returned by the above query will be automatically converted to and populate instances of the Pet type.
Furthermore, you may want to have only a subset of the whole resultset returned, much like in a MySQL limit clause. In this case, you will use the JCRCriteriaFactory.createMgnlCriteriaWithLimit factory method. For this to work, the underlying JCR repository implementation must support this feature (Jackrabbit 1.4+ does).
Here is an example.
Collection<Pet> pets = JCRCriteriaFactory.createMgnlCriteriaWithLimit("//dogs//*", MgnlContext.getQueryManager("website"), "mgnl:content", Pet.class).add( Restrictions.contains("@name", "Nana")).add( Restrictions.gt("@weight", Float.valueOf(10))).add( Restrictions.between("@birthDate", begin, end). setFirstResult(5). setMaxResults(10). addOrder(Order.desc("@jcr:score()")).list();
Notice the setFirstResult(int) and setMaxResults(int) methods. Now calling list() will return a subset of only five Pet objects, starting from the 6th item (counting starts from 0). If you dont specify these two calls, list() will behave as usual by returning the entire result set. If you only call setMaxResults(int), the result set will be the subset of elements (0, maxResults) (firstResultValue is 0 by default).
A word of warning about implementations returned by JCRCriteriaFactory. They are NOT thread-safe, therefore client code wishing to use one of them as a shared global variable MUST coordinate access to it. These objects are actually meant to be instantiated and used within a method scope (e.g. a service method), where no concurrent issues arise.
Finally, it is good to know that openutils-mgnlcriteria API catches all checked exceptions thrown by JCR and Magnolia and wraps them into its own runtime net.sourceforge.openutils.mgnlcriteria.jcr.query.JCRQueryException, leaving to the API user the choice whether to catch it or not and, when needed, get to the original cause of error.
You can check out the openutils-mgnlcriteria from sourceforge svn (sorry, no Maven artifacts yet) here https://openutils.svn.sourceforge.net/svnroot/openutils/trunk/openutils-mgnlcriteria or, if you are using Maven, you can include it in your project as a dependency with the following snippet
<dependency>
<groupId>net.sourceforge.openutils</groupId>
<artifactId>openutils-mgnlcriteria</artifactId>
<version>[version here]</version>
</dependency>
See here for the latest artifact version http://mvnrepository.com/artifact/net.sourceforge.openutils/openutils-mgnlcriteria/

Comments (7)
May 13, 2009
Boris Kraft says:
Another amazing piece of work! Thank so much. For the record, is this module...Another amazing piece of work! Thank so much. For the record, is this module under the umbrella of Openmind or you personally? You can also change the info in the module listif I guessed wrong...
May 13, 2009
Federico Grilli says:
Hi Boris, thank you! As to your question, the API is part of OpenMind's Open...Hi Boris, thank you! As to your question, the API is part of OpenMind's OpenUtils project.
May 13, 2009
Boris Kraft says:
Federico, in the modules list I have named this module "Critera Search" - I thin...Federico, in the modules list I have named this module "Critera Search" - I think that this makes it easier for people to get an idea what it might be about
If you like to, feel free to use that name.
May 13, 2009
Grégory Joseph says:
Note that JCR2 also provides a query api (I haven't looked at it, but I do hope ...Note that JCR2 also provides a query api (I haven't looked at it, but I do hope they've made their job correctly and took note of the best examples around), and that it also deprecates xpath queries ...
May 13, 2009
Federico Grilli says:
Hi Grégory, I must admit that I did not know about JCR2 but from what I've just ...Hi Grégory, I must admit that I did not know about JCR2 but from what I've just seen, the jackrabbit implementation of it looks not very mature and the query API doesnt seem to have a Criteria-like interface. Anyway, hopefully I didnt reinvent the wheel
May 14, 2009
Grégory Joseph says:
Great then; I only knew they had a new query api, but it could be, indeed that t...Great then; I only knew they had a new query api, but it could be, indeed that there's no criteria-api like this one anyway; just wanted to point it out
The API itself should be mature/close to final if not already. The implementation is another story.
May 13, 2009
Grégory Joseph says:
Hey, at first glance I hadn't seen that this was using content2bean to get you a...Hey, at first glance I hadn't seen that this was using content2bean to get you actual beans, that's great