Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Microservice avec les micro-frameworks Java @ DevoxxFR 2016

Microservice avec les micro-frameworks Java @ DevoxxFR 2016

Hands-on DEVOXX FR 2016.
Feign, SparkJava, Micro frameworks, Microservices

Laurent BARESSE

April 22, 2016
Tweet

More Decks by Laurent BARESSE

Other Decks in Programming

Transcript

  1. #DevoxxFR
    20/04/2016
    #feign #sparkjava
    3 heures
    pour développer un micro-service
    avec les micro-frameworks Java

    View Slide

  2. #DevoxxFR
    Laurent Baresse
    Developer & Geek
    [email protected]
    @Baresse
    Igor Laborie
    Expert Web & Java
    [email protected]
    @ilaborie
    #feign #sparkjava

    View Slide

  3. #DevoxxFR
    Roadmap
    13:30 - Introduction to micro-XXX
    MyCellar
    13:45 - Feign
    Exercises Set #1
    15:00 - Coffee Time
    15:15 - SparkJava
    Exercises Set #2
    16:30 - End
    #feign #sparkjava

    View Slide

  4. #DevoxxFR
    Practical notes
    Wifi SSID devoxxfr-hol / hol@1375
    Requirement: JDK 8, Maven 3, your favorite IDE
    Download projects
    - https://ilaborie.org/DevoxxFR/
    Or clone github project
    - https://github.com/Baresse/FeignSparkJava-exos
    #feign #sparkjava

    View Slide

  5. #DevoxxFR
    Introduction to micro-XXX
    #feign #sparkjava

    View Slide

  6. #DevoxxFR
    Microservices
    #feign #sparkjava
    Martin Fowler : Microservices (http://martinfowler.
    com/articles/microservices.html)
    ● Componentization via Services
    ● Decentralized governance
    ● Decentralized data management

    View Slide

  7. #DevoxxFR
    Micro-frameworks
    #feign #sparkjava
    ● Plenty of micro-framework availables
    ● Criteria
    ○ Simple and mastered in few hours
    ○ Community
    ○ Elegant & Java 8 oriented

    View Slide

  8. #DevoxxFR
    MyCellar
    #feign #sparkjava

    View Slide

  9. #DevoxxFR #feign #sparkjava

    View Slide

  10. #DevoxxFR
    Cellar Service
    microservices: mockup services (authentication,
    reference, comment and stock)
    src/main/java // devoxx.microframeworks.exos
    ● models: Pojo used in the application
    ● routes: Cellar service REST routes
    implementation (Spark Java)
    ● services: REST clients services
    implementation (Feign)
    ● Main: Cellar service Main class (embed cellar
    front-end)
    #feign #sparkjava

    View Slide

  11. #DevoxxFR
    Start others microservices
    Open 4 terminals / consoles
    ./start-authentication-services.sh
    ./start-reference-services.sh
    ./start-comments-services.sh
    ./start-stocks-services.sh
    #feign #sparkjava
    $ ./start-authentication-service.sh
    [Thread-0] [INFO] log - Logging initialized @363ms
    [Thread-0] [INFO] JettySparkServer - == Spark has ignited ...
    [Thread-0] [INFO] JettySparkServer - >> Listening on 0.0.0.0:8093
    [Thread-0] [INFO] Server - jetty-9.3.z-SNAPSHOT
    [Thread-0] [INFO] ServerConnector - Started ServerConnector@50f244a7{HTTP/1.1,
    [http/1.1]}{0.0.0.0:8093}
    [Thread-0] [INFO] Server - Started @450ms

    View Slide

  12. #DevoxxFR
    Or if you <3 Docker
    $ docker-compose up
    Creating sparkfeign-auth
    Creating sparkfeign-reference
    Creating sparkfeign-stocks
    Creating sparkfeign-comments
    Attaching to sparkfeign-auth, sparkfeign-reference, sparkfeign-stocks,
    sparkfeign-comments
    sparkfeign-auth | [Thread-0] [INFO] log - Logging initialized @578ms
    sparkfeign-reference | [main] [INFO] WineDao - Parse wines database :323 wines
    read.
    sparkfeign-auth | [Thread-0] [INFO] JettySparkServer - == Spark has ignited ...
    sparkfeign-reference | [Thread-0] [INFO] log - Logging initialized @565ms
    sparkfeign-auth | [Thread-0] [INFO] JettySparkServer - >> Listening on 0.0.0.0:
    8093
    ...

    View Slide

  13. #DevoxxFR
    Feign
    Consuming RESTful WebService
    #feign #sparkjava

    View Slide

  14. #DevoxxFR
    Why Feign ?
    #feign #sparkjava

    View Slide

  15. #DevoxxFR
    com.netflix.feign:feign-core:8.16.0
    * for feign-core, others extensions had few
    https://github.com/Netflix/feign
    Apache License v2.0
    Java 7+, Java 8 friendly
    No dependencies*
    #feign #sparkjava

    View Slide

  16. #DevoxxFR
    Interface & Annotations [1/5]
    public interface CatClient {
    List findAll();
    Cat findById(String id);
    Cat create(Cat cat);
    // ...
    }
    #feign #sparkjava

    View Slide

  17. #DevoxxFR
    Interface & Annotations [2/5]
    public interface CatClient {
    @RequestLine("GET /cats")
    List findAll();
    Cat findById(String id);
    Cat create(Cat cat);
    // ...
    }
    #feign #sparkjava

    View Slide

  18. #DevoxxFR
    Interface & Annotations [3/5]
    public interface CatClient {
    @RequestLine("GET /cats")
    List findAll();
    @RequestLine("GET /cats/{id}")
    Cat findById(@Param("id") String id);
    Cat create(Cat cat);
    // ...
    }
    #feign #sparkjava

    View Slide

  19. #DevoxxFR
    Interface & Annotations [4/5]
    public interface CatClient {
    @RequestLine("GET /cats")
    List findAll();
    @RequestLine("GET /cats/{id}")
    Cat findById(@Param("id") String id);
    @RequestLine("POST /cats")
    Cat create(Cat cat);
    // ...
    }
    #feign #sparkjava

    View Slide

  20. #DevoxxFR
    Interface & Annotations [5/5]
    @Headers("Accept: application/json")
    public interface CatClient {
    @RequestLine("GET /cats")
    List findAll();
    @RequestLine("GET /cats/{id}")
    Cat findById(@Param("id") String id);
    @Headers("Content-Type: application/json")
    @RequestLine("POST /cats")
    Cat create(Cat cat);
    // ...
    }
    #feign #sparkjava

    View Slide

  21. #DevoxxFR
    Build the instance
    public static CatClient create(String url) {
    return Feign.builder()
    // extra configuration ...
    .target(CatClient.class, url);
    }
    Use the Feign.Builder()
    #feign #sparkjava

    View Slide

  22. #DevoxxFR
    Body Encoder & decoder
    It’s easy to create custom encoder/decoder.
    public static CatClient create(String url) {
    return Feign.builder()
    .encoder(new GsonEncoder())
    .decoder(new GsonDecoder())
    .target(CatClient.class, url);
    }
    Available extensions: GSON, Jackson, JAXB, Sax
    #feign #sparkjava

    View Slide

  23. #DevoxxFR
    Error Decoder
    public static CatClient create(String url) {
    return Feign.builder()
    .errorDecoder((msg, response) ->
    new WTFException(response.status()))
    .target(CatClient.class, url);
    }
    Feign throw a FeignException on NOK response
    #feign #sparkjava

    View Slide

  24. #DevoxxFR
    RequestInterceptor customisation
    RequestInterceptor ~ Consumer
    Example: add an HTTP header
    public static CatClient create(String url) {
    // TODO get user JSON Web Tokens
    String jwt = "";
    return Feign.builder()
    .requestInterceptor(template -> {
    template.header("Authorization", "Bearer " + jwt));
    }).target(CatClient.class, url);
    }
    #feign #sparkjava

    View Slide

  25. #DevoxxFR
    Others extensions ...
    Implement Contract for custom annotations (e.g. JAX-RS)
    Use another HTTP client implements Client
    Apache HttpClient: feign-httpclient
    OkHttp: feign-okhttp
    Also have integration for
    SLF4J logging: feign-slf4j
    Ribbon: feign-ribbon
    Histryx circuit breaker: feign-histryx
    ...
    #feign #sparkjava

    View Slide

  26. #DevoxxFR
    Exercises Set #1
    #feign #sparkjava

    View Slide

  27. #DevoxxFR #feign #sparkjava

    View Slide

  28. #DevoxxFR
    Ex 1.1 : Encoder/Decoder JSON
    Ex 1.2: ReferenceService
    Ex 1.3: CommentService
    Ex 1.4: StockService
    Ex 1.5 (bonus): Jackson instead of Gson
    Ex 1.6 (bonus): Add logs
    Ex 1.7 (bonus): connect Heroku
    -- PAUSE --
    #feign #sparkjava

    View Slide

  29. #DevoxxFR
    SparkJava
    #feign #sparkjava

    View Slide

  30. #DevoxxFR
    Why Spark Java ?
    #feign #sparkjava

    View Slide

  31. #DevoxxFR
    TL;TR: The promise...

    com.sparkjava
    spark-core
    2.3

    #feign #sparkjava
    http://localhost:4567/hello
    import static spark.Spark.*;
    public class HelloWorld {
    public static void main(String[] args) {
    get("/hello", (req, res) -> "Hello World");
    }
    }

    View Slide

  32. #DevoxxFR
    Spark Java
    http://sparkjava.com
    Apache License v2.0
    Lightweight and embedded web server (Jetty)
    #feign #sparkjava

    View Slide

  33. #DevoxxFR
    Roadmap
    Embedded Server Configuration
    Routes
    Request
    Response
    Filters
    Exceptions
    #feign #sparkjava

    View Slide

  34. #DevoxxFR
    Embedded web server - Configuration
    // If provided port = 0, an arbitrary available port will //
    be used ; default 4567
    port(int port)
    // the folder in classpath
    staticFileLocation(String folder)
    // the external folder serving static files
    externalStaticFileLocation(String externalFolder)
    Configuration before any route / filter mapping
    #feign #sparkjava

    View Slide

  35. #DevoxxFR
    Routes
    #feign #sparkjava
    Routes are matched in the order they are defined. The first
    route that matches the request is invoked.
    ● Verb: get, post, put, delete, head, trace, connect,
    options
    ● Path: "/path", "/path/:param"
    ● Callback: (request, response) -> { }
    Optionally:
    ● Accept-type = "application/json"
    ● ResponseTranformer

    View Slide

  36. #DevoxxFR
    Routes matching
    // Show something
    get("/", (request, response) -> { ... });
    // Create something
    post("/", (request, response) -> { ... });
    // Update something
    put("/", (request, response) -> { ... });
    // Annihilate something
    delete("/", (request, response) -> { ... });
    // Appease something
    options("/", (request, response) -> { ... });
    #feign #sparkjava

    View Slide

  37. #DevoxxFR
    Routes matching & URL parameters
    // matches "GET /hello/foo" and "GET /hello/bar"
    // request.params("name") is 'foo' or 'bar'
    get("/hello/:name", (request, response) -> {
    return "Hello: " + request.params("name");
    });
    NOTE : Query parameters are not used for URL matching
    #feign #sparkjava

    View Slide

  38. #DevoxxFR
    Request
    request.body(); // request body sent by the client
    request.bodyAsBytes(); // request body as bytes
    request.headers(); // the HTTP header list
    request.headers("BAR"); // value of BAR header
    request.params("foo"); // value of foo path parameter
    request.params(); // map with all parameters
    request.queryParams(); // the query param list
    request.queryParams("FOO"); // value of FOO query param
    request.queryParamsValues("FOO") // all values of FOO query param
    See Spark.Request for other methods and details
    #feign #sparkjava

    View Slide

  39. #DevoxxFR
    Response
    response.body("Hello"); // sets content to Hello
    response.header("FOO", "bar"); // sets header FOO with value bar
    response.redirect("/example"); // browser redirect (HTTP 302)
    response.redirect("/bar", 301); // moved permanently
    response.status(401); // set status code to 401
    response.type("text/xml"); // set content type to text/xml
    See Spark.Response for other methods and details
    #feign #sparkjava

    View Slide

  40. #DevoxxFR
    Filters
    before((request, response) -> {
    // ... check if authenticated
    halt(401, "You are not welcome here");
    });
    before("/protected/*", (request, response) -> {
    // ... check if authenticated
    halt(401, "Go Away!");
    });
    after((request, response) -> {
    response.header("foo", "set by after f ilter");
    });
    Filters can:
    read the request
    read/modify the
    response
    #feign #sparkjava

    View Slide

  41. #DevoxxFR
    Exceptions
    // Should an exception be thrown somewhere...
    get("/throwexception", (request, response) -> {
    throw new NotFoundException();
    });
    // Exception handler
    exception(NotFoundException.class, (e, request,
    response) -> {
    response.status(404);
    response.body("Resource not found");
    });
    #feign #sparkjava

    View Slide

  42. #DevoxxFR
    With Spark Java, you can also ...
    ● Cookies
    ● Session
    ● WebSockets (only with embedded web server)
    ● Request/Response GZIP
    ● View and Templatings (mustache, thymeleaf,
    velocity, …)
    #feign #sparkjava

    View Slide

  43. #DevoxxFR
    Exercises Set #2
    #feign #sparkjava

    View Slide

  44. #DevoxxFR #feign #sparkjava

    View Slide

  45. #DevoxxFR
    Ex 2.1 : WineRoute
    Ex 2.2: CellarRoute
    Ex 2.3: CommentRoute
    Ex 2.4: Exception handlers
    Ex 2.5 (bonus): Asynchronous services
    aggregation
    Ex 2.6 (bonus): Docker
    #feign #sparkjava

    View Slide

  46. #DevoxxFR
    Resources
    Feign : https://github.com/Netflix/feign
    SparkJava: http://sparkjava.com
    Github (Exos)
    https://github.com/Baresse/FeignSparkJava-exos
    Github (Microservices-Mocks)
    https://github.com/Baresse/FeignSparkJava-mocks
    #feign #sparkjava

    View Slide

  47. #DevoxxFR
    Q / A
    Thanks !
    #feign #sparkjava

    View Slide