RequestFactory ou comment faire du CRUD avec GWT

Par | Classé dans Intermédiaire, Java, Non classé, Web | Le 24/02/2012

1

Historique

Lors de la sortie de la version 2.1 de Google Web Toolkit, une nouvelle API : RequestFactory a fait son apparition. Cette API a été conçue dans le but de simplifier l’interaction et la manipulation de données côté serveur depuis le client (javascript).
Auparavant, les développeurs utilisaient essentiellement GWT-RPC pour les appels de service impliquant des manipulations de données côté serveur.
Etant donné que le code côté client interagit avec du Java côté serveur, GWT-RPC fournit nativement
un mécanisme de sérialisation de données puissant. Cependant, cela ajoutait également un certain nombre de contraintes. Entres autres, le fait que tout objet échangé entre le client et le serveur devait être Serializable (au sens GWT), l’utilisation du pattern DTO qui induisait une redondance du code métier serveur au niveau du client etc.

Différence entre GWT-RPC et RequestFactory

La différence fondamentale entre les deux API réside dans l’orientation. GWT-RPC  est une API orientée service. A la base, elle permet d’invoquer des méthodes distantes d’une couche service pour interagir avec les données.

RequestFactory quant à elle est une API orientée donnée. Elle invoque directement des méthodes exposées non pas sur une couche service, mais sur les entités métiers (selon la terminologie GWT) elles-mêmes. C’est comme si on rendait les données serveurs disponibles au niveau du client. Les méthodes invoquées sont alors les méthodes des objets métiers.

Concepts de base

RequestFactory se base sur la notion de Proxy. Pour effectuer des opérations sur les données côté serveur, il définit un objet proxy qui “représente” cet objet serveur au niveau du client. Ce proxy est en fait une “interface” qui définit l’ensemble des méthodes qu’on voudrait exposer sur l’objet métier lui-même. Pour déclencher l’exécution d’une action sur l’objet côté serveur, il suffit de l’invoquer sur l’interface du proxy et RequestFactory se charge de l’envoi de la requête ainsi que de la sérialisation/déserialisation des données. Il est à noter qu’il utilise un protocole de sérialisation qui lui est propre et qui est différent de GWT-RPC.

Quelques règles à respecter

Le fonctionnement interne de RequestFactory impose quelques contraintes au niveau des classes métiers dont :

L’objet métier doit avoir un constructeur sans argument

la nécéssité d’avoir un champ VERSION dans la classe métier (annoté @Version en JPA). Ce champ permet à RequestFactory de tester si un objet a changé d’état.

Chaque Entité doit également disposer d’une méthode statique permettant de retrouver une instance de l’objet par son identifiant. Par exemple, pour l’entité de type Person, ce sera :

public static findPerson(Long id) {

// retrieving object by Id using EntityManager

}

Cas d’utilisation

Supposons alors qu’on ait un objet métier Personne dans notre application. Les objets de cette classe sont déstinés à être sauvegardés dans une base de données. On les appelle tout naturellement des “Entités” dans RequestFactory. On supposera que la persistance est gérée par Hibernate dans notre application et que tout a déjà été configuré (hibernate.cfg.xml, etc.). Nous avons donc dans notre domaine, le code suivant :

@Entity public class Person {
  @Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Version
@Column(name = "version")
private Integer version;

@Version
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;

  @JoinColumn(name="address_id")
  Address address;

  public Personne() { }  // Getters and setters ...

}

Après avoir défini notre objet métier, on va donc lui adjoindre un “Proxy” qui sera une représentation de cet objet métier côté client. RequestFactory se charge alors de
propager les opérations invoquées sur les proxy vers les entités côté serveur. Il est également important de noter que RequestFactory envoie seulement les différences entre
ce qu’il y a côté serveur et côté client, économisant ainsi la bande passante.

Entity Proxy

Une entity proxy est un proxy qui comme son nom l’indique, représente une entité côté serveur. Pour la définir il suffit de créer une interface qui étend EntityProxy
et d’indiquer la classe métier qu’il représente via l’annotation @ProxyFor.

@ProxyFor(Person.class)
public interface PersonProxy extends EntityProxy {
public Person() { }
// Les méthodes exposées ...
public String getName();
public void setName(String name);
public AddressProxy getAddress();
public void setAddress(AddressProxy address);
// Les méthodes exposées ...
public String getName();
public void setName(String name);
public AddressProxy getAddress();
public void setAddress(AddressProxy address);
}

