A few days ago I've started developing a Backend for Mobile Applications using Google App Engine and Google Cloud Endpoints. This tutorial shows how the endpoints are getting generated automatically, as well as the client library for Android.
So we have our Entity:
@Entity
public class Person implements IsSerializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String name;
//...
}
And the endpoint for this class:
@Api(name = "personendpoint")
public class PersonEndpoint {
@ApiMethod(name = "getPerson")
public Person getPerson(@Named("id") Long id) {
...
Besides, using the generated Android Endpoint Library (that uses the REST API) I would like to add a User Interface on the Server, build with Google Web Toolkit (GWT). But how should I manipulate the date on Server Side? I can see different approaches...
Option A1: Adding an RPC Service in GWT
public interface PersonServiceAsync {
void insertPerson(Person person, AsyncCallback<Person> callback);
}
@RemoteServiceRelativePath("api")
public interface PersonService extends RemoteService {
public Person insertPerson(Person person);
}
public class PersonServiceImpl extends RemoteServiceServlet implements PersonService{
public Person insertPerson(Person person) {
EntityManager mgr = getEntityManager();
try {
if (containsPerson(person)) {
throw new EntityExistsException("Object already exists");
}
mgr.persist(person);
} finally {
mgr.close();
}
return person;
}
//...
}
But now my PersonServiceImpl
and PersonEndpoint
do roughly the same. So we didn't follow DRY :) Besides, that Person is not allowed to have com.google.appengine.api.datastore.Key
so we would have to change our Entities.
Option A2: Service calls endpoint class
@Override
public Person insertPerson(Person person) {
return new PersonEndpoint().insertPerson(person);
}
Should work , but still no com.google.appengine.api.datastore.Key
Type in the Entity and since Endpoints are using CollectionResponse<Person>
we would have to transform this into an Collection<Person>
in case of listPerson()
.
Option B1: Using the Java Endpoint Client Library
We could split the GWT Client from our App Engine API Backend and use the generated Endpoint Client Libraries for Java. So we call the REST/Endpoint-API from within a RemoteServiceServlet
. But wouldn't this end up in two Requests, even if the GWT client and Endpoints are on the same server or even in the same project?
GWT Client --(RPC)--> GWT Server --(HTTP Request)--> App Engine Backend Server
Option B2: Using the JavaScript Endpoint Client Library
Might be the best approach but would end up in massive JSNI.
So what's best practice? I can't find any example projects using Google Cloud Endpoints AND GWT in one project :)