I am going to use the AppEngine Datastore, see:
This is because JDO and JPA are massive and have a steep learning curve They suggest Objectify, TWiG and Slim3. With my first Google I found this cool article by Andreas Borglin, and then lots of links to his article.
Now for some implementation.
First I have to manually register the entities with ObjectifyService. The Best Practices guide advised me to use a DAO object with a static initialiser. so I created a new class in package com.yrdomain.yrproject.server;
import com.googlecode.objectify.ObjectifyService; import com.googlecode.objectify.util.DAOBase; /** * By accessing Objectify through your own DAO class, you can register your * entities in a static initializer and also add domain-specific helper methods. * */ public class DAO extends DAOBase { static { ObjectifyService.register(Gift.class); } /* Your DAO can have your own useful methods public MyThing getOrCreateMyThing(long id) { MyThing found = ofy().find(clazz, id); if (found == null) return new MyThing(id); else return found; }*/ }
I then didn't realise what I was doing and tried to get a reference to the Objectify twice with:
Objectify ofy = ObjectifyService.begin();
in my YrprojectService.java class. However, by extending DAOBase, it already gets this and is accessible by just typing:
dao.ofy().some_method()
If you do it twice it comes up with a NoClassDefFoundError for DAOBase - well it did the first time, when trying to re-create the error to put in the stack-trace for you guys, it worked fine!
This is a first go at the implementation:
public class YrprojectService { DAO dao = new DAO(); @ServiceMethod public Gift createGift() { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String message; if (user == null) { message = "No one is logged in!\nSent from App Engine at " + new Date(); } else { message = "Howdie, " + user.getEmail() +
"!\nSent from createGift on the App Engine at " +
new Date(); } // Simple create Gift porsche = new Gift(); porsche.setGiftName("sports car"); porsche.setGiftLocation(message); dao.ofy().put(porsche); assert porsche.getId() != null; // id was autogenerated return porsche; } //...other CRUD methods... }
It all works fine, as in there are no errors... but can I get my porche back?
Another Error
Objectify FAQs suggest that we turn off the datanucleus byte-code enhancer in Eclipse (go to the Project Properties -> Builders and disable the Enhancer) If you are using the default AppEngine Connected Android Project that is created when you use the Wizard in Eclipse, it uses JDO in the registration of the device. If you subsequently decide to use Objectify, turning off the datanucleus byte-code enhancer will give you the following error:
Failure: Got exception javax.jdo.JDOUserException: Persistent class "Class com.yrdomain.yrproject.server.DeviceInfo does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class. NestedThrowables: org.datanucleus.store.exceptions.NoTableManagedException: Persistent class "Class comyrdomain.yrproject.server.DeviceInfo does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class.
Just turn on the enhancer again, Clean and re-build, the error will go away. You have to remove all the default behaviour and use the Objectify ways. People like to turn off the enhancer because it can take too much time, its easier to just be a bit more specific in what files you want enhanced, remember it's looking for files that will be persisted. Change these options in:
Project Settings > Google > App Engine > ORM
Change the src/ and shared/ folders