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.
English
Türkçe
Most of the Objectify methodology is not valid in new version. Please see my blog for updated Objectify 2.0.2 examples.
There is nothing unavailable in new version, can you name anything not valid shown here???
Used the latest version with the example above, everything seems ok.
So you tried with 2.0.2 or 2.1?
Hi,I was delveloped a simple web application(Employee details like eid,ename) in JPA.And i deployed in GAE.how can i see my data storage?
You can use the app engine console to view your data.
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.
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..
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
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..
Ahhhmm, just to add – I had generics there – but the left/right bracket got wiped by you parser
Ohh I think I get it, you mean the script clipboard copier is trimming the generics code. Is this right?
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
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