Blogs

SpringSource Blog

Announcing GORM for Redis

grocher

One of the major movements inspired by the rise of the cloud platform is the growing interest in alternative storage techniques to traditional relational databases. One such storage mechanism is Redis, a high performance key/value store that is playing an important part in future cloud infrastructure.

There has been a lot of interest in Redis within the Grails community and hot on the heels of the Redis 2.0.0 release we are pleased to announce the availability of GORM for Redis Milestone 1.

What is GORM for Redis? Quite simply it allows Grails developers used to the convenience of features such as dynamic finders, criteria and named queries to take advantage of Redis as their underlying store instead of Hibernate.

Once you have Redis up and running you can install GORM for Redis from the Grails command line:

grails install-plugin redis

If you uninstall the Hibernate plugin then all domain classes in grails-app/domain will become Redis entities instead, otherwise you can specify an individual entity as persistable with Redis using:

static mapWith = "redis"

Once you have your Redis domain classes ready you can continue to use the regular GORM API methods such as save(), delete(), dynamic finders etc.

A lower-level API is also included if you want to build your own indices:

def theSimpsons = Person.findAllByLastName("Simpson")
def list = redis.list("the.simpsons")
theSimpsons.each { list << it.id }

And then query the indices:

def theSimpsons = redis.entities(Person, "the.simpsons")
theSimpsons.each {
    println it.firstName
}

See the full documentation for further information on working with the lower level API and other features. There is also a sample application available to download.

The Redis plugin itself is built on the Inconsequential codebase which is designed as an abstraction above NoSQL stores. We also have in-progress support for other alternative stores such as Cassandra and JCR.

The project is open source and we are interested in collaborating with the NoSQL community to build out similar support as that found in GORM for Redis. There is a GORM TCK which you can run against an implementation to test compatibility which we continue to extend to cover as many features of GORM as possible.

If you're interested in helping us on our quest give us a shout on the Inconsequential mailing list.

This is a milestone release, so we're interested in hearing your feedback as we head closer to milestone 2 and the inevitable final release.

Enjoy!

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

9 responses


  1. Hi Graham,

    I got following exception with grails-1.3.4.

    Redis server is running in default port.

    Error 500:
    Servlet: default
    URI: /example1/
    Exception Message: No value for key [org.hibernate.impl.SessionFactoryImpl@17da438] bound to thread [http-8080-1]
    Caused by: Error executing filter after view error: No value for key [org.hibernate.impl.SessionFactoryImpl@17da438] bound to thread [http-8080-1]. Original error: Could not open Datastore Session; nested exception is java.lang.IllegalStateException: Cannot create RedisSession. No Redis client library found on classpath. Please make sure you have the Jedis library on your classpath
    Class: Unknown
    At Line: [-1]
    Code Snippet:
    Stack Trace

    org.codehaus.groovy.grails.web.mapping.exceptions.UrlMappingException: Error executing filter after view error: No value for key [org.hibernate.impl.SessionFactoryImpl@17da438] bound to thread [http-8080-1]. Original error: Could not open Datastore Session; nested exception is java.lang.IllegalStateException: Cannot create RedisSession. No Redis client library found on classpath. Please make sure you have the Jedis library on your classpath

    at org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.renderViewForUrlMappingInfo(UrlMappingsFilter.java:260)

    at org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.doFilterInternal(UrlMappingsFilter.java:189)

    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.obtainContent(GrailsPageFilter.java:245)

    at org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.doFilter(GrailsPageFilter.java:134)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)


  2. @Vinay Could you provide steps to reproduce? Can't seem to reproduce it myself


  3. Hi Graeme,

    Thanks for reply. Here are steps:

    $uname -a
    Linux 2.6.15-1.2054_FC5smp #1 SMP Tue Mar 14 16:05:46 EST 2006 i686

    1. Installed redis-2.0.1
    2. started redis using ./redis-server command as said in README
    3. Installed grails-1.3.4
    4. created grails-app called example1
    5. Created domain class as follows
    class Person {

    static mapWith = "redis"

    String surName
    String firstName
    String secondName
    String gender
    String dob
    static constraints = {
    }
    }
    6. grails generate-all Person
    7. grails run-app

    After this I get above error in console output of run-app.

    cheers
    Vinay


  4. @Vinay I followed your steps but cannot reproduce. If you can raise a JIRA issue and attach an example that would help. Thanks.


  5. I’m curious, does GORM use the property set when retrieving from the database?

    on a credential domain class I wanting to guard against a password field being set to a non-hashed value… So my initial thinking was to create:

    String password
    void setPassword(String pw) {
    password = getHash(pw,salt)
    }

    but if the hashed password was retrieved from the database wouldn’t it end up going through another cycle of hashing?


  6. @Nox Yes the property getters and setters are used, in general it is better to hash the password outside of the domain


  7. Great share, thanks, I really enjoyed reading your post. Credit Report Com – how to get your free credit report and more


  8. @Graeme,

    Awesome work! Question:

    It is still a bit blur to me where I should draw a line between Hibernate managed entities, and Redis ( NoSQL ) pairs.

    I really liked how seamlessly Redis & Hibernate are implemented in GORM ( person.redis.save() ), and thus it makes me wonder, when I am creating a data model, which entities ( or I guess, "what questions these entities answer to as YES", so they ) should be mapped with Redis ( static mapWith = "redis" )?

    Thank you,
    /Anatoly


  9. Interesting in knowning more about JCR support. We use Jackrabbit 1.x with traditional java code at the moment, would love to bring that stuff into the Grails fold.

9 trackbacks

Leave a Reply