Création d'une application offline avec Couchbase Mobile

Introduction

Au travers de cet article, je souhaite vous présenter une solution packagée pour la réplication / synchronisation de données sur des terminaux distants.

Cette introduction se base sur la suite Couchbase et combine les solutions Serveur et Mobile de l'éditeur.

Ces solutions permettent un gain de temps significatif dans le développement et le déploiement d'applications synchronisées.

Nous allons le voir via la mise en place d'un cas d'usage couvrant l'alimentation d'un cluster Couchbase Server et la synchronisation de données sur une application mobile.

Cas d'usages possibles

Les cas d'usages de ce type de solution sont multiples. C'est ce qui en fait à mon sens l'intérêt principal.

Une architecture utilisant ces solutions peut permettre de couvrir les besoins suivants :

  • Application de secours ;
  • Application décentralisée ;
  • Application mobile ;
  • Application hors ligne.

Pourquoi Couchbase ?

Couchbase nous apporte une solution complète permettant la synchronisation des données sur machines distantes.

La partie Couchbase Serveur est une base de données avec les caractéristiques suivantes :

  • NoSQL de type document ;
  • Distribuée ;
  • Scalable.

La partie Couchbase Mobile permet, quant à elle :

  • La réplication de données sur des devices distants ;
  • Le routage des données ;
  • Une base de données embarquée de type NoSQL orientée documents.

Ces deux solutions sont disponibles en version :

  • Community : Open Source, avec restriction de certaines fonctionnalités et sans support ;
  • Enterprise : propriétaire, payante avec support.

Dans l'exemple qui va être proposé nous allons utiliser la version Community.

L’application article

Afin d’illustrer la mise en place des différents composants, j’ai réalisé une application. Cette application permet la saisie d’articles et leur réplication sur des terminaux mobiles.
Article---Application

L'application se décompose en deux répositories, qui permettent de lancer l'ensemble de la solution :

  • L'application partagée : le serveur Web, Couchbase Server, Couchbase Gateway (cf. README pour le lancement) ;
  • L'application mobile android se connectant à la Gateway.

La première partie disponible sous GitLab de cette application, permet :

  • La saisie d’articles via une interface web ;
  • Le stockage des données dans le cluster Couchbase ;
  • L'analyse des données par la Gateway en fonction du contenu des documents.

La seconde partie disponible sous GitLab est composée d’une application mobile :

  • L’application mobile se connecte à la Gateway afin de récupérer et stocker en local les données triées par la Gateway.

L’architecture

Article---Cr-ation-d-une-application-offline-avec-Couchbase-Mobile---1--2

Couchbase Server

La partie Couchbase Server et l'application liée servent à créer des articles et à les sauvegarder dans la base de données NoSQL.

Déploiement serveur

Le cluster Couchbase s’installe facilement et l’automatisation de son déploiement est assez simple.

Le lancement de 3 commandes permet de charger une instance de Couchbase

couchbase-cli cluster-init
couchbase-cli bucket-create
couchbase-cli user-manage

Ces trois commandes sont visibles dans le fichier docker-compose.yml de l'application.

Génération de l'application

L’application réalisée se base sur Spring Boot et à été générée via le site https://start.spring.io en utilisant les options :

  • Couchbase ;
  • Web.

La mise en place de cette application n’étant pas le but principal de cet article, nous allons présenter succinctement la couche d’accès aux données. Pour plus d’informations, vous pouvez consulter le site de Spring Data Couchbase.

Configuration accès Couchbase

Nous avons utilisé un bean de configuration afin de configurer le cluster.

@Configuration
@EnableCouchbaseRepositories(basePackages = {"com.ippon.article"})
public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {

Une configuration spécifique est nécessaire afin d’utiliser la solution Couchbase Mobile.

Cette configuration permet de modifier le mot clef utilisé par Spring Data Couchbase pour connaître le type d’objet stocké (utilisation de l’attribut javaClass à la place de _class pour stocker le type dans le document).

public String typeKey() {
  return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE;
}

Repository

Nous avons ensuite créé un repository afin d’accéder à nos données et en sauvegarder de nouvelles.

@Repository
public interface ArticleRepository extends CouchbaseRepository<Article, String> {
}

Lancement de l’application

L'application complète disponible sur GitLab se lance en utilisant docker-compose up et ./mvnw spring-boot run (cf. README).

Couchbase Mobile (Gateway / Couchbase Lite)

La solution Couchbase Mobile comporte deux composants majeurs :

  • La Gateway qui scrute et organise les documents stockés dans le cluster Couchbase dans des channel ;
  • Couchbase Lite qui permet de se connecter à la Gateway pour récupérer les documents et les stocker en local.

Gateway

La gateway est le composant qui permet de faire passerelle entre le monde serveur et le monde mobile. Cette partie s’occupe de la connexion au cluster, de l’analyse des documents modifiés et de leur dépôt dans des channel afin de pouvoir être récupérés par des utilisateurs.

Lancement et configuration

La configuration de la gateway se fait au travers d’un fichier JSON comportant :

  • Les données de connexion au serveur ;
  • Une fonction JavaScript permettant de router les données en channel et gérer les autorisations.

Réplication des données (channel et utilisateurs)

Channel

La réplication des données se fait en utilisant un mécanisme nommé channel qui permet de rassembler les documents. Un document pouvant se trouver dans plusieurs channel.

Dans notre application, pour chaque document traité par la Gateway, s’il possède un attribut tag, il sera placé dans le channel correspondant.

"sync": `
  function(doc, oldDoc) {
      if (doc.tag !== undefined) {
          channel("CHANNEL_" + doc.tag);
      }
  }
`

Utilisateur

Une fois les données positionnées dans ces channel l’étape suivante est de définir des utilisateurs pouvant y accéder.

Les différents channels accédés par l’utilisateur sont définis lors de la création de l’utilisateur.

Les utilisateurs peuvent être créés sur la gateway :

  • Via le fichier de configuration ;
  • En utilisant l’API REST via curl par exemple.

Dans l’application article, les données étant distinctes par client, chaque utilisateur aura accès à un seul channel qui correspond au tag auquel il s'abonne.

"users": {
  "test": {"password": "agile", "admin_channels": ["CHANNEL_agile"]}
},

Couchbase Lite

Une fois les documents organisés en channel et les utilisateurs créés pour y accéder, il reste à créer l’application qui récupérera les données et qui les synchronisera.

La solution Couchbase mobile propose, pour répondre à cette problématique, d’embarquer une base de données nommée Couchbase Lite. Cette base de données embarquée, stockée sur disque, permet un stockage de type NoSQL orienté document. Elle dispose de fonctionnalités d’accès par Clefs, Vues Map / Reduce et N1QL (depuis la version 2.0).

Couchbase Lite est une adaptation de la base de données SQLite par Couchbase.

Elle permet de se connecter à la Gateway afin de redescendre et/ou remonter des données. La réplication se fait au travers d'un protocole présenté sur ce post de blog.

Les plateformes supportées

Couchbase Lite est disponible sur plusieurs plateformes et langages :

  • Android ;
  • IOS ;
  • Pure Java applications ;
  • C#.

Dans la version 2.0 de Couchbase Mobile, la version Pure Java n’est pas encore supportée.

Initialisation de la base

L’initialisation et la configuration de la base de données Couchbase Lite se fait assez simplement :

DatabaseConfiguration config = new DatabaseConfiguration(androidContext);
database = new Database("localdb", config);

Cette initialisation permettra l’ouverture (ou la création) de la base de données stockée sur le disque.

Réplication (Pull / Push)

Couchbase Lite introduit les notions de réplication de type Pull pour la redescente d’informations et de type Push pour la remontée.

Afin de configurer la réplication, il faut spécifier :

  • L’URL d’une Gateway ;
  • Un couple utilisateur / mot de passe configuré sur la Gateway ;
  • Le type de réplication (Pull ou Push).

À la suite de cela, la réplication se fait de manière transparente soit :

  • Une unique fois ;
  • En continu.

Dans notre exemple nous avons choisi de réaliser la redescente d’information en continu. La remontée d’information n’est pas activée.

// Create replicators to pull changes.
Endpoint targetEndpoint = new URLEndpoint(new URI(gatewayUrl));
ReplicatorConfiguration replConfig = new ReplicatorConfiguration(database, targetEndpoint);

replConfig.setReplicatorType(ReplicatorConfiguration.ReplicatorType.PULL);

// Add authentication.
replConfig.setAuthenticator(new BasicAuthenticator(gatewayUser, gatewayPwd));
replConfig.setContinuous(true);

// Create replicator.
replicator = new Replicator(replConfig);

// Start replication.
replicator.start();

Accès aux données

Le SDK de la nouvelle version de la solution mobile nous permet l’utilisation d’expressions proches de ce que l’on pourrait retrouver dans les Criteria Hibernate.

Query query = QueryBuilder.select(SelectResult.property("content"))
      .from(DataSource.database(database))
      .where(Expression.property("javaClass").equalTo(Expression.string(javaClass)));

Ces expressions intégrées depuis la version 2.0 viennent simplifier l’accès qui était auparavant possible exclusivement par clefs ou bien par vues MapReduce.

Notions avancées

Filtres de réplication

Les données répliquées peuvent être filtrées par Couchbase Lite.

Cela peut être utile lorsque l’application mobile peut réaliser des insertions en base et que l’on ne souhaite pas remonter certains types de documents.

Gestion des conflits

Un élément structurant dans le design de l’application est la gestion des conflits.

Couchbase Mobile permettant de travailler en mode déconnecté. Le choix peut être fait de vouloir modifier les documents répliqués pour les remonter au serveur.

Le document pourra donc être modifié :

  • Directement sur le cluster Couchbase (via l’application liée au cluster) ;
  • Sur plusieurs Couchbase Lite (applications avec les données synchronisées).

Dans ce cas, lorsque la prochaine synchronisation aura lieu, il y aura un conflit à gérer car les documents pourront être différents.

Lors de la détection d’un conflit, deux révisions du document sont créées et la mise en place de détection et de résolution de conflit est alors à faire.

Le présent article de blog illustre très bien les principes sous-jacents et guide dans la mise en place de résolution.

Suivant le cas d'usage si le besoin de modification se présente,
une stratégie possible peut être l'utilisation de l'Event Sourcing. Chaque modification se caractérisant par la création d'un nouvel évènement. Cela évite les conflits par document et permet la mise en place d'une architecture orientée évènements.

Démonstration

Le workflow de synchronisation se synthétise en 4 étapes majeures illustrées par les deux projets présents sous GitLab :

  1. Ajout de l’article ;
  2. Présence en base ;
  3. Traitement par la Gateway ;
  4. Synchronisation.

Article---Cr-ation-d-une-application-offline-avec-Couchbase-Mobile---3-

Aller plus loin

Le cas de création d’un mode déconnecté est généralement assez complexe. On voit, au travers du cas exposé, que l’utilisation de la solution proposée par Couchbase permet de s'abstraire d’une partie des problématiques.

Un des aspects intéressant de la suite est également la présence d’un driver réactif pour la partie Couchbase Server, cela permet l'utilisation du paradigme de programmation réactive (désormais supporté par Spring 5). Cela permet d’assurer un aspect événementiel de bout en bout, en partant du terminal mobile jusqu'à l’application exploitant les données dans le cluster.

Je vous invite à jeter un œil à cette solution qui pourrait vous faire gagner du temps et vous surprendre :).