{"id":160,"date":"2020-03-08T12:21:10","date_gmt":"2020-03-08T11:21:10","guid":{"rendered":"http:\/\/baptiste-meynier.com\/?p=160"},"modified":"2023-02-18T18:45:11","modified_gmt":"2023-02-18T17:45:11","slug":"les-microprofiles-eclipse","status":"publish","type":"post","link":"https:\/\/baptiste-meynier.com\/index.php\/2020\/03\/08\/les-microprofiles-eclipse\/","title":{"rendered":"Les MicroProfiles Eclipse"},"content":{"rendered":"\n<p>Notre m\u00e9tier vit une p\u00e9riode de migration massive de ses infrastructures vers le Cloud. Un monde ou les services doivent \u00eatre en toutes circonstances disponibles. Les applications doivent \u00eatre stateless, scalables, l\u00e9g\u00e8res et rapides \u00e0 lancer.<\/p>\n\n\n\n<p>Spring Boot est le premier \u00e0 avoir tir\u00e9 l\u2019\u00e9pingle de son jeu, sachez cependant qu\u2019il n\u2019est pas le seul sur le march\u00e9, bien au contraire.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"281\" height=\"91\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/eclipse-foundation.png\" alt=\"\" class=\"wp-image-163\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Fin 2016 la fondation Eclipse a lanc\u00e9 l\u2019initiative MicroProfile autour de deux id\u00e9es :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>D\u00e9finir un sous ensemble de sp\u00e9cifications JakartaEE pour proposer un serveur plus l\u00e9ger<\/li>\n\n\n\n<li>D\u00e9finir de nouvelles sp\u00e9cifications pour une meilleure int\u00e9gration au cloud<\/li>\n<\/ul>\n\n\n\n<p>Voici le d\u00e9tail de la derni\u00e8re version :<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/1infoq-microprofile-3.png\" alt=\"\" class=\"wp-image-165\" width=\"797\" height=\"463\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/1infoq-microprofile-3.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/1infoq-microprofile-3-300x174.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/1infoq-microprofile-3-768x446.png 768w\" sizes=\"auto, (max-width: 797px) 100vw, 797px\" \/><\/figure>\n<\/div>\n\n\n<p>Vous retrouverez l\u2019ensemble des sp\u00e9cifications sur le compte&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/eclipse\" target=\"_blank\">Github<\/a>&nbsp;de la Fondation Eclipse. A noter qu\u2019elle dispose de son propre syst\u00e8me de validation de sp\u00e9cifications, l\u2019Eclipse Foundation Specification Process (EFSP). Une nouvelle release est publi\u00e9e tous les trimestres. L\u2019objectif est que ces composants fassent l\u2019objet d\u2019une JCP (Java Community Process) pour int\u00e9grer les JSR (Java Specification Requests).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Mais de quoi est compos\u00e9 une sp\u00e9cification Eclipse Microprofile ?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La sp\u00e9cification sous forme asciidoc<\/li>\n\n\n\n<li>L\u2019API, ensemble d\u2019interfaces \/ \u00e9num\u00e9rations Java permettant de d\u00e9finir les fonctionnalit\u00e9s \u00e0 impl\u00e9menter<\/li>\n\n\n\n<li>Suite de tests appel\u00e9e TCK (Technology Compatibility Kit) permettant de valider une impl\u00e9mentation<\/li>\n<\/ul>\n\n\n\n<p>N\u2019h\u00e9sitez pas \u00e0 y jeter un coup d\u2019\u0153il, les&nbsp;<a href=\"https:\/\/github.com\/eclipse\/microprofile-health\/blob\/master\/spec\/src\/main\/asciidoc\/protocol-wireformat.adoc\" target=\"_blank\" rel=\"noreferrer noopener\">sp\u00e9cifications<\/a>&nbsp;sont de v\u00e9ritables mines d\u2019or. Elles d\u00e9crivent et d\u00e9taillent l\u2019ensemble des fonctionnalit\u00e9s qui la compose. En les consultant vous y d\u00e9couvrirez peut \u00eatre une feature qui vous sera utile !<\/p>\n\n\n\n<p>N\u2019oublions pas qu\u2019il s\u2019agit de sp\u00e9cifications, vous ne trouverez pas d\u2019impl\u00e9mentation dans ce type de repos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Faisons un petit tour du propri\u00e9taire<\/h2>\n\n\n\n<p>J\u2019ai d\u00e9coup\u00e9 les sp\u00e9cifications en 3 cat\u00e9gories.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1) Les composants JakartaEE<\/h2>\n\n\n\n<p>Il s\u2019agit de composants repris des sp\u00e9cifications JakartaEE, ils forment les fondations de notre MicroProfile (n\u2019h\u00e9sitez pas \u00e0 lire l\u2019article&nbsp;<a href=\"http:\/\/blog.keywer.com\/un-nouveau-vent-souffle-sur-le-monde-des-applications-web-java\/\" target=\"_blank\" rel=\"noreferrer noopener\">JakartaEE<\/a>&nbsp;sur notre blog).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">CDI<\/h3>\n\n\n\n<p>Context and Dependency Injection est le m\u00e9canisme central sur lequel se repose bon nombre de composants. Ce syst\u00e8me permet de limiter le couplage entre les objets en facilitant le remplacement des impl\u00e9mentations. La plupart de ses fonctionnalit\u00e9s s\u2019effectuent en phase de compilation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Produces\n@ApplicationScoped\npublic static ObjectMapper creerMapper() {\n  return new ObjectMapper();\n}\n\n...\n\n@Inject\nFishService fishService;\n\n@Inject\nObjectMapper objectMapper;<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">JAX-RS<\/h3>\n\n\n\n<p>Je ne m\u2019attarderai pas sur la sp\u00e9cification standardisant les applications Rest bien connue de tous. Il s\u2019agit certainement avec CDI de la sp\u00e9cification la plus fournie en fonctionnalit\u00e9s.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">JSON-P<\/h3>\n\n\n\n<p>Sp\u00e9cification permettant de faciliter la manipulation de json (parsing, cr\u00e9ation, transformation, recherche).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">JsonBuilderFactory bf = Json.createBuilderFactory(null)\nJsonArray array = bf.createArrayBuilder()\n.add(bf.createObjectBuilder()\n.add(\"id\", 1)\n.add(\"name\", \"Cichlidae\")\n.add(\"water_type\", 0))\n.add(bf.createObjectBuilder()\n.add(\"id\", 2)\n.add(\"name\", \"Cyprinidae\")\n.add(\"water_type\", 0))\n.build();<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">JSON-B<\/h3>\n\n\n\n<p>Cette sp\u00e9cification permet de d\u00e9finir la fa\u00e7on de mapper un objet java en json et vice versa.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">public class Fish {\n   public long id;\n   public String name;\n   public WaterType waterType;\n}\n\nJsonb jsonb = JsonbBuilder.create();\n\nFish maurice = new Fish();\nmaurice.id = 1;\nmaurice.name = \"Maurice\";\nmaurice.waterType= WaterType.FRESH;\n\nString mauriceJson = jsonb.toJson(maurice);\nSystem.out.println(mauriceJson); \/\/ {\"id\":1,\"name\":\"Maurice\",\"waterType\": 1}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/wheel_jakarta_microprofile_opacity-293x300-1.png\" alt=\"\" class=\"wp-image-172\" width=\"432\" height=\"442\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sp\u00e9cifications utilitaires<\/h2>\n\n\n\n<p>Ces sp\u00e9cifications ne sont pas indispensables au bon fonctionnement de votre projet mais elles vous faciliteront la vie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Open API<\/h3>\n\n\n\n<p>Cette sp\u00e9cification standardise la documentation des API, c\u2019est sur ce standard que repose Swagger.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@GET\n@Path(\"\/{fishname}\")\n@Operation(summary = \"Get fish by fish name\")\n@APIResponse(description = \"The fish\",\ncontent = @Content(mediaType = \"application\/json\",\nschema = @Schema(implementation = Fish.class))),\n@APIResponse(responseCode = \"400\", description = \"Fish not found\")\npublic Response getFishByName(\n@Parameter(description = \"The name that needs to be fetched. Use fish1 for testing. \", required = true) @PathParam(\"fishname\") String fishname)<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">GET \/openapi<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">\/fish\/{fishname}:\nget:\nsummary: Get fish by fish name\noperationId: getFishByName\nparameters:\n- name: fishname\nin: path\ndescription: 'The name that needs to be fetched. Use fish1 for testing. '\nrequired: true\nschema:\ntype: string\nresponses:\ndefault:\ndescription: The fish\ncontent:\napplication\/json:\nschema:\n$ref: '#\/components\/schemas\/Fish'\n400:\ndescription: Fish not found<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Rest Client<\/h3>\n\n\n\n<p>Cette sp\u00e9cification particuli\u00e8rement riche standardise les clients Rest. La fonctionnalit\u00e9 principale de cette API est de pouvoir cr\u00e9er un proxy de service Rest.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Path(\"\/fishs\")\n@Produces(\"application\/json\")\n@Consumes(\"application\/json\")\npublic interface FishServiceClient {\n   @GET\n   @Path(\"family\/{fishFamily}\")\n   Response countByFamily(@PathParam(\"fishFamily\") String fishFamily);\n\n   @PUT\n   Response updateFish(@BeanParam PutFish putFish);\n}\n\npublic class PutFish {\n   @HeaderParam(\"Authorization\")\n   private String authorization;\n   @PathParam(\"fishId\")\n   private String fishId;\n   \/\/ getters, setters, constructors omitted\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Fault tolerance<\/h3>\n\n\n\n<p>Cette sp\u00e9cification permet de rendre votre application plus r\u00e9siliente en cas de perte de d\u00e9pendances externes (service, database, etc).<\/p>\n\n\n\n<p>Prenons l\u2019exemple d\u2019une application affichant le d\u00e9tail d\u2019une fiche d\u2019un poisson. Son contenu doit \u00eatre affich\u00e9 m\u00eame sous forme d\u00e9grad\u00e9. Une partie de ces informations provient d\u2019un service externe qui devient brusquement indisponible.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Retry(maxRetries = 2)\n@Fallback(fallbackMethod= \"fallbackForFindFamilyName\")\npublic String findFamilyName(String fishName) {\n   return fishServiceClient.findFamilyName(fishName);\n}\n\nprivate String fallbackForFindFamilyName() {\n   return \"Missing information\";\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">JWT Propagation<\/h3>\n\n\n\n<p>Json Web Token Propagation nous aide \u00e0 r\u00e9cup\u00e9rer les informations sur le Principal du contexte. Il suffit juste d\u2019utiliser des annotations via son int\u00e9gration \u00e0 CDI (header, claim et signature).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Inject\nprivate JsonWebToken callerPrincipal;\n\n@Inject\n@Claim(\"raw_token\")\nprivate String rawToken;\n\n@Inject\n@Claim(\"groups\")\nprivate Set groups;\n\n@Inject\n@Claim(\"exp\")\nprivate long expiration;\n\n@Inject\n@Claim(\"sub\")\nprivate String subject;<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Open tracing<\/h3>\n\n\n\n<p>Cette sp\u00e9cification permet de standardiser la mani\u00e8re de tracer les appels dans un contexte distribu\u00e9. Ces flux pourront \u00eatre exploit\u00e9s par des outils tels que Jaeger ou Zipkin. Cette fonctionnalit\u00e9 ne n\u00e9cessite pas d\u2019activation particuli\u00e8re si vous disposez d\u2019une application JAX-RS. Dans le cas contraire il est possible d\u2019utiliser l\u2019annotation @Traced.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sp\u00e9cifications permettant l&#8217;int\u00e9gration \u00e0 un environnement Cloud<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Microprofile Config<\/h3>\n\n\n\n<p>C\u2019est l\u2019une des sp\u00e9cifications que je trouve la plus int\u00e9ressante, elle standardise le chargement de configurations. Elle est capable de r\u00e9cup\u00e9rer ces informations depuis plusieurs sources, fichiers, param\u00e8tres de lancement du serveur, variables d\u2019environnements etc. Il existe des impl\u00e9mentations vers ZooKeeper Consule ou encore Etcd.<\/p>\n\n\n\n<p>Prenons l\u2019exemple d\u2019une variable d\u2019environnement appel\u00e9e $SHOP_NAME=FishParadise, que vous souhaitez exploiter dans votre application.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Inject @ConfigProperty(name=\"SHOP_NAME\", defaultValue=\"FishMarket\")\nString shopName<\/code><\/pre>\n\n\n\n<p>A noter que le fichier de configuration par d\u00e9faut pour un Microprofile Eclipse est le fichier microprofile-config.properties.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Microprofile Health<\/h3>\n\n\n\n<p>Cette sp\u00e9cification permet de sonder l\u2019\u00e9tat d\u2019une application. Elle expose plusieurs endpoints permettant de v\u00e9rifier que votre application est lanc\u00e9e (Liveness), ou pr\u00eate \u00e0 fournir son service (Readyness). Il est possible d\u2019ajouter soi-m\u00eame ses v\u00e9rifications en les impl\u00e9mentant.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">GET \/health\/live<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n  \"status\" : \"UP\",\n  \"checks\" : [ {\n    \"name\" : \"DataSourceHealthCheck\",\n    \"status\" : \"UP\"\n  } ]\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Microprofile Metric<\/h3>\n\n\n\n<p>Sp\u00e9cification permettant de r\u00e9cup\u00e9rer des statistiques sur l\u2019usage de l\u2019application. Ces m\u00e9triques sont divis\u00e9es en 3 cat\u00e9gories Base, Application, Vendor. Elles sont accessibles via l\u2019url \/metrics\/[Base|Vendor|Application]. Vous y trouverez des informations sur l\u2019usage du CPU, l\u2019\u00e9tat de la jvm ou encore sur votre pool http. Il est \u00e9galement possible d\u2019ajouter vos propres m\u00e9triques m\u00e9tier.<\/p>\n\n\n\n<p>La sp\u00e9cification fournit de nombreuses annotations @Counted @ConcurrentGauge @Gauge @Metered @Metric @Timed @SimplyTimed. Elles pourront \u00eatre appliqu\u00e9es selon les cas, \u00e0 des m\u00e9thodes, types ou classes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">@Gauge(unit = MetricUnits.NONE, name = \"fishQueueSize\")\npublic int getFishQueueSize() {\n   return fishQueue.size;\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre id=\"block-f4ca4b5b-3b34-4b9b-8fdd-5b06cbaab34e\" class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">GET \/metrics<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"># TYPE base_jvm_uptime_seconds gauge\n# HELP base_jvm_uptime_seconds Displays the start time of the Java virtual machine in milliseconds. This attribute displays the approximate time when the Java virtual machine started.\nbase_jvm_uptime_seconds{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 315.14300000000003\n# TYPE base_classloader_loadedClasses_total_total counter\n# HELP base_classloader_loadedClasses_total_total Displays the total number of classes that have been loaded since the Java virtual machine has started execution.\nbase_classloader_loadedClasses_total_total{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 12580\n# TYPE base_thread_count gauge\n# HELP base_thread_count Displays the current number of live threads including both daemon and non-daemon threads\nbase_thread_count{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 28\n# TYPE base_memory_committedHeap_bytes gauge\n# HELP base_memory_committedHeap_bytes Displays the amount of memory in bytes that is committed for the Java virtual machine to use. This amount of memory is guaranteed for the Java virtual machine to use.\nbase_memory_committedHeap_bytes{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 3.16669952E8\n# TYPE base_gc_total_total counter\n# HELP base_gc_total_total Displays the total number of collections that have occurred. This attribute lists -1 if the collection count is undefined for this collector.\nbase_gc_total_total{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",name=\"G1-Young-Generation\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 6\n# TYPE base_gc_total_total counter\n# HELP base_gc_total_total Displays the total number of collections that have occurred. This attribute lists -1 if the collection count is undefined for this collector.\nbase_gc_total_total{environment=\"dev\",instanceId=\"9afb9093-e0a9-4518-8b66-852f6b9c310a\",name=\"G1-Old-Generation\",serviceName=\"UNKNOWN\",serviceVersion=\"1.0.0\"} 0<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">C&#8217;est bien beau de voir les sp\u00e9cifications, mais sans impl\u00e9mentations \u00e7a ne fonctionne pas !<\/h3>\n\n\n\n<p>Il en existe de nombreuses fournies par Oracle, RedHat, IBM etc. Je vous propose de jeter un coup d\u2019\u0153il sur l\u2019impl\u00e9mentation la plus utilis\u00e9e (licence apache) :<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/smallrye_project_logo.png\" alt=\"\" class=\"wp-image-173\" width=\"303\" height=\"81\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Mais quels serveurs sont compatibles ?<\/h3>\n\n\n\n<p>Voici un&nbsp;<a href=\"https:\/\/start.microprofile.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">web starter<\/a>&nbsp;permettant de cr\u00e9er votre projet MicroProfile Eclipse.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"669\" height=\"551\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/starter.png\" alt=\"\" class=\"wp-image-169\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/starter.png 669w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/starter-300x247.png 300w\" sizes=\"auto, (max-width: 669px) 100vw, 669px\" \/><\/figure>\n<\/div>\n\n\n<p>Vous y trouverez des noms bien connus tel que Wildfly et OpenLiberty TomEE et des petits nouveaux comme Payara, KumuluzEE, Helidon et Quarkus.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Un peu de pratique<\/h2>\n\n\n\n<p>J\u2019ai choisi pour ce projet d\u2019utiliser&nbsp;<a href=\"https:\/\/ee.kumuluz.com\/\">KumuluzEE<\/a>&nbsp;. Il dispose d\u2019une bonne documentation, de nombreuses impl\u00e9mentations et le support est particuli\u00e8rement r\u00e9actif.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"464\" height=\"71\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/kumuluzee-logo.png\" alt=\"\" class=\"wp-image-168\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/kumuluzee-logo.png 464w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/kumuluzee-logo-300x46.png 300w\" sizes=\"auto, (max-width: 464px) 100vw, 464px\" \/><\/figure>\n<\/div>\n\n\n<h4 class=\"wp-block-heading\"><\/h4>\n\n\n\n<h4 class=\"wp-block-heading\">Structure du projet:<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">C:\\USERS\\BMEYNIER\\IDEAPROJECTS\\MICROPROFILE-ARTICLE\n\u251c\u2500\u2500\u2500.idea\n\u2502   \u2514\u2500\u2500\u2500libraries\n\u2514\u2500\u2500\u2500src\n    \u251c\u2500\u2500\u2500assembly\n    \u2502   \u2514\u2500\u2500\u2500conf\n    \u2502       \u2514\u2500\u2500\u2500local\n    \u2502           \u2514\u2500\u2500\u2500META-INF\n    \u251c\u2500\u2500\u2500doc\n    \u2502   \u2514\u2500\u2500\u2500postman\n    \u2514\u2500\u2500\u2500main\n        \u251c\u2500\u2500\u2500docker\n        \u2502   \u251c\u2500\u2500\u2500app\n        \u2502   \u2514\u2500\u2500\u2500db\n        \u2502       \u251c\u2500\u2500\u2500init\n        \u2502       \u2514\u2500\u2500\u2500scripts\n        \u251c\u2500\u2500\u2500filters\n        \u251c\u2500\u2500\u2500java\n        \u2502   \u2514\u2500\u2500\u2500com\n        \u2502       \u2514\u2500\u2500\u2500bmeynier\n        \u2502           \u2514\u2500\u2500\u2500article\n        \u2502               \u2514\u2500\u2500\u2500microprofile\n        \u2502                   \u251c\u2500\u2500\u2500domain\n        \u2502                   \u2502   \u2514\u2500\u2500\u2500enums\n        \u2502                   \u251c\u2500\u2500\u2500repository\n        \u2502                   \u2514\u2500\u2500\u2500rest\n        \u2502                       \u2514\u2500\u2500\u2500producer\n        \u251c\u2500\u2500\u2500k3s\n        \u2514\u2500\u2500\u2500resources\n            \u251c\u2500\u2500\u2500META-INF\n            \u2514\u2500\u2500\u2500WEB-INF<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Configuration du pom<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"xml\" class=\"language-xml\">&lt;dependencyManagement&gt;\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.eclipse.microprofile&lt;\/groupId&gt;\n            &lt;artifactId&gt;microprofile&lt;\/artifactId&gt;\n            &lt;version&gt;${microprofile.version}&lt;\/version&gt;\n            &lt;type&gt;pom&lt;\/type&gt;\n            &lt;scope&gt;import&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n&lt;\/dependencyManagement&gt;<\/code><\/pre>\n\n\n\n<p>Import des specifications Microprofile<\/p>\n\n\n\n<p>A cela il faut ajouter dans le d\u00e9pendencyManagement le bom contenant toutes les impl\u00e9mentations fournies par KumuluzEE.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"xml\" class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;com.kumuluz.ee&lt;\/groupId&gt;\n    &lt;artifactId&gt;kumuluzee-bom&lt;\/artifactId&gt;\n    &lt;version&gt;${kumuluzee.version}&lt;\/version&gt;\n    &lt;type&gt;pom&lt;\/type&gt;\n    &lt;scope&gt;import&lt;\/scope&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>Il faut ensuite faire ses courses en choisissant les impl\u00e9mentations dont vous avez besoin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"xml\" class=\"language-xml\">&lt;dependency&gt;\n    &lt;groupId&gt;com.kumuluz.ee&lt;\/groupId&gt;\n    &lt;artifactId&gt;kumuluzee-servlet-jetty&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;com.kumuluz.ee&lt;\/groupId&gt;\n    &lt;artifactId&gt;kumuluzee-jpa-hibernate&lt;\/artifactId&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>Jetty en guise de server http et Hibernate pour le JPA<\/p>\n\n\n\n<p>Les MicroProfiles sont tr\u00e8s flexibles, j\u2019aurai tr\u00e8s bien pu choisir d\u2019autres impl\u00e9mentations telles que Undertow et Eclipse-Link.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Microprofile.properties<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"properties\" class=\"language-properties\">kumuluzee.datasources[0].jndi-name = jdbc\/FishsDS\nkumuluzee.datasources[0].connection-url = ${KUMULUZEE_DATASOURCES0_CONNECTIONURL}\nkumuluzee.datasources[0].driver-name = ${KUMULUZEE_DATASOURCES0_DRIVER}\nkumuluzee.datasources[0].username = ${KUMULUZEE_DATASOURCES0_USERNAME}\nkumuluzee.datasources[0].password = ${KUMULUZEE_DATASOURCES0_PASSWORD}\nkumuluzee.datasources[0].pool.max-size = 20\nkumuluzee.health.checks.data-source-health-check =\nkumuluzee.health.checks.data-source-health-check.type = readiness\nkumuluzee.health.checks.data-source-health-check.jndi-name = jdbc\/FishsDS\nkumuluzee.health.checks.disk-space-health-check =\nkumuluzee.health.checks.disk-space-health-check.type = liveness\nkumuluzee.health.checks.disk-space-health-check.threshold = 10000<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Taille du jar:<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER Microprofile-Article]$ ls -alhs .\/target\/\ntotal 30M\n4,0K drwxr-xr-x. 7 baptiste baptiste 4,0K 30 avril 07:40 .\n4,0K drwxr-xr-x. 6 baptiste baptiste 4,0K 30 avril 07:44 ..\n 30M -rw-r--r--. 1 baptiste baptiste  30M 30 avril 07:40 microprofile-article-1.0.0-SNAPSHOT.jar\n 16K -rw-r--r--. 1 baptiste baptiste  15K 30 avril 07:40 microprofile-article-1.0.0-SNAPSHOT.jar.original<\/code><\/pre>\n\n\n\n<p>Vous trouverez dans ce jar de 30Mo votre code source ainsi que toutes les d\u00e9pendances du serveur, il est ex\u00e9cutable tel quel.<\/p>\n\n\n\n<p>Pour avoir une id\u00e9e claire de ce que vous embarquez je vous conseille vivement de lancer la commande mvn dependency:tree et d\u2019ouvrir le contenu du jar.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Temps de lancement:<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER Microprofile-Article]$ $JAVA_11\/bin\/java -jar  .\/target\/microprofile-article-1.0.0-SNAPSHOT.jar\n2020-04-30 07:34:36.628 INFO -- com.kumuluz.ee.configuration.sources.FileConfigurationSource -- Loading configuration from .properties file: META-INF\/microprofile-config.properties\n2020-04-30 07:34:36.644 INFO -- com.kumuluz.ee.configuration.sources.FileConfigurationSource -- Configuration successfully read.\n2020-04-30 07:34:36.645 INFO -- com.kumuluz.ee.EeApplication -- Initialized configuration source: EnvironmentConfigurationSource\n2020-04-30 07:34:36.645 INFO -- com.kumuluz.ee.EeApplication -- Initialized configuration source: SystemPropertyConfigurationSource\n2020-04-30 07:34:36.646 INFO -- com.kumuluz.ee.EeApplication -- Initialized configuration source: FileConfigurationSource\n2020-04-30 07:34:36.647 INFO -- com.kumuluz.ee.EeApplication -- Initializing KumuluzEE\n2020-04-30 07:34:36.647 INFO -- com.kumuluz.ee.EeApplication -- Checking for requirements\n2020-04-30 07:34:36.648 INFO -- com.kumuluz.ee.EeApplication -- KumuluzEE running inside a JAR runtime.\n[...]\n2020-04-30 07:34:39.944 INFO -- org.eclipse.jetty.server.AbstractConnector -- Started ServerConnector@45cd8607{HTTP\/1.1,[http\/1.1]}{0.0.0.0:8080}\n2020-04-30 07:34:39.944 INFO -- org.eclipse.jetty.server.Server -- Started @3776ms\n2020-04-30 07:34:39.944 INFO -- com.kumuluz.ee.EeApplication -- KumuluzEE started successfully<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Consommation m\u00e9moire:<\/h4>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"718\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/heap_memory-1-1024x718-1.png\" alt=\"\" class=\"wp-image-170\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/heap_memory-1-1024x718-1.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/heap_memory-1-1024x718-1-300x210.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/heap_memory-1-1024x718-1-768x539.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>De 35 \u00e0 150 Mo (simulation r\u00e9alis\u00e9e avec activit\u00e9 mod\u00e9r\u00e9e) avec comme limite -Xmx256m.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Et si on mettait tout \u00e7a dans le Cloud ?<\/h2>\n\n\n\n<h5 class=\"wp-block-heading\">Pour cet exemple j\u2019ai install\u00e9 une version all\u00e9g\u00e9e de Kubernetes sur mon poste, K3s de Rancher.<\/h5>\n\n\n\n<p><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"44\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/rancher-logo-horiz-color-300x44-1.png\" alt=\"\" class=\"wp-image-171\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Nous d\u00e9finirons deux services :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Une base de donn\u00e9es de type H2<\/li>\n\n\n\n<li>Notre application KumuluzEE<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">La base de donn\u00e9es<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: fishs-database\n  namespace: default\nspec:\n  selector:\n    matchLabels:\n      app: fishs-database\n  template:\n    metadata:\n      labels:\n        app: fishs-database\n    spec:\n      initContainers:\n        - name: init-database\n          image: bmeynier\/microprofile\/k3s-init-database:v1.0.0\n          command: ['sh', '-c', '\/tmp\/createDatabase.sh']\n          envFrom:\n            - secretRef:\n                name: k3s-fishs-secret\n          volumeMounts:\n            - name: database\n              mountPath: \/database\n      containers:\n        - name: fishs-database\n          image: bmeynier\/microprofile\/k3s-database:v1.0.0\n          volumeMounts:\n            - name: database\n              mountPath: \/database\n          ports:\n            - containerPort: 1521\n      volumes:\n        - emptyDir: {}\n          name: database\n\n---\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: fishs-database\n  namespace: default\nspec:\n  selector:\n    app: fishs-database\n  ports:\n    - port: 1521\n      targetPort: 1521<\/code><\/pre>\n\n\n\n<p>La base de donn\u00e9es est initialis\u00e9e \u00e0 l\u2019aide d\u2019un init-container. A noter que le volume est partag\u00e9 entre l\u2019init-container et le container.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">L\u2019application KumuluzEE<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: fishs-application\n  namespace: default\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: fishs-application\n  template:\n    metadata:\n      labels:\n        app: fishs-application\n    spec:\n      containers:\n        - name: fishs-application\n          image: bmeynier\/microprofile\/k3s-application:v1.0.0\n          envFrom:\n            - configMapRef:\n                name: k3s-fishs-config\n            - secretRef:\n                name: k3s-fishs-secret\n          # system probes\n          readinessProbe:\n            httpGet:\n              path: \/health\/ready\n              port: 8080\n            initialDelaySeconds: 20\n            periodSeconds: 10\n            timeoutSeconds: 3\n            failureThreshold: 1\n          livenessProbe:\n            httpGet:\n              path: \/health\/live\n              port: 8080\n            initialDelaySeconds: 15\n            periodSeconds: 10\n            timeoutSeconds: 3\n            failureThreshold: 1\n          resources:\n            limits:\n              memory: 256Mi\n              cpu: 500m\n            requests:\n              memory: 64Mi\n          ports:\n            - containerPort: 8080\n\n---\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: fishs-application\n  namespace: default\nspec:\n  selector:\n    app: fishs-application\n  ports:\n    - port: 8080\n      targetPort: 8080\n  type: LoadBalancer<\/code><\/pre>\n\n\n\n<p>Vous remarquerez l\u2019usage de ConfigMap et de Secret. Ces objets Kubernetes seront inject\u00e9s en tant que variables d\u2019environnement lors du lancement de mon Pod. Je pourrai ensuite les exploiter gr\u00e2ce \u00e0 MicroProfile Config.<\/p>\n\n\n\n<p>Le second point int\u00e9ressant concerne la d\u00e9finition des Healths [Live|Ready] qui int\u00e9ragissent avec MicroProfile Health.<\/p>\n\n\n\n<p>Le composant Microprofile Metric permet de scaler de mani\u00e8re horizontale nos services, nous en parlerons dans un prochain article.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@DESKTOP-BMEYNIER Microprofile-Article]$ sudo k3s kubectl get all\n[sudo] Mot de passe de baptiste : \nNAME                                     READY   STATUS    RESTARTS   AGE\npod\/fishs-database-dbc9d98d-984ms        1\/1     Running   0          73m\npod\/svclb-fishs-application-25tlg        1\/1     Running   0          17m\npod\/fishs-application-764f69b78d-k7sqx   1\/1     Running   0          17m\n\nNAME                        TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE\nservice\/kubernetes          ClusterIP      10.43.0.1       &lt;none&gt;         443\/TCP          3h41m\nservice\/fishs-database      ClusterIP      10.43.188.110   &lt;none&gt;         1521\/TCP         73m\nservice\/fishs-application   LoadBalancer   10.43.229.234   X.X.X.X   8080:32158\/TCP   17m\n\nNAME                                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE\ndaemonset.apps\/svclb-fishs-application   1         1         1       1            1           &lt;none&gt;          17m\n\nNAME                                READY   UP-TO-DATE   AVAILABLE   AGE\ndeployment.apps\/fishs-database      1\/1     1            1           73m\ndeployment.apps\/fishs-application   1\/1     1            1           17m\n\nNAME                                           DESIRED   CURRENT   READY   AGE\nreplicaset.apps\/fishs-database-dbc9d98d        1         1         1       73m\nreplicaset.apps\/fishs-application-764f69b78d   1         1         1       17m\n\nNAME                                                    REFERENCE                      TARGETS                MINPODS   MAXPODS   REPLICAS   AGE\nhorizontalpodautoscaler.autoscaling\/fishs-application   Deployment\/fishs-application   &lt;unknown&gt;\/1k, 0%\/50%   1         3         1          16m<\/code><\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/gitlab.com\/bmeynier\/Microprofile-Eclipse\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/gitlab.png\" alt=\"\" class=\"wp-image-176\" width=\"107\" height=\"99\"\/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\"><em>Retrouvez le code source sur Gitlab !<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Il existe un large choix de serveurs<\/li>\n\n\n\n<li>Une nouvelle release sort tous les trimestres<\/li>\n\n\n\n<li>Ces serveurs sont flexibles, l\u00e9gers et rapides !<\/li>\n\n\n\n<li>Il est toujours possible de surcharger le comportement d\u2019un composants, il ne s\u2019agit pas d\u2019une boite noire<\/li>\n\n\n\n<li>Il sont parfaitement int\u00e9gr\u00e9s aux environnements cloud<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"695\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/makeChoiceThree.png\" alt=\"\" class=\"wp-image-213\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/makeChoiceThree.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/makeChoiceThree-300x204.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/makeChoiceThree-768x521.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><a rel=\"noreferrer noopener\" href=\"https:\/\/gitlab.com\/keywer-article\/microprofile-eclipse\" target=\"_blank\"><\/a><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>Notre m\u00e9tier vit une p\u00e9riode de migration massive de ses infrastructures vers le Cloud. Un monde ou les services doivent \u00eatre en toutes circonstances disponibles. Les applications doivent \u00eatre stateless, scalables, l\u00e9g\u00e8res et rapides \u00e0 lancer. Spring Boot est le premier \u00e0 avoir tir\u00e9 l\u2019\u00e9pingle de son jeu, sachez cependant qu\u2019il n\u2019est pas le seul &hellip;<\/p>\n","protected":false},"author":1,"featured_media":161,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[5],"tags":[],"class_list":["post-160","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microprofile"],"_links":{"self":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/160","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/comments?post=160"}],"version-history":[{"count":41,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/160\/revisions"}],"predecessor-version":[{"id":1848,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/160\/revisions\/1848"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/media\/161"}],"wp:attachment":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/media?parent=160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/categories?post=160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/tags?post=160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}