vendredi 27 décembre 2013

Générer l'exposition de vos entités JPA via des services RESTful avec Telosys Tools et Spring Data REST (partie 1)

Avant le tutorial de génération à proprement parlé, faisons un petit tour des technologies utilisées ...

Spring Data REST dans l'écosystème Spring

Spring Data REST fait partie du projet plus global se nommant Spring Data. Ce projet se concentre sur la mise en oeuvre de technologies spécialisées dans l'accès aux données, que les bases de données soit relationnelles (Spring Data JPA ou JDBC) ou NoSQL (Spring Data MongoDB, Spring Data Neo4J ou encore Spring Data Redis). Les principaux projets sont disponibles ici : http://projects.spring.io/spring-data/

Spring Data REST, comme son nom l'indique, s'occupe de l'exposition en REST de vos données. La version actuelle est une 2.0.0.M1, l'API n'est pas encore vraiment stabilisée.
Au niveau architecture, il s'appuie sur Spring MVC.

Quel est l'apport de Data REST par rapport à Spring MVC ?

On pourrait se poser la question tant il est simple de créer un service REST avec Spring MVC. Là, Data REST va encore un peu plus loin en fournissant par défaut une véritable API RESTful HTTP (avec le support d'HATEOAS que nous verrons après). Dès lors qu'une entité dispose d'un repository Spring DATA (qu'il soit JPA, MongoDB, Neo4J ou Gemfire), Spring fournit la sémantique HTTP associées (GET, POST/PUT, DELETE), il est possible ensuite de définir des méthodes de recherche spécifiques à travers les repositories et ses méthodes seront exposées aussi comme par exemple :

Méthode de AuthorRepository

Une fois l'application déployée, nous disposerons de l'API suivante : http://localhost:8080/authors/search/byLastName?lastname=Doe


Cela ne remplace pas pour autant les capacités de Spring MVC. Ce dernier est parfaitement adapté à l'exposition de services plus orienté métier, alors que Data REST lui se "contente" d'exposer les entités de persistance. D'un point de vue architecture, il n'est pas conseillé de designer ses services en se calant sur les opérations CRUD de son SI. Il vaut mieux y réfléchir en pensant acte métier. Les deux sont donc complémentaires.

HATEOAS

Je crois que toutes les personnes qui ont vu ce nom ont eu la même réaction ! "C'est quoi ce nom ?"
Cet acronyme improbable signifie Hypermedia As The Engine Of Application State. C'est une contrainte d'architecture pour la mise en oeuvre de services RESTful. Il repose sur un principe simple : Chaque ressource REST exposée est accessible via un lien hypertext. Dès lors qu'une ressource est liée à une autre, la référence à cette dernière sera son lien hypertext, que le client devra parcourir pour accéder aux informations.

Le support des liens dans les services RESTful correspond au niveau 3 de l'échelle de maturité de Richarson. Cette échelle permet de mesurer votre API face au type d'architecture REST :


Je vous recommande cet article sur le sujet :
http://martinfowler.com/articles/richardsonMaturityModel.html

Un petit exemple en Json avec un "book":


Le flux Json nous donne l'url à suivre pour obtenir les informations liées.

C'est un cadre intéressant qui structure les flux REST. Il reste cependant, pour l'instant, une contrainte à son adoption, c'est la compatibilité des clients. Il faut nécessairement que le les clients soit "HATEOAS Friendly"

Spring intégre HATEOAS et permet via son API de gérer aisément les différents liens pour les parcourir ou les créer : http://projects.spring.io/spring-hateoas/
La version actuelle est la 0.7.0. Tout n'est pas encore sec mais je pense que cela ne va pas tarder à devenir une référence ... pourquoi attendre la première release pour se pencher dessus ?

Spring Data REST supporte HATEOAS et expose, par défaut, vos API avec. C'est que nous allons utiliser.

L'application Rest-Shell


Afin de faciliter le parcours et l'utilisation d'une API RESTful HATEOAS, Spring fournit une application en ligne de commande nommée "Rest-Shell". Elle permet l'utilisation de requêtes HTTP sans avoir à utiliser l'url complète d'une ressource et dispose de quelques commandes assez pratiques dont voici un aperçu.
La documentation se trouve ici : https://github.com/spring-projects/rest-shell, je vous recommande de l'installer.


Imaginons ici qu'une base de données de type bookstore soit exposée via des services RESTful. L'url par défaut est localhost:8080.


Je lance la rest-shell et j'obtiens l'écran suivant :



Pour connaitre l'ensemble des ressources exposées, HATEOAS fournit la liste attendue dès qu'une requête de type GET est adressée à la racine. L'application rest-shell permet d'explorer l'API grâce à la commande discover :


Vous pouvez alors récupérer l'ensemble des books en tapant un get books par exemple. Ou alors vous pouvez avoir envie de parcourir les ressources disponibles sous books. Pour cela il suffit d'utiliser la commande follow  <ressource> et de faire un discover comme ci-dessous : 



Vous voulez récupérer les données du Book 1 ? Ok tapons : get 1 :

Remarquez la structure en lien apportées par HATEOAS
Nous ne ferons pas le tour exhaustif des commandes mais finissons par les principales (POST, DELETE et l'utilisation de paramètres) :



L'utilisation du POST

L'utilisation du DELETE

L'utilisation de paramètres 
A noter que cette application n'est pas obligatoire, votre navigateur suffit mais le parcours des liens peut s'avérer fastidieux.




Spring DATA JPA


Bon assez parlé de REST pour l'instant. Nous avons vu que Spring DATA REST s'appuie sur des repositories pour pouvoir les exposer via des services RESTful. Nous allons ici parler des repositories pour JPA.


Spring fournit une API que je trouve très efficace et productive pour mettre en oeuvre la DAL de votre projet. Cette API s'appuie sur l’utilisation d'interfaces (les repositories) dont le developpeur n'a pas besoin de fournir d'implémentation. Par défaut, les principales méthodes de CRUD sont fournies : findAll, findOne, delete, deleteAll, save...



Il est ensuite possible de définir d'autres méthodes, toujours dans cette interface et toujours sans avoir à fournir d'implémentation et utilisant deux façons de procéder, soit :


  • Par convention de nommage sur la méthode
  • Par l'utilisation de l'annotation @Query
La convention de nommage permet déjà de faire quelque requêtes intéressantes en utilisant les mots clés suivants :


Voici quelque exemple pour le DAO d'une classe Book


Le gain en ligne de code est tout de même appréciable.

Telosys Tools


Telosys Tools est un plug-in Eclipse de génération de code reposant sur un mécanisme de template permettant d'être indépendant  de la technologie générée. Il est simple d'utilisation et se branche directement sur n'importe quelle base de données relationnelle. Il est "database first".
Les templates actuellement disponibles vous permettent par exemple de partir de votre base pour générer vos couches d'accès aux données avec JPA/Hibernate par exemple, ou allez plus loin en disposant d'un starter kit pour Spring MVC ou encore AngularJS (Les écrans sont aussi générés).

Il est aussi possible de générer d'autres langages, de la documentation et de créer vos propres templates rapidement !

N'hésitez pas à consulter le site pour plus informations :
 https://sites.google.com/site/telosystools/ 
et à le supporter :-) 
http://marketplace.eclipse.org/content/telosys-tools

Il peut s’avérer être un atout majeur de productivité sur vos projets.


Dans la deuxième partie de l'article , nous verrons comment générer, avec Telosys Tools, une API complète (repositories, recherche avancées, validations), en quelques minutes, en partant de votre base relationnelle et en mettant en oeuvre les composants décrits dans cet article.

Pour la deuxième partie c'est par ici.


mercredi 18 décembre 2013

Couchbase : Comment automatiser la gestion de vos vues (version, creation, update, controle de source ...)


L'interface web sur serveur Couchbase est vraiment d'une grande qualité de part sa simplicité d'utilisation et des fonctionnalités qu'elle procure. C'est un point très différenciant vis à vis de la concurrence.

Si vous lisez cet article c'est que vous vous êtes posé la même question que moi : Créer des vues via l'interface est vraiment efficace mais comment puis-je intégrer cette étape dans mon environnement de développement ? Je travaille en équipe, j'ai donc besoin que les scripts soient sous un VCS et idéalement que la mise à jour des vues sur le serveur soit automatisée.

Je vous propose une solution que j'ai mise en oeuvre avec l'API pour Java.

Les sources sont disponibles sur Github : https://github.com/bewilcox/Couchbase-manage-views

L'organisation des vues

Le vues étant des scripts map/reduce écrits en javascript, mon projet va contenir un ensemble de fichier .js
Plutôt que de faire un fichier par vue, je suis parti du principe de regrouper thématiquement plusieurs vues dans un seul fichier. Par exemple, toutes les vues portant sur un type de document ("Tous les docs Author", "les docs Author par leur nom", "les docs Author par statut etc.)

L'ensemble de ces scripts sous placés sous src\main\resources\couchbase\views :



La structure des fichiers de scripts

Les fichiers js sont structurés pour permettre d'extraire facilement les vues. J'utilise des tags sous forme de commentaires pour cela. 
Chaque vue commence par le commentaire : //startview <nom de la vue>
Et se termine par le commentaire : //endview

Voici un exemple de ficher :

La méthode présentée plus bas se chargera, pour chaque bloc, de créer la vue sur le serveur.


Mise à jour des vues sur le serveur

Voici un extrait du code me permettant de scanner cette arborescence et mettre à jour les vues sur le serveur :


La gestion de la version

La méthode initDatabase() vérifie la version de la base pour déclencher ou non la mise des vues sur le serveur. Il faut savoir que cette mise à jour procède à un annule et remplace ce qui a pour conséquence la réindexation de tous les documents.
Ce fonctionnement est perfectible, il serait plus optimal de gérér une version par vue plutôt qu'une version globale.

La dernière version est celle présente dans le fichier couchbase.properties
couchbase.database.version = 1.0.1 

La version courante de la base est donnée par le document DB_VERSION créé par l'API.
{"major":1,"minor":0,"rev:1} 


Les améliorations possibles

C'est un première ébauche et quelques améliorations sont possibles :
  • Actuellement, toutes les vues ne sont pas créées dans le même document design. Les vues dont le nom commence par "all" sont dans un document design et les autres dans un autre. Il serait mieux par exemple de modifier l'arborescence des fichiers js et de créer un répertoire par document design avec les vues en dessous.
  • La gestion de la version serait plus optimale si elle était au niveau d'une vue et non globale.
  • Actuellement, la création d'une vue par l'API la créée directement avec le statut "Production". Il pourrait être intéressant de pouvoir spécifier le statut cible en fonction de vos contraintes projet. 



Pour finir, un petit mot sur N1QL

Il est répandu de penser que les vues s'apparentent quelque part aux procédures stockées d'une base relationnelle. C'est une erreur. Les vues sont des scripts d'indexation et non des scripts de requêtage. Le serveur Couchbase parse ces scripts ce qui lui permet, pour chaque document, de mettre à jour son arbre d'index. La partie requêtage à proprement parlé est réalisée par l'API client en s'appuyant sur ces vues.

Ce mécanisme fait que le requêtage d'une base Couchbase est moins trivial que sur les autres bases NoSQL et peut s'avérer même complexe dans le cas de requêtes avancées.

C'est ce défaut que sont en train de combler les équipes de Couchbase en créant le langage N1QL (prononcer "niquel"). Il s'apparente fortement à la syntaxe SQL et permettra d'interroger facilement les documents. Nous connaissons tous la syntaxe SQL ce qui va limiter grandement la courbe d'apprentissage.

A la rédaction de cet article, N1QL est en Developer Review 2. Vous pouvez d'ores et déjà l'utiliser pour tester :