Guide de LinkRest

Guide de LinkRest

1. Vue d'ensemble

LinkRest est un framework open-source pour la création de services Web REST basés sur les données. Il repose surJAX-RS etApache Cayenne ORM et utilise un protocole de message basé sur HTTP / JSON.

Fondamentalement, ce cadre est conçu pour fournir un moyen facile d’exposer notre magasin de données sur le Web.

Dans les sections suivantes, nous allons voir comment nous pouvons créer un service Web REST pour accéder à un modèle de données à l'aide deLinkRest.

2. Dépendances deMaven

Pour commencer à travailler avec la bibliothèque, nous devons d'abord ajouter la dépendancelink-rest:


    com.nhl.link.rest
    link-rest
    2.9

Cela apporte également l'artefactcayenne-server.

De plus, nous utiliseronsJersey comme implémentation deJAX-RS, nous devons donc ajouter la dépendancejersey-container-servlet, ainsi quejersey-media-moxy pour sérialiser les réponses JSON:


    org.glassfish.jersey.containers
    jersey-container-servlet
    2.25.1


    org.glassfish.jersey.media
    jersey-media-moxy
    2.25.1

Pour notre exemple, nous allons travailler avec une base de donnéesH2 en mémoire car elle est plus simple à configurer; par conséquent, nous ajouterons égalementh2:


    com.h2database
    h2
    1.4.196

Modèle de données3. Cayenne

Le modèle de données avec lequel nous allons travailler contient une entitéDepartment et une entitéEmployee qui représentent une relation un-à-plusieurs:

image

Comme mentionné,LinkRest works with data objects generated using Apache Cayenne ORM. Travailler avecCayenne n'est pas le sujet principal de cet article, donc pour plus d'informations, consultez lesApache Cayenne documentation.

Nous allons enregistrer le projetCayenne dans un fichiercayenne-linkrest-project.xml.

Après avoir exécuté lescayenne-maven-plugin, cela générera deux classes abstraitesDepartment_ and Employee_ - qui étendront la classeCayenneDataObject, ainsi que deux classes concrètes qui en dérivent,Department etEmployee.

Ces dernières classes sont celles que nous pouvons personnaliser et utiliser avecLinkRest.

4. Démarrage de l'applicationLinkRest

Dans la section suivante, nous allons écrire et tester des points de terminaison REST, donc pour pouvoir les exécuter, nous devons configurer notre environnement d'exécution.

Puisque nous utilisonsJersey comme implémentation deJAX-RS, ajoutons une classe qui étendResourceConfig et spécifie le package qui contiendra les classes dans lesquelles nous définissons les points de terminaison REST:

@ApplicationPath("/linkrest")
public class LinkRestApplication extends ResourceConfig {

    public LinkRestApplication() {
        packages("com.example.linkrest.apis");

        // load linkrest runtime
    }
}

Dans le même constructeur, nous devons construire et enregistrer lesLinkRestRuntime dans le conteneurJersey. Cette classe est basée sur le premier chargement desCayenneRuntime:

ServerRuntime cayenneRuntime = ServerRuntime.builder()
  .addConfig("cayenne-linkrest-project.xml")
  .build();
LinkRestRuntime lrRuntime = LinkRestBuilder.build(cayenneRuntime);
super.register(lrRuntime);

Enfin, nous devons ajouter la classe auxweb.xml:


    linkrest
    org.glassfish.jersey.servlet.ServletContainer
        
            javax.ws.rs.Application
            com.example.LinkRestApplication
        
    1


    linkrest
    /*

5. Ressources REST

Maintenant que nous avons nos classes modèles, nous pouvons commencer à écrire des ressources REST.

LesREST endpoints are created using standard JAX-RS annotations, while the response is built using the LinkRest class.

Notre exemple consistera à écrire une série de points de terminaison CRUD qui accèdent à l'URL de/departmenten utilisant différentes méthodes HTTP.

Commençons par créer la classeDepartmentResource, qui est mappée sur/department:

@Path("department")
@Produces(MediaType.APPLICATION_JSON)
public class DepartmentResource {

    @Context
    private Configuration config;

    // ...
}

La classeLinkRest a besoin d'une instance de la classeJAX-RS Configuration, qui est injectée à l'aide de l'annotationContext, également fournie parJAX-RS.

Ensuite, continuons à écrire chacun des points de terminaison qui accèdent aux objetsDepartment.

5.1. Création d'entités à l'aide de POST

Pour créer une entité, la classeLinkRest fournit la méthodecreate() qui renvoie un objetUpdateBuilder:

@POST
public SimpleResponse create(String data) {
    return LinkRest.create(Department.class, config).sync(data);
}

Le paramètre data peut être un objet JSON unique représentant unDepartment ou un tableau d'objets. Ce paramètre est envoyé auxUpdateBuilder en utilisant la méthodesync() pour créer un ou plusieurs objets et insérer les enregistrements dans la base de données, après quoi la méthode renvoie unSimpleResponse.

La bibliothèque définit 3 formats supplémentaires pour les réponses:

  • DataResponse<T> - une réponse qui représente une collection deT

  • MetadataResponse<T> - contient des informations de métadonnées sur le type

  • SimpleResponse - un objet qui contient deux attributssuccess etmessage

Ensuite, utilisonscurl pour ajouter un enregistrementDepartment à la base de données:

curl -i -X POST -H "Content-Type:application/json"
  -d "{"name":"IT"}" http://localhost:8080/linkrest/department

En conséquence, la commande renvoie l'état201 Created et un attributsuccess:

{"success":true}

Nous pouvons également créer plusieurs objets en envoyant un tableau JSON:

curl -i -X POST -H "Content-Type:application/json"
  -d "[{"name":"HR"},{"name":"Marketing"}]"
  http://localhost:8080/linkrest/department

5.2. Lecture d'entités à l'aide de GET

La méthode principale pour interroger les objets est la méthodeselect() de la classeLinkRest. Cela renvoie un objetSelectBuilder que nous pouvons utiliser pour enchaîner des méthodes de requête ou de filtrage supplémentaires.

Créons un point de terminaison dans la classeDepartmentResource qui renvoie tous les objetsDepartment de la base de données:

@GET
public DataResponse getAll(@Context UriInfo uriInfo) {
    return LinkRest.select(Department.class, config).uri(uriInfo).get();
}

L'appeluri() définit les informations de requête pour lesSelectBuilder, tandis que get () renvoie une collection deDepartments encapsulée comme un objetDataResponse<Department>.

Jetons un coup d'œil aux services que nous avons ajoutés avant d'utiliser ce point de terminaison:

curl -i -X GET http://localhost:8080/linkrest/department

La réponse prend la forme d'un objet JSON avec un tableaudata et une propriététotal:

{"data":[
  {"id":200,"name":"IT"},
  {"id":201,"name":"Marketing"},
  {"id":202,"name":"HR"}
],
"total":3}

Alternativement, pour récupérer une collection d'objets, nous pouvons également récupérer un seul objet en utilisant lesgetOne() au lieu deget().

Ajoutons un point de terminaison mappé à/department/{departmentId} qui renvoie un objet avec un identifiant donné. Pour cela, nous filtrerons les enregistrements à l'aide de la méthodebyId():

@GET
@Path("{id}")
public DataResponse getOne(@PathParam("id") int id,
  @Context UriInfo uriInfo) {
    return LinkRest.select(Department.class, config)
      .byId(id).uri(uriInfo).getOne();
}

Ensuite, nous pouvons envoyer une demande GET à cette URL:

curl -i -X GET http://localhost:8080/linkrest/department/200

Le résultat est un tableaudata avec un élément:

{"data":[{"id":200,"name":"IT"}],"total":1}

5.3. Mise à jour d'entités à l'aide de PUT

Pour mettre à jour les enregistrements, nous pouvons utiliser la méthodeupdate() oucreateOrUpdate(). Ce dernier mettra à jour les enregistrements s'ils existent ou les créera s'ils ne le font pas:

@PUT
public SimpleResponse createOrUpdate(String data) {
    return LinkRest.createOrUpdate(Department.class, config).sync(data);
}

Comme dans les sections précédentes, l'argumentdata peut être un seul objet ou un tableau d'objets.

Mettons à jour l'un des départements précédemment ajoutés:

curl -i -X PUT -H "Content-Type:application/json"
  -d "{"id":202,"name":"Human Resources"}"
  http://localhost:8080/linkrest/department

Cela renvoie un objet JSON avec un message de réussite ou d'erreur. Ensuite, nous pouvons vérifier si le nom du département portant l'ID 202 a été modifié:

curl -i -X GET http://localhost:8080/linkrest/department/202

Effectivement, cette commande renvoie l'objet avec le nouveau nom:

{"data":[
  {"id":202,"name":"Human Resources"}
],
"total":1}

5.4. Suppression d'entités à l'aide deDELETE

Et, pour supprimer un objet, nous pouvons appeler la méthodedelete() qui crée unDeleteBuilder, puis spécifier la clé primaire de l'objet que nous voulons supprimer en utilisant la méthodeid():

@DELETE
@Path("{id}")
public SimpleResponse delete(@PathParam("id") int id) {
    return LinkRest.delete(Department.class, config).id(id).delete();
}

Ensuite, nous pouvons appeler ce point de terminaison en utilisantcurl:

curl -i -X DELETE http://localhost:8080/linkrest/department/202

5.5. Utilisation des relations entre les entités

LinkRest contient également des méthodes qui facilitent le travail avec les relations entre les objets.

CommeDepartment a une relation un-à-plusieurs avecEmployee, ajoutons un point de terminaison/department/{departmentId}/employees qui accède à une classeEmployeeSubResource:

@Path("{id}/employees")
public EmployeeSubResource getEmployees(
  @PathParam("id") int id, @Context UriInfo uriInfo) {
    return new EmployeeSubResource(id);
}

La classeEmployeeSubResource correspond à un département, donc elle aura un constructeur qui définit un identifiant de département, ainsi que l'instanceConfiguration:

@Produces(MediaType.APPLICATION_JSON)
public class EmployeeSubResource {
    private Configuration config;

    private int departmentId;

    public EmployeeSubResource(int departmentId, Configuration configuration) {
        this.departmentId = departmentId;
        this.config = config;
    }

    public EmployeeSubResource() {
    }
}

Notez qu'un constructeur par défaut est nécessaire pour que l'objet soit sérialisé en tant qu'objet JSON.

Ensuite, définissons un point de terminaison qui récupère tous les employés d'un service:

@GET
public DataResponse getAll(@Context UriInfo uriInfo) {
    return LinkRest.select(Employee.class, config)
      .toManyParent(Department.class, departmentId, Department.EMPLOYEES)
      .uri(uriInfo).get();
}

Dans cet exemple, nous avons utilisé la méthodetoManyParent() desSelectBuilder pour interroger uniquement les objets avec un parent donné.

Les points de terminaison pour les méthodes POST, PUT, DELETE peuvent être créés de manière similaire.

Pour ajouter des employés à un service, nous pouvons appeler le point de terminaisondepartments/{departmentId}/employees avec la méthode POST:

curl -i -X POST -H "Content-Type:application/json"
  -d "{"name":"John"}" http://localhost:8080/linkrest/department/200/employees

Ensuite, envoyons une demande GET pour afficher les employés du service:

curl -i -X GET "http://localhost:8080/linkrest/department/200/employees
Cela renvoie un objet JSON avec un tableau de données
{"data":[{"id":200,"name":"John"}],"total":1}

6. Personnalisation de la réponse avec des paramètres de demande

LinkRest offre un moyen simple de personnaliser la réponse en ajoutant des paramètres spécifiques à la requête. Ceux-ci peuvent être utilisés pour filtrer, trier, paginer ou restreindre l'ensemble des attributs du jeu de résultats.

6.1. Filtration

Nous pouvons filtrer les résultats en fonction des valeurs des attributs en utilisant le paramètrecayenneExp. Comme son nom l'indique, cela suit le format deCayenne expressions.

Envoyons une demande qui ne renvoie que les départements avec le nom "IT":

curl -i -X GET http://localhost:8080/linkrest/department?cayenneExp=name='IT'

6.2. Tri

Les paramètres à ajouter pour trier un ensemble de résultats sontsort etdir. Le premier d'entre eux spécifie l'attribut par lequel trier et le second le sens du tri.

Voyons tous les départements triés par nom:

curl -i -X GET "http://localhost:8080/linkrest/department?sort=name&dir=ASC"

6.3. Pagination

La bibliothèque prend en charge la pagination en ajoutant les paramètresstart etlimit:

curl -i -X GET "http://localhost:8080/linkrest/department?start=0&limit=2

6.4. Sélection des attributs

En utilisant les paramètresinclude etexclude, nous pouvons contrôler quels attributs ou relations sont renvoyés dans le résultat.

Par exemple, envoyons une demande qui n'affiche que les noms des départements:

curl -i -X GET "http://localhost:8080/linkrest/department?include=name

Pour afficher les noms ainsi que les employés d'un service avec uniquement leur nom, nous pouvons utiliser l'attributinclude deux fois:

curl -i -X GET "http://localhost:8080/linkrest/department?include=name&include=employees.name

7. Conclusion

Dans l'article, nous avons montré comment nous pouvons exposer rapidement un modèle de données via des points de terminaison REST en utilisant le frameworkLinkRest.

Le code source complet des exemples peut être trouvéover on GitHub.