Introduction à RESTX

Introduction à RESTX

1. Vue d'ensemble

Dans ce didacticiel, nous allons visiter le framework léger Java RESTRESTX.

2. Caractéristiques

Construire une API RESTful est assez facile avec le framework RESTX. Il contient tous les paramètres par défaut que l'on peut attendre d'un framework REST, comme le service JSON, les paramètres de requête et de chemin d'accès, les mécanismes de routage et de filtrage, les statistiques d'utilisation et la surveillance.

RESTX est également fourni avec une console Web d'administration intuitive et un programme d'installation en ligne de commande pour un démarrage facile.

Il est également sous licence Apache License 2 et maintenu par une communauté de développeurs. La configuration Java minimale requise pour RESTX est JDK 7.

3. Configuration

RESTX est livré avec une application shell / commande pratique qui est utile pour démarrer rapidement un projet Java.

Nous devons d'abord installer l'application avant de pouvoir continuer. Les instructions d'installation détaillées sont disponibleshere.

4. Installer des plugins de base

Il est maintenant temps d’installer les principaux plugins pour pouvoir créer une application à partir du shell lui-même.

Dans le shell RESTX, exécutons la commande suivante:

shell install

Il nous demandera ensuite de sélectionner les plugins à installer. Nous devons sélectionner le nombre qui pointe versio.restx:restx-core-shell. The shell will automatically restart once installation completes.

5. Bootstrap de l'application Shell

En utilisant le shell RESTX, il est très pratique d’amorcer une nouvelle application. Il fournit un guide basé sur un assistant.

Nous commençons par exécuter la commande suivante sur le shell:

app new

Cette commande déclenchera l'assistant. Ensuite, nous pouvons choisir les options par défaut ou les modifier selon nos besoins:

imageimage

Puisque nous avons choisi de générer unpom.xml,, le projet peut être facilement importé dans n'importe quel IDE Java standard.

Dans quelques cas, nous pouvons avoir besoin de modifierthe IDE settings.

Notre prochaine étape sera de construire le projet:

mvn clean install -DskipTests

Once the build is successful we can run the AppServer class as a Java Application from the IDE. Cela démarrera le serveur avec la console d’administration, en écoutant sur le port 8080.

Nous pouvons accéder àhttp://127.0.0.1:8080/api/@/ui and voir l'interface utilisateur de base.

Les routes commençant par/@/ sont utilisées pour la console d'administration qui est un chemin réservé dans RESTX.

Pour nous connecter à la console d'administration, nous pouvons utiliser le nom d'utilisateur par défaut «admin et le mot de passe que nous avons fourni lors de la création de l'application.

Avant de jouer avec la console, explorons le code et comprenons ce que l'assistant a généré.

6. Une ressource RESTX

Les routes sont définies dans la classe <main_package>.rest.HelloResource:

@Component
@RestxResource
public class HelloResource {
    @GET("/message")
    @RolesAllowed(Roles.HELLO_ROLE)
    public Message sayHello() {
        return new Message().setMessage(String.format("hello %s, it's %s",
          RestxSession.current().getPrincipal().get().getName(),
          DateTime.now().toString("HH:mm:ss")));
    }
}

Il est immédiatement évident que RESTX utilise les annotations J2EE par défaut pour la sécurité et les liaisons REST. Pour la plupart, il utilise ses propres annotations pour l'injection de dépendance.

RESTX prend également en charge de nombreuses valeurs par défaut raisonnables pourmapping method parameters to the request.

Et, en plus de ces annotations standard, il y a@RestxResource, qui le déclare comme une ressource que RESTX reconnaît.

Le chemin de base est ajouté dans lessrc/main/webapp/WEB-INF/web.xml. Dans notre cas, il s'agit de/api, donc nous pouvons envoyer une requête GET àhttp://localhost:8080/api/message, en supposant une authentification correcte.

La classeMessage est simplement un bean Java que RESTX sérialise en JSON.

Nous contrôlons l'accès utilisateur en spécifiant l'annotationRolesAllowed à l'aide duHELLO_ROLE qui a été généré par le bootstrapper.

7. La classe de module

Comme indiqué précédemment, RESTX utilise des annotations d'injection de dépendances au standard J2EE, comme@Named, et invente les siennes si nécessaire, s'inspirant probablement du framework Dagger pour@Module et@Provides.

Il les utilise pour créer le module principal des applications, qui définit entre autres le mot de passe administrateur:

@Module
public class AppModule {

    @Provides
    public SignatureKey signatureKey() {
        return new SignatureKey("restx-demo -44749418370 restx-demo 801f-4116-48f2-906b"
            .getBytes(Charsets.UTF_8));
    }

    @Provides
    @Named("restx.admin.password")
    public String restxAdminPassword() {
        return "1234";
    }

    @Provides
    public ConfigSupplier appConfigSupplier(ConfigLoader configLoader) {
        return configLoader.fromResource("restx/demo/settings");
    }

    // other provider methods to create components
}

@Module définit une classe qui peut définir d'autres composants, similaire à@Module dans Dagger, ou@Configuration in Spring.

@Provides expose un composant par programme, comme@Provides in Dagger ou@Bean dans Spring.

Et, enfin, l'annotation@Named est utilisée pour indiquer le nom du composant produit.

AppModule fournit également unSignatureKey utilisé pour signer le contenu envoyé aux clients. Lors de la création de la session pour l'exemple d'application, par exemple, un cookie, signé avec la clé configurée, sera créé:

HTTP/1.1 200 OK
...
Set-Cookie: RestxSessionSignature-restx-demo="ySfv8FejvizMMvruGlK3K2hwdb8="; RestxSession-restx-demo="..."
...

8. La classe lanceur

Enfin, la classeAppServer est utilisée pour exécuter l'application en tant qu'application Java standard dans un serveur Jetty intégré:

public class AppServer {
    public static final String WEB_INF_LOCATION = "src/main/webapp/WEB-INF/web.xml";
    public static final String WEB_APP_LOCATION = "src/main/webapp";

    public static void main(String[] args) throws Exception {
        int port = Integer.valueOf(Optional.fromNullable(System.getenv("PORT")).or("8080"));
        WebServer server =
            new Jetty8WebServer(WEB_INF_LOCATION, WEB_APP_LOCATION, port, "0.0.0.0");
        System.setProperty("restx.mode", System.getProperty("restx.mode", "dev"));
        System.setProperty("restx.app.package", "restx.demo");
        server.startAndAwait();
    }
}

Ici, le modedev est utilisé pendant la phase de développement pour activer des fonctionnalités telles que la compilation automatique qui raccourcit la boucle de rétroaction du développement.

Nous pouvons empaqueter l'application sous forme de fichierwar (archive Web) à déployer dans un conteneur Web J2EE autonome.

Voyons comment tester l'application dans la section suivante.

9. Test d'intégration à l'aide de Specs

L'une des principales caractéristiques de RESTX est son concept de «spécifications». Un échantillonspec ressemblerait à ceci:

title: should admin say hello
given:
  - time: 2013-08-28T01:18:00.822+02:00
wts:
  - when: |
      GET hello?who=xavier
    then: |
      {"message":"hello xavier, it's 01:18:00"}

Le test est écrit dans une structureGiven-When-Then dans un fichierYAML qui définit fondamentalement comment l'API doit répondre (then) à une requête spécifique (when) étant donné un état actuel du système (given).

La classeHelloResourceSpecTest danssrc/test/resources déclenchera les tests écrits dans les spécifications ci-dessus:

@RunWith(RestxSpecTestsRunner.class)
@FindSpecsIn("specs/hello")
public class HelloResourceSpecTest {}

La classeRestxSpecTestsRunner est uncustom JUnit runner. Il contient des règles personnalisées JUnit pour:

  • mettre en place un serveur embarqué

  • préparer l'état du système (selon la sectiongiven dans les spécifications)

  • émettre les demandes spécifiées, et

  • vérifier les réponses attendues

L'annotation@FindSpecsIn pointe vers le chemin des fichiers de spécifications sur lesquels les tests doivent être exécutés.

Les spécifications deThe spec helps to write integration tests and provide examples in the API docs. sont également utiles pour lesmock HTTP requests and record request/response pairs.

10. Test manuel

Nous pouvons également tester manuellement via HTTP. Nous devons d’abord nous connecter et, pour ce faire, nous devons hacher le mot de passe de l’administrateur dans la console RESTX:

hash md5 

Et puis nous pouvons passer cela au point de terminaison/sessions:

curl -b u1 -c u1 -X POST -H "Content-Type: application/json"
  -d '{"principal":{"name":"admin","passwordHash":"1d528266b85cf052803a57288"}}'
  http://localhost:8080/api/sessions

(Notez que les utilisateurs Windows doivent d'abord bouclerdownload.)

Et maintenant, si nous utilisons la session dans le cadre de notre requête/message:

curl -b u1 "http://localhost:8080/api/message?who=restx"

Ensuite, nous obtiendrons quelque chose comme ceci:

{"message" : "hello admin, it's 09:56:51"}

11. Exploration de la console d'administration

La console d'administration fournit des ressources utiles pour contrôler l'application.

Jetons un œil aux fonctionnalités clés en accédant àhttp://127.0.0.1:8080/admin/@/ui.

11.1. Documents sur l'API

La section Documents de l'API répertorie tous les itinéraires disponibles, y compris toutes les options:

imageimage

Et nous pouvons cliquer sur des itinéraires individuels et les essayer sur la console elle-même:

imageimage

11.2. surveillance

La sectionJVM Metrics affiche les métriques d'application avec les sessions actives, l'utilisation de la mémoire et le vidage des threads:

imageimage

SousApplication Metrics, nous avons principalement deux catégories d'éléments surveillés par défaut:

  • BUILD correspond à l'instanciation des composants applicatifs

  • HTTP correspond aux requêtes HTTP traitées par RESTX

11.3. Statistiques

RESTX permet à l'utilisateur de choisir de collecter et de partager des statistiques anonymes sur l'application afin de fournir des informations à la communauté RESTX. We can easily opt out by excluding the restx-stats-admin module.

Les statistiques indiquent des éléments tels que le système d'exploitation sous-jacent et la version de la machine virtuelle Java:

imageimage

Because this page shows sensitive information,make sure to review its configuration options.

En plus de cela, la console d’administration peut également nous aider:

  • vérifier les journaux du serveur (journaux)

  • afficher les erreurs rencontrées (erreurs)

  • vérifier les variables d'environnement (Config)

12. Autorisation

RESTX endpoints are secured by default. Cela signifie que si pour n'importe quel point de terminaison:

@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

Lorsqu'il est appelé sans authentification, il renvoie un401  par défaut.

Pour rendre un point de terminaison public, nous devons utiliser l'annotation@PermitAll au niveau de la méthode ou de la classe:

@PermitAll
@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

Notez qu'au niveau de la classe, toutes les méthodes sont publiques.

De plus, le framework permet également de spécifier les rôles des utilisateurs à l'aide de l'annotation@RolesAllowed:

@RolesAllowed("admin")
@GET("/greetings/{who}")
public Message sayHello(String who) {
    return new Message(who);
}

Avec cette annotation, RESTX vérifiera si un rôle administrateur est également attribué à l'utilisateur authentifié. Dans le cas où un utilisateur authentifié sans rôles d'administrateur tente d'accéder au point de terminaison, l'application renverra un403 au lieu d'un401.

Par défaut, les rôles utilisateur et les informations d'identification sont stockés sur le système de fichiers, dans des fichiers séparés.

Ainsi, l'ID utilisateur avec le mot de passe chiffré est stocké sous le fichier/data/credentials.json:

{
    "user1": "$2a$10$iZluUbCseDOvKnoe",
    "user2": "$2a$10$oym3Swr7pScdiCXu"
}

Et, les rôles des utilisateurs sont définis dans le fichier/data/users.json:

[
    {"name":"user1", "roles": ["hello"]},
    {"name":"user2", "roles": []}
]

Dans l'exemple d'application, les fichiers sont chargés dans leAppModule via la classeFileBasedUserRepository:

new FileBasedUserRepository<>(StdUser.class, mapper,
  new StdUser("admin", ImmutableSet. of("*")),
  Paths.get("data/users.json"), Paths.get("data/credentials.json"), true)

La classeStdUser contient les objets utilisateur. Il peut s'agir d'une classe d'utilisateurs personnalisée, mais elle doit être sérialisable en JSON.

Nous pouvons, bien sûr, utiliser une implémentation deUserRepositorydifférente, comme celle qui atteint une base de données.


13. Conclusion

Ce tutoriel a donné un aperçu du framework RESTX Java léger.

Le framework est encore en développement et il pourrait y avoir quelques aspérités dans son utilisation. Consultezthe official documentation pour plus de détails.

L'exemple d'application amorcée est disponible dans nosGitHub repository.