jeudi 22 juin 2017

Service REST avec Kotlin, Spring Boot pour les débutants

Aujourd'hui on va créer un petit service REST qui s'appelle "Greeter" très simple et qui va pas faire autre chose que nous ecrire "Salut, ". Ensuite on va l'améliorer au niveau que ce service sera capable de rediriger les appels selon le nom qu'on mets comme paramètre dans l'adresse HTTP.

La logique est tres simple:
Si le nom est "R21" - afficher la page d'erreur
Pour le reste - afficher la page normale.

Le but est de prendre connaissance avec Kotlin et voir, comment Kotlin nous pourrait simplifier la vie au niveau du syntaxe et l'efficacité. On aura besoin:
- IntelliJ IDEA - une IDE Java très belle et efficace qui je commence a utiliser plus en plus. C'était développée par la société JetBrains, c'est gratuite (la version "community" qui sera suffisante pour nous) et permets de faire certains choses a la manière plus rapide (p.e. l'input prédictif du code). Ici l'addresse: https://www.jetbrains.com/idea/download/
- Spring Boot - pour nous simplifier le lancement du projet.
- Spring Initializer - pour nous simplifier la création de la structure de notre projet Java Spring
- 10 Min du temps, pas plus (encore moins, avec copier/coller).

Le code vous trouverez ici: https://github.com/cyberglad/kotlindemo




 Création du projet 



 - Allez sur la site de Spring Initializer:https://start.spring.io/

Sélectionnez "Maven" comme outil d'automatisation d'assemblage des bibliothèques pour notre programme , "Kotlin" comme langage et la version Spring Boot 1.5.4 (en fait, vous pouvez prendre n'importe quelle version).

- Sélectionnez Jersey JAX-RS comme "dependency", on n'aura pas besoin plus qu'une.
- C'est tout, telechargez la structure du projet (cliquer sur "Generate Project")

Importation dans Intellij IDEA:




- Installez le programme, ouvrez-le, choisissez "File->Open":
- Simplement sélectionnez le folder correct et choisissez "ok"
- Le projet va être importé a l'IDE avec toute sa structure, ensuite l'IDE va créer les folders nécessaires "src" et "test" avec des subfolders et avec la classe Kotlin principale KotlindemoApplication


package com.projects.kotlin.kotlindemo

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
class KotlindemoApplication

fun main(args: Array) {
    SpringApplication.run(KotlindemoApplication::class.java, *args)
}
Ce syntaxe peut sembler a Groovy, donc ce devrait être bien facil pour un programmeur Java. On peut noter que le truc qui prenait dans Java plusieurs lignes, ici vient ecrit avec 1 ligne et il y a moins des déclarations a faire chaque fois (Public, static, etc). Vous pouvez lancer le programme tel quel et ce devrait compiler tel quel sans erreurs. Juste que vous voyez rien sur localhost, pq on a encore rien écrit.

Création du contrôleur REST

On commence par la création d'un package qu'on va appeler "restful", ou on va créer une nouvelle classe Kotlin (clic droit->New->Kotlin Class):
- On declare la classe "open" et on va le mettre 2 annotations:@Component pour déclarer que c'est un service et @Path("greet/{name}" pour spécifier le chemin URL (Alt+Enter pour importer les bibliothèques nécessaires.
- On va mettre un méthode "greet" (avec des annotations correctes @GET et @Produces pour déclarer le type d'appel et le typ de contenu qui va retourner notre service). Jusqu'à ce moment on aura ça dans le code:

@Component
@Path("greet/{name}")
open class GreetController{ 
    @GET  
    @Produces(MediaType.APPLICATION_JSON) 
    fun  greet(@PathParam("name") name:String): Response { 
        return Response.ok(name).build() 
    } 
}
- Maintenant on va créer la classe pour configurer Jersey (on va dériver cette classe de la classe ResourceConfig):
import org.glassfish.jersey.server.ResourceConfig
import org.springframework.stereotype.Component

@Component
class JerseyConfig: ResourceConfig
{
    constructor() {
        packages(JerseyConfig:: class.java.`package`.name)
    }
}

La ligne JerseyConfig:: class.java fait en Kotlin la meme chose que la ligne JerseyConfig.class en Java. Ensuite on obtient le package (en Java on fait ça avec le méthode Java.lang.Class.getPackage()) avec son nom. Le mot "Package" on mais en guillemets pq c'est un mot "réservé" en Kotlin et sans guillemets peut être interprété d'une manière incorrecte.
Execution
- On peut lancer notre service soit avec un triangle vert, soit avec "Run" depuis le menu:
- S'il n'a pas d'erreur, on voit la phrase dans les logs, comme:

Started KotlindemoApplicationKt in 5.216 seconds (JVM running for 6.136)
Tapez l'adresse dans votre browser avec le nom:
http://localhost:8080/greet/
On obtient une page blanche avec le nom écrit, dans mon cas - c'est Yuri:


Extra
On peut aussi faire notre petit service plus intelligent a la maniere, qu'on voudrait éviter la connexion pour un utilisateur specific (p.e. "R21", que peut être un robot web avec une "mauvaise intention"). Normalement on faisait cette fonctionnalité dans Java avec des exceptions, ou on a redirigé certains appels de notre service aux exceptions et assigné au contrôleur de traiter ces exceptions. Mais Kotlin nous permettra d'obtenir la même fonctionnalité sans entrer dans le monde d'exceptions.
- on va créer un nouveau package "service" avec une nouvelle classe "GreetService":
- dans cette classe on va créer une interface Resp pour la reponse et 2 classes qui implémentent cette interface pour la réponse positive (Success) et la réponse négative (Error). Ensuite on va definir un methode "greet" qui va rediriger la réponse selon le nom comme paramètre:

import org.springframework.stereotype.Component 
 
@Component 
class GreetService{ 
 
    interface Resp { 
        class Success(val msg: String): Resp 
        class Error(): Resp 
    } 
    fun greet(name: String): Resp { 
        return if (name.equals("R21")) 
            Resp.Error() 
        else             
            Resp.Success("Hello, ${name}") 
    } 
} 
- ensuite on modifie le controlleur créé au début de ce tutoriel:
package com.projects.kotlin.kotlindemo.restful
import com.projects.kotlin.kotlindemo.service.GreetService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.util.*
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Component
@Path("greet/{name}")
open class GreetController @Autowired constructor(val service: GreetService){
    data class Greet(val message: String, val time:String)

    @GET  
    @Produces(MediaType.APPLICATION_JSON)
    fun greet(@PathParam("name") name:String): Response {
        val resp = service.greet(name)
        return when(resp){
            is GreetService.Resp.Success -> Response.ok(resp.msg, Date().toString()).build()
            is GreetService.Resp.Error -> Response.status(Response.Status.BAD_REQUEST).build()
            else->Response.status(Response.Status.INTERNAL_SERVER_ERROR).build()
        }
     }
}

Notez qu'avec la déclaration de la classe en Kotlin, on déclare aussi l'"Autowired" pour injecter notre service. Tres efficace! Ensuite on redirige l'action du service a la réponse correcte (soit "ok", soit "error"). On relance notre service et on essaie avec un "bon" utilisateur:

Par contre, s'on essaie avec "R21" - on obtient une erreur!
Voila le petit service avec Kotlin! Dans les prochaines tutoriels on va faire encore des choses plus intéressantes et compliqués, comme ca on va apprécier encore plus l'efficacité et la simplicité de ce langage.

Aucun commentaire:

Enregistrer un commentaire