Les méthodes qu’on a défini dans le proxy sont les méthodes “invocables” sur l’objet métier. Ainsi, si on veut restreindre l’appel à certaines méthodes de l’objet métier
côté serveur, il suffit de ne pas l’indiquer dans le proxy. Ici par exemple, on a omis les modificateurs de Surname, ce qui veut dire qu’on ne pourra pas invoquer la méthode
de modification du prénom depuis le côté client.
Remarquons également que si une Entité A possède une référence vers une autre Entité B, les signatures du proxy AProxy feront référence à des BProxy (dans notre cas, AddressProxy).

Le lien entre le client et le serveur : RequestFactory

Après avoir défini les entités et leurs proxy, on crée maintenant la RequestFactory elle-même. C’est une interface qui comme son nom l’indique va créer les “stubs”
permettant la communication entre le client et le serveur.

public interface ApplicationRequestFactory extends RequestFactory

{

    PersonRequest personRequest();

    AddressRequest addressRequest();
}

PersonRequest et AddressRequest sont nos stubs pour les opérations concernant respectivement les entités Person et Address.

@Service(PersonServiceDAO.class)
public interface PersonneRequestContext extends RequestContext {

Request<List<PersonProxy>> getPersonList();

Request<PersonProxy> findPersonById(Long id);

}

Notons que les stubs utilisent toujours Request comme type de retour, où X est le paramètre de retour de la méthode de service.
Le stub doit nommer via une annotation, la méthode qui implémente les services côté serveur. Ainsi, dans notre exemple on a deux méthodes qu’on peut invoquer côté serveur
pour les entités de la classe Personne : on peut retrouver la liste complète ou encore retrouver une Personne par son identifiant.
On pourrait imaginer une classe service comme la suivante ( j’ai omis volontairement toute la partie de gestion des exceptions liées à la persistance des données pour une raison de lisibilité) :

public class PersonServiceDAO {

public List<PersonProxy> getPersonList()
  {
      List<Person> personList = new ArrayList();
      EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
      try {
          personList = entityManager.createQuery("FROM Person").getResultList();
      } catch (Exception e) {
          e.printStackTrace();
      }
      return personList;
  }

public Personne findPersonById(Long id) {
      EntityManager entityManager = PersistenceManager.getEntityManagerFactory().createEntityManager();
      Person person = null;
      try {
          person = entityManager.find(Person.class, id);
      } catch (Exception e) {
          e.printStackTrace();
      }
      return person;
  }
}

Utiliser RequestFactory

Enfin la dernière étape pour l’exécution de RequestFactory est de l’invoquer depuis le code client. Dans un premier temps, on doit initialiser le bus d’évènement. Une manière de procéder c’est de faire l’initialisation dans le constructeur de la classe dans laquelle on va utiliser RequestFactory.

public class OurClassWindow {
final EventBus eventBus = new SimpleEventBus();
ApplicationRequestFactory requestFactory = GWT.create(ApplicationRequestFactory.class);

public OurClassWindow() {
// Initialize event bus
requestFactory.initialize(eventBus);
}

}

Le mécanisme d’appels dans RequestFactory est très similaire à ce que l’on retrouve dans GWT-RPC. Après avoir retrouvé la requestContext, on invoque la méthode tout en
passant un callback qui sera appelé par RequestFactory au retour de la fonction.

Receiver<List<PersonProxy>> receiver = new Receiver<List<PersonProxy>>(){
@Override 	public void onSuccess(List<PersonProxy> response) {

// Do something with the response from RequestFactory

} };

requestFactory.personRequestContext.getPersonList().fire(receiver);

receiver ici, représente la méthode callback qui sera appelée au retour de la fonction. Comme dans GWT-RPC, il dispose de méthodes onSuccess et onFailure permettant de gérer
les cas de réussite ou d’échecs après l’appel.

Conclusion

Si vous avez déjà codé en GWT, vous savez à quel point il est fastidieux d’écrire des services uniquement pour ramener des données stockées en base  : RequestFactory est une manière élégante simple pour effectuer à moindre coût des appels vers un backend. L’API et la mise en oeuvre sont similaires à ceux de GWT-RPC, il est ainsi très facile de l’appréhender même si on est habitué à GWT-RPC.

pour aller plus loin : https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory

Tomcat 6 – JNDI – password crypté et pool de connexion V7

Par | Classé dans Intermédiaire, Java | Le 02/02/2012

Tags « »

0

Cet article est destiné à ceux qui ont la ‘chance’ d’avoir Tomcat 6 comme serveur pour leurs applications et qui doivent paramétrer le pool de connexions par JNDI.

Voici un petit article issu d’une demande d’un client.

Le client : C’est bien la configuration par JNDI, ça serait mieux si on ne voyait pas le mot de passe en clair :-(

Moi: No problem, everything is possible (enfin je crois) …

Effectivement c’est possible. D’après la documentation, il suffit d’implémenter une classe de type ‘factory’ pour instancier les connexions avec la base de données.

Dans cet article, vous verrez comment crypter facilement un mot de passe ou autre mais aussi comment remplacer le pool de connexion DBCP  par le pool de connexion de Tomcat 7 (plus performant à  mon goût).

Tout ceci se fait en 3 étapes :

  • Codage d’une classe ‘Factory’
  • Configuration de la ressource JNDI
  • Copier les jar dans le répertoire lib de Tomcat

Lire la suite…

Devoxx 2011 – Comparatif de performances des frameworks web Java et plus encore …

Par | Classé dans Débutant, Java | Le 26/01/2012

Tags « »

0

Comparatifs de frameworks web à Devoxx 2011

Cet article a pour but de présenter brièvement la présentation de Stijn Van den Enden, lors du Devoxx 2011, sur les performances brutes de plusieurs frameworks connus et de partager quelques impressions sur ce sujet.

Dans la première partie, il présente la méthodologie de tests ainsi que les outils : le coté test.
Dans la seconde partie, il nous montre les résultats qu’il a obtenu : le coté performance.
Les slides de la présentation sont disponibles ici

En résumé, on y voit la mise en place de la plateforme de tests ainsi que les outils utilisés.

Lire la suite…

J’ai testé le livre : Apache Maven version 2 et 3 par Nicolas De Loof et Arnaud Héritier

Par | Classé dans Java | Le 20/01/2012

Tags « »

3

apache maven cover

La seconde édition de ce livre est sortie il y a déjà quelques mois. Cette nouvelle édition apporte le support de Maven 3 ainsi que des corrections. Je n’avais entendu que du bien de la première version, allons voir ce que donne cette seconde édition !
Depuis quelques années j’utilise 2 ressources principales afin de m’aider dans mon utilisation quotidienne de Maven : la documentation officielle et l’ebook Maven The Definitive Guide dont j’ai toujours une copie dans ma dropbox. Cet ebook a beaucoup de lacunes et n’approfondie par certaines notions Maven qui pourtant le mériteraient, mais je le consulte tout de même régulièrement.

Je me considère comme un bon utilisateur de Maven, mais je suis loin d’être un expert. Cela fait déjà plusieurs années que je le pratique, et je l’utilise quotidiennement dans le cadre de mes missions chez les clients. En lisant le livre Apache maven l’objectif était double :

  • Apprendre de nouvelles choses ou appronfondir certaines notions que j’utilise peu
  • Trouver un complément à Maven The Definitive Guide qui date désormais quelque peu

Lire la suite…

Extreme programming : retour d’expérience

Par | Classé dans Agilité | Le 10/01/2012

Tags « »

0

Intro

SCRUM, Extreme Programming (XP), Lean-management, le développement agile, c’est tendance !

Objectifs : améliorer la réactivité, la qualité et le coût du logiciel avec en ligne de mire la sacro-sainte satisfaction client.

J’ai participé, pendant deux ans, à un projet réalisé « from scratch » en suivant une méthodologie agile : l’Extreme programming. En tant que développeur (sur les deux ans), et « coach XP » (sur les six derniers mois).  L’objectif du projet était le développement d’une application de trading « in-house » dans une banque d’investissement, la taille de l’équipe a varié au cours de ces deux ans de 3 à 7 (manager compris).

Ce post a pour but d’expliquer les pour et les contre de cette méthode tel que je l’ai vécu.

Lire la suite…

Marchés actions: un rallye de noël en 2011?

Par | Classé dans Finance | Le 14/12/2011

Tags « »

1

Traditionnellement, les fêtes de fin d’année sont une période faste pour les marchés actions. Les pessimistes en vacances, les bonus de fin d’année ou la joie de cette période de fête sont autant de raisons discutables avancées pour expliquer ce phénomène. Toujours est-il que pratiquement tous les ans, pendant les deux semaines incluant noël et le nouvel an, le marché progresse mieux que sa moyenne de l’année, dans des volumes restant toutefois assez faibles.

Pour quantifier cet effet sur les dix dernières années, j’ai reconstitué les performances annuelles du CAC 40 depuis 2001 que j’ai comparées aux performances de ce même CAC 40 sur la période allant du 15 décembre au 03 janvier, chaque année. Ces performances sont ensuite annualisées pour faciliter la comparaison. Les résultats sont visibles dans le tableau suivant :

Lire la suite…