Objectify; an easy way to use Google Datastore

Objectify; an easy way to use Google Datastore
3 votes, 4.33 avg. rating (87% score)

If you had watched Larry Ellison on Oracle-Sun Strategy Update webcast, he was making fun with the word “cloud”, telling thats just a new name for something they had been doing a long time. However same time Oracle’s web site was announcing Oracle Cloud Computing Forum.


Whatever name you call it, clouds are popular and when it comes to clouds Google App Engine is an exciting one. Google’s approach to clouds is not much different from Apple to computers, end users should not be involved to administration and internals, things should be simple,  easy to use but yet still trendy. Google App Engine supports Java, has an eclipse plugin, built on Google’s famous database approach the BigTable, comes with GWT which offers easy web development and a simple, easy to use database supporting JPA/JDO. Still datastore might become a little confusing since it is not a full relational database and also the low level API might become confusing.


This is where objectify takes stage, its The simplest possible *typed* abstraction to the Google App Engine datastore. Objectify comes with a nice wiki, which includes examples, and documentation.


To try objectify first you need to install GAE plugin to eclipse, next you need to download one single jar file. The following would not be adding much to original wiki, but can be used as a summary and shows what i tried on objectify.


I assume you have GAE plugin running on eclipse, if you don’t, visit http://code.google.com/appengine/downloads.html#Download_the_Google_Plugin_for_Eclipse to install the plugin, and while you are there don’t forget to register an account.


Lets start with creating some entities;

@Entity
public class Course {
    @Id //id fields can be long, Long or String. Only Long automatically generates keys when it s null
    Long id;
    String name;
    String branch;
    //add getters and setters
}



Now lets create another entity within relation to first one;

@Entity
public class Student {
    @Id
    Long id;
    String name;
    OKey<Course> course;
    //add getters and setters
}



Since our entities are ready, lets start playing with them. To use our entities on datastore via Objectify, first thing we need to do is to register them. Lets create a service class to perform data operations.

public class SchoolService{
    public SchoolService(){
        ObjectifyService.register(Course.class);
        ObjectifyService.register(Student.class);
    }
    //...



Now lets write some code to test the datastore.

    //...
    public boolean createCourseWithSomeStudents()[
        Objectify objectify=ObjectifyService.begin();

        //create a course
        Course course=new Course();
        course.setName("Beginning GAE Programming");
        course.setBranch("Cloud Platforms");
        objectify.put(course); //persists our entity and sets a generated id

        //Lets create some students for our class
        Student student=new Student();
        student.setName("Murat");
        student.setCourse(new OKey<Course>(Course.class, course.getId());
        objectify.put(student);

        //just add as many to same course...
        return true;
    }



Entities with null assigned Long ids will automatically assigned autogenerated values. If you set this id to your object same put operation would work as an update. Since out datastore has some data, now it is time to query.


First lets write a method to list all our available courses.

    public List<Courses> getCourses(){
        Objectify objectify=ObjectifyService.begin();
        //Create a OQuery for Course class without setting any filter
	OQuery<Course> q = ObjectifyService.createQuery(Course.class);
	List<Course> courses = ofy.prepare(q).asList();
        return courses;
    }



This should return all persisted courses (which should be one if you had just followed the example) as type safe list. Since the course is retrieved we can query for the data related to it. Too add a method which queries the student objects which have relations with the course we retrieved, OQuery provides filter methods.

     public List<Student> getStudentsFromCourse(Course course){
        Objectify objectify=ObjectifyService.begin();
        //get the OKey of the object
        OKey<Course> courseKey = new OKey<Course>(Course.class, course.getId());
        //prepare a query for student
	OQuery<Student> q = ObjectifyService.createQuery(Student.class);
	//add our course key as a search criteria
        q.filter("course", courseKey);
	List<Student> students = objectify.prepare(q).asList();
        return students;
    }



Instead of using asList method there are several other methods such as, asIterable and asSingle (nice if you are sure to hit a single result).


Objectify may not be perfect on all aspects but its quite nice and easy, to use the Google App Engine Datastore which may not be very friendly with JPA/JDO all the time. The current documentation is not bad and quite complete and honestly I find it much clear than GAE’s JPA/JDO documentation.


Also do not forget to check best practices which has nice tips and can save you from pitfalls like not using static initializers for the entites to register themselves to objectifyService.


By the way, for a quick test just extend HttpServlet in our service class and add a doPost method calling the methods you want to test.

Tagged with: ,
Posted in Blog
14 Comments » for Objectify; an easy way to use Google Datastore
  1. tero says:

    Most of the Objectify methodology is not valid in new version. Please see my blog for updated Objectify 2.0.2 examples.

  2. Annoyed says:

    The example code does not work. As well as typos, it has incorrect typing/casting, important chunks missing, and is generally a waste of time.

    I do not understand why people posting examples like these cannot understand we are not all brilliant like them and that it is virtually impossible to second-guess the missing bits when trying to understand new technologies.

    Much better if you keep your brilliance (and errors) to yourself rather than waste people’s time – or post complete, simple, clear code that works.

    • Murat Yener says:

      Let me know what did not work and I ll tell you how to fix it. You didn’t wrote what exactly not working and didn’t also provide a real email. So there is no way I can help you..

  3. David says:

    Just to see that I got this straight:
    If you have an Array of object, which conceptually “belong” to a single parent object, than I should migrate my code this way:
    Public class Parent {
    ArrayList myChildren;
    }

    Public class Parent {
    ArrayList myChildrenKeys;
    }

    Am I correct?
    There is no easier way to migrate such a code?
    Many thanks,
    David

    • Murat Yener says:

      Actually Google Datastore does not like two way relationships. It is always recommended to re(simple)design instead of migration. However your code should be fine. Hmm for an easier way there are some little tricks you can apply, I will prepare an example to show since it would be hard to explain in comments.. ;)

  4. David says:

    Ahhhmm, just to add – I had generics there – but the left/right bracket got wiped by you parser :(

  5. David says:

    Here are some mistakes I’ve noticed in you demo code (using the latest Objectify-2.2 Jar).
    The Student class should begin with:
    import com.googlecode.objectify.Key; //So it won’t import Google default Key
    Line 6, of class Student should be:
    Key course; //That is, replace OKey with Key.

    David

    • Murat Yener says:

      I will check if version 2.2 has any differences. The code should be fine with the verison I used by the time the post was written. Honestly if objectify is breaking backward compability, it would be hard catch up each version :(

Leave a Reply

Your email address will not be published. Required fields are marked *

*


× five = 10

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>