50 votes

GWT et Google Cloud Endpoints

Il y a quelques jours, j'ai commencé à développer un backend pour des applications mobiles en utilisant Google App Engine et Points d'extrémité Google Cloud . Ce tutoriel montre comment les points de terminaison sont générés automatiquement, ainsi que la bibliothèque client pour Android.

Nous avons donc notre entité :

@Entity
public class Person implements IsSerializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    private String name;
//...
} 

Et le point final pour cette classe :

@Api(name = "personendpoint")
public class PersonEndpoint {

    @ApiMethod(name = "getPerson")
    public Person getPerson(@Named("id") Long id) {
...

En outre, en utilisant la bibliothèque Android Endpoint générée (qui utilise l'API REST), je voudrais ajouter une interface utilisateur sur le serveur, construite avec Google Web Toolkit (GWT) . Mais comment dois-je manipuler la date du côté du serveur ? Je peux voir différentes approches...

Option A1 : Ajouter un service RPC dans 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;
    }

        //...
}

Mais maintenant, mon PersonServiceImpl y PersonEndpoint font à peu près la même chose. Donc nous n'avons pas suivi SEC :) De plus, cette personne n'est pas autorisée à avoir com.google.appengine.api.datastore.Key donc nous devrions changer nos Entités.

Option A2 : le service appelle la classe de points de terminaison

@Override
public Person insertPerson(Person person) {
    return new PersonEndpoint().insertPerson(person);
}

Devrait fonctionner, mais toujours pas com.google.appengine.api.datastore.Key Tapez dans l'entité et puisque les points de terminaison utilisent CollectionResponse<Person> nous devrions le transformer en un Collection<Person> en cas de listPerson() .

Option B1 : Utilisation de la bibliothèque client Java Endpoint

Nous pourrions séparer le client GWT de notre backend API App Engine et utiliser les bibliothèques de client de point de terminaison générées pour Java. Ainsi, nous appelons l'API REST/Endpoint à partir d'un fichier RemoteServiceServlet . Mais cela n'aboutirait-il pas à deux requêtes, même si le client GWT et les points de terminaison sont sur le même serveur ou même dans le même projet ?

Client GWT --(RPC)--> Serveur GWT --(Requête HTTP)--> Serveur Backend App Engine

Option B2 : Utilisation de la bibliothèque JavaScript Endpoint Client

C'est peut-être la meilleure approche, mais cela aboutirait à une JSNI massive.


Quelle est donc la meilleure pratique ? Je ne trouve pas d'exemple de projet utilisant Google Cloud Endpoints ET GWT dans un seul projet :)

12voto

Le bon vieux dilemme des DTO. Il n'y a pas de bon ou de mauvais, juste ce qui est assez bon pour vous.

Se répéter peut être une bonne chose. Pour l'instant, vous exposez votre modèle de données par le biais de votre point de terminaison, ce qui signifie que toute modification de vos entités aura un impact sur les utilisateurs de votre application mobile. Disons que vous renommez un attribut du côté serveur -> chaque client qui n'a pas mis à jour l'application tombe en panne.

La sécurité est également un problème : si votre entité User a une propriété "email", la sérialiser via GWT RPC rendra l'email de votre utilisateur virtuellement disponible pour tout débogueur javascript.

Est-ce vraiment ce que vous voulez ?

Ne vous méprenez pas, je ne suis pas un fan de ces applications monstres à "couches d'oignons" où 80% du code semble être fait pour transformer des objets en d'autres objets ayant pratiquement les mêmes propriétés.

Je pense que la bonne solution se situe entre les deux : avoir un modèle "client" (DTOs), fait de POJOs sérialisables (pas de datastore, ORM, JAXB, ou autre annotation) que vous exposez à la fois via GWT RPC et Client Endpoints. Votre implémentation de servlet GWT et le serveur Endpoint appelleraient le même service qui transformerait votre modèle client en entités et les traiterait/persisterait.

De cette façon, vous pouvez réutiliser votre code tout en le gardant simple, avoir une interface uniforme à travers vos API et permettre à votre plomberie intérieure d'évoluer sans modifier les interfaces client.

0voto

user2534191 Points 31

Peut-être que je ne comprends pas quelque chose. Mais tout semble (pour moi) être très facile.

  1. GWT (client !) n'est pas sur le serveur. C'est un Javascript compilé exécuté dans le navigateur du client.

  2. Le plugin Google génère un code client Javascript qui appelle le point de terminaison avec le JSON approprié.

  3. Le code ci-dessus peut être appelé à partir de GWT.

Voila ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X