<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Slickteam - Medium]]></title>
        <description><![CDATA[Le Blog — Come as you geek ! 100% technophile &amp; 100% pur beurre une ESN pas comme les autres. www.slickteam.fr — contactez-nous ! - Medium]]></description>
        <link>https://medium.com/slickteam?source=rss----c233e538993b---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Slickteam - Medium</title>
            <link>https://medium.com/slickteam?source=rss----c233e538993b---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 01:13:12 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/slickteam" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Retours du Devoxx FR 2026]]></title>
            <link>https://medium.com/slickteam/retours-du-devoxx-fr-2026-7ee55ac75891?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/7ee55ac75891</guid>
            <category><![CDATA[devoxxfr]]></category>
            <category><![CDATA[devoxx]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[conference]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Wed, 27 May 2026 11:42:16 GMT</pubDate>
            <atom:updated>2026-06-04T08:55:49.875Z</atom:updated>
            <content:encoded><![CDATA[<p>Cette année j’ai encore eu la chance de pouvoir assister pendant 3 jours au Devoxx France, et je suis de nouveau ressorti avec pleins d’idées à tester et de belles conférences à partager.</p><figure><img alt="Une image générée représentant un magasin avec un robot au milieu dans des couleurs plutôt agréables et avec un design sympathique. Image extrait du site du Devoxx France pour 2026" src="https://cdn-images-1.medium.com/max/1024/1*xQAzarr7FOMatt7USIlz8g.png" /></figure><p>Le thème cette année était Happy AI. Après une édition 2025 déjà très axée IA, cette nouvelle édition continue dans la même ligne. A la vue du programme, une chose m’a sauté aux yeux : après 2025 où il y avait beaucoup de cas d’usages avec des frameworks, des rappels et ateliers sur les techniques (chat, RAG, …), cette année il y avait plus de méthodologie et des retours d’expérience. En particulier sur l’usage en tant qu’assistant de codage, avec des concepts et des points d’attention dont je n’avais pas connaissance et que je peux appliquer immédiatement pour certains. Bref, pas mal de concret.</p><p>Voici un résumé des conférences / ateliers auxquels j’ai participé et qui m’ont personnellement le plus apporté.</p><p><a href="https://www.youtube.com/watch?v=kMce8KBDMWQ"><strong>L’IA au service du bien commun : Agir avec raison dans l’incertain</strong></a><strong> — Laurence Devillers</strong></p><p>Première keynote de ce Devoxx France, et première conférence très intéressante. Laurence Devillers est professeure en intelligence artificielle et chercheur au CNRS entre autres, et travaille dans l’IA depuis les années 90.</p><p>L’IA va amplifier nos capacités, refléter ce que nous sommes ou pas, et elle ne ressent rien. Elle ne comprend pas ce qu’elle produit. Elle permet d’avancer plus vite, mais si nous ne sommes pas capables de comprendre ce que sort la machine, nos postes seront remplacés. L’éducation est clé pour avoir un esprit critique face à l’IA.</p><p>Tout au long de sa présentation, elle a démystifié 11 mythes autour de l’IA. Elle a parlé du paradoxe de Frankenstein, qui nous bride dans notre imaginaire sur le développement de l’IA. Ce mythe évoque la création de la vie par nous “humains” et le fait que celle-ci se rebelle contre nous. Ceci a pour effet de nous ralentir dans nos travaux sur l’IA.</p><p>Quelques autres mythes dont elle a parlé :</p><ul><li><strong>L’IA générale est pour demain</strong> (et non, pas du tout). Pour cela elle se base la théorie de <a href="https://editions.flammarion.com/systeme-1-systeme-2/9782081211476">système 1 / système 2</a> de Daniel Kahneman : système 1, voie rapide de décision (intuition, lié à la survie) ; système 2, la cognition, plus long, réflexion par rapport au sens commun, … Par rapport à nous qui avons 2 systèmes, l’IA générative n’a que le système 1 (par la régularité des patterns dans la masse des données d’entraînement) et pas de système 2, car elle n’a pas de conscience du monde. Donc on se doit d’agir en tant que système 2 pour elle.</li><li><strong>L’IA a un niveau doctorat</strong>. Qu’est-ce qu’un doctorant ? La méthode scientifique : je fais des hypothèses, je teste des choses, je regarde, j’évalue, je reviens en arrière, … L’IA ne fait pas ça.</li><li><strong>Avec l’IA plus besoin de faire des études.</strong> Au contraire, l’IA doit nous inciter à faire plus d’études en sciences. Pour faire des meilleures machines, plus malines, il faut plus d’études, surtout en sciences.</li></ul><p>Elle conclue sa keynote par une citation de Blaise Pascal (également dans le titre de la conf) : il faut continuer à agir avec raison dans l’incertain. Cette phrase correspond bien au thème de sa conférence, je vous conseille son visionnage si vous voulez prendre un peu de hauteur par rapport aux différentes affirmations que l’on entend régulièrement sur l’IA.</p><p><strong>Specification Driven Development: Développer à l’ère des LLMs — Philippe Bousquet et Benjamin Barbe</strong></p><p>Dans cet atelier de 3h, Philippe Bousquet et Benjamin Barbe nous ont présenté un “outil” : <a href="https://speckit.org/">speckit</a>. C’est un ensemble d’agents ainsi qu’une méthodologie pour développer à l’aide d’agents, en partant de spécifications. Cela fait quelques temps que j’en avais entendu parler, ce fut donc l’occasion de tester !</p><p>Speckit propose la méthodologie suivante, sachant que toutes les étapes ne sont pas obligatoires :</p><ul><li><strong>Constitution </strong>: règles et architecture du projet</li><li><strong>Spécifications </strong>: intention fonctionnelle</li><li><strong>Clarification </strong>: éliminer les ambiguïtés et les incohérences</li><li><strong>Planification </strong>: établissement du plan et définition des tâches</li><li><strong>Implémentation </strong>: implémentation des tâches</li></ul><p>Il fonctionne avec une multitude d’agents ou LLM, ce qui le rend très facile à implémenter. Personnellement pour l’atelier j’ai utilisé <a href="https://mistral.ai/fr/products/vibe">Mistral Vibe</a>.</p><p>L’atelier est bien fait :</p><ul><li>un cas pour lequel on part de zéro et on implémente un projet entier via speckit</li><li>un second cas où on part d’un projet existant et on y intègre speckit pour développer de nouvelles fonctionnalités</li></ul><p>J’ai été très content d’assister à cet atelier, les présentateurs connaissaient bien le sujet, malgré la jeunesse de l’outil. Le support vous guide bien également. Si cela vous intéresse l’atelier complet est disponible en ligne <a href="https://github.com/darken33/connaissance-client">ici</a>, avec la documentation. Je vous le conseille vivement si vous voulez tester speckit !</p><p><a href="https://www.youtube.com/watch?v=l_heE0CQQxg"><strong>Domptez vos Agents : AGENTS.md et Context Engineering pour une IA déterministe</strong></a><strong> — Benoit Fontaine</strong></p><p>Pour ce tool-in-action, Benoit Fontaine nous a présenté un mélange entre l’état de l’art des connaissances sur les comportements des modèles suivant le contexte, ainsi que son expérience personnelle.</p><p>Premier constat : votre agent n’est pas stupide, il est mal nourri. Les performances des agents sont intrinsèquement liées aux données du contexte. Les performances se dégradent lorsque :</p><ul><li>la connaissance est diluée (contexte trop important).</li><li>l’agent est distrait : le contexte est pollué par du code proche mais qui n’a rien à voir avec le dev en cours, ce qui décontextualise la réponse de l’agent.</li></ul><p>Le LLM a une meilleure connaissance du début et de la fin du contexte, sur des informations en milieu de contexte la diminution de performance est d’environ 30%. L’agent aura des meilleures performances quand la taille du contexte est contenue entre 60 et 80% de la taille maximale.</p><p>Votre AGENTS.md doit devenir l’unique source de vérité :</p><ul><li>architecture et règles des couches</li><li>conventions</li><li>TDD / BDD (ou autre)</li><li>Règles strictes et les violations interdites</li></ul><p>AGENTS.md est régi par une norme définie par la Linux Foundation, adopter un autre format revient à s’enfermer dans du vendor locking.</p><p>La commande <strong>/compact</strong> est très importante car elle permet de nettoyer le contexte de tout ce qui pourrait le parasiter et ainsi ne garder que l’utile.</p><p>Comment déterminer que votre contexte est arrivé “pourri” :</p><ul><li>Hallucinations d’API : il va commencer à inventer des appels à des api qui n’existent pas</li><li>Amnésie des conventions</li><li>Boucle d’erreur : il boucle sur la même erreur sans en sortir</li><li>Génération de code incohérent</li></ul><p>=&gt; contexte pourri = session morte. Vous pouvez redémarrer une nouvelle session.</p><p>L’IA est amplificateur universel, il n’y a pas de magie. Soignez votre contexte :).</p><p>Pour préparer sa conférence, Benoit à écrit trois articles sur medium, vous pouvez les trouver ici : <a href="https://medium.benoitfontaine.fr/">https://medium.benoitfontaine.fr/</a>. De même, il a fait un projet Github qui lui a servi de support, il est disponible ici : <a href="https://github.com/b-fontaine/devoxx-2026">https://github.com/b-fontaine/devoxx-2026</a></p><p><a href="https://www.youtube.com/watch?v=NNJC-zgsLTA"><strong>Serveurs MCP : bonnes pratiques, choix de conception et leurs conséquences</strong></a><strong> — Horacio Gonzalez</strong></p><p>Ce fut la dernière université à laquelle j’ai assisté avant de devoir quitter ce Devoxx 2026, et elle fut très intéressante ! Horacio Gonzalez nous a fait un retour d’expérience sur l’usage et le développement de serveur MCP, depuis les premiers serveurs sortis après l’annonce du protocole jusqu’à aujourd’hui.</p><p>Pour ceux qui ont des doutes sur l’utilité du MCP encore aujourd’hui (ça va tellement vite avec l’outillage IA), celui-ci va devenir un incontournable car il permet de faire le pont entre des accès techniques (APIs, …) et une demande de l’utilisateur en langage naturel. Via un serveur MCP il est possible de donner accès à un LLM à des fonctions lui permettant de mieux nourrir son contexte, mieux répondre à la demande de l’utilisateur.</p><p>Le LLM n’appelle jamais l’outil directement, c’est l’application qui fait appel au LLM qui le fera. Actuellement il y a une phase d’appel à évolutions pour une nouvelle version de la spécification qui devrait publiée en juin 2026.</p><p>Horacio a commencé par nous décrire les 3 primitives serveurs qu’un MCP peut exposer (outil, ressource, prompt). Puis une fois les bases du protocole posées, il nous a exposé sa méthode pour développer son propre MCP :</p><ul><li><strong>Phase 1</strong> : avoir quelque chose de fonctionnel. Bien utiliser toutes les primitives. Les outils doivent être construits comme des APIs. Les ressources permettent de limiter la réflexion des LLMs en fournissant des données statiques (ou semi-statiques). Les prompts ont l’intérêt de pouvoir être versionnés et ainsi être adaptés au modèle et sa version. Structurez bien les retours et les erreurs, mieux cela sera fait plus le LLM sera performant. Et surtout : n’oubliez pas toutes vos bonnes pratiques de code (sécurité surtout !).</li><li><strong>Phase 2</strong> : on commence a déployer. L’authentification n’est pas optionnelle, on doit savoir qui fait quoi : pour de la sécurité, de la traçabilité, et l’amélioration globale du système. Mettre en place des logs, avec de l’observabilité, et un dashboard permettant de mesurer la fiabilité de l’outil (et suivre son éventuelle dégradation suite à changement de modèle). Pour éviter de surcharger le contexte, on peut appliquer le nouveau pattern <a href="https://developers.cloudflare.com/agents/api-reference/codemode/">code mode</a> de Cloudflare. Il est possible de voir comment CleverCloud a implémenté un MCP pour son API en regardant son code <a href="https://github.com/CleverCloud/mcp-simple-server">ici</a>.</li><li><strong>Phase 3</strong> : passage à l’échelle. Comme pour un gros monolithe, on découpe en domaines / microservices. Faire plusieurs MCP suivant son propre contexte (par domaine, par source/service, par rôle), et mettre une gateway en frontal pour regrouper les fonctions communes (nettoyage des I/O, authentification, …) et avoir des MCPs plus simples. Mettre également un rate limit pour éviter les LLMs qui bouclent par moments.</li></ul><p>Personnellement j’ai bien aimé cette université, même si Horacio avait prévu bien plus de contenu qu’il n’y avait de temps disponible. Son expérience et ses anecdotes permettent d’avoir une bonne compréhension de ce qu’on peut faire avec un MCP (et ce qu’on ne doit pas faire !). Si le sujet vous intéresse, je vous conseille vivement son visionnage.</p><p>Enfin voici les autres conférences auxquelles j’ai assisté :</p><ul><li><a href="https://www.youtube.com/watch?v=q_k3aW1BKmI">Les échecs à l’ère de l’intelligence artificielle</a> — Laurent Fressinet : l’histoire de la relation entre l’IA et les échecs, avec notamment Kasparov et Deep Blue. Keynote intéressante qui démontre aussi l’évolution des relations entre les humains et la machine.</li><li><a href="https://www.youtube.com/watch?v=N3NzgO6M-Ss">Apprendre à notre IA à … apprendre</a> — Stéphane Philippart : une bonne conférence pour comprendre comment mieux nourrir une IA pour la rendre plus pertinente.</li><li><a href="https://www.youtube.com/watch?v=AAwDj9-oL-g">CLI-Driven Developer Experience : L’ingrédient secret d’une équipe alignée</a> — Julian Briault : comment Julien, à travers son expérience aux restos du cœur ou chez Deezer, à mis au point une CLI pour faciliter les opérations, le partage de connaissance, … au sein des équipes (dev, ops, …).</li><li><a href="https://www.youtube.com/watch?v=3xgi_ULQMgc">Le développeur face à l’IA : du prototypage rapide à la fin des intermédiaires ?</a> — Nicolas Grenié : comment utiliser l’IA pour prototyper rapidement et laisser libre cours à ses idées pour déployer rapidement. Une keynote qui donne pleins d’idées.</li><li><a href="https://www.youtube.com/watch?v=h2CECLQl4nU">L’IA sur le terrain : l’humain au cœur de la valeur</a> — Marjory Cannone : tout le monde veut de l’IA, mais tout le monde ne sait pas comment ou ne sait pas s’il en a besoin. Retour terrain de Marjory qui travaille avec des TPE/PME dans les Vosges.</li><li><a href="https://www.youtube.com/watch?v=igA4UyZb3z4">Concurrency Crossroads: Choosing between Reactive Programming &amp; Virtual Threads </a>— Willem Jan Glerum : conférence Java, avec des rappels sur ce qu’est la programmation réactive, les threads virtuels, et ce que ça peut apporter ou pas suivant les cas. Elle se termine sur un comparatif de performances réalisé par l’équipe de Quarkus.</li><li><a href="https://www.youtube.com/watch?v=_Z19XcCMeNo">Les gardiens du Prompt : menaces et recettes de sécurité pour une production zen</a> — Philippe Laumay et Loïc Gudet : tous pleins de bons conseils sur la gestion d’une application avec de l’IA, la sécurisation des prompts, les guardrails, … Chaudement recommandée pour ce qui font de l’IA en production.</li><li><a href="https://www.youtube.com/watch?v=7bqt1Qp7Y2k">Se retourner la tête avec les quiz Java de José et Jean-Michel</a> — José Paumard et Jean-Michel Doudoux : un moment de détente avec un quiz en live et beaucoup de discussions dans le public suivant les questions !</li><li><a href="https://www.youtube.com/watch?v=ZEtc6WnreI0">Mise : un multi-outil pour votre poste Dev &amp; Ops </a>— Rémi Verchère : une bonne présentation de Mise, un outil d’installation d’outils de configuration de contexte projet. Il m’intéressait car avec l’arrêt de volta les mainteneurs recommandaient de passer à Mise. A tester !</li><li><a href="https://www.youtube.com/watch?v=fg6DDchoxG8">L’IA au défi de la condition humaine</a> — Jean-Gabriel Ganascia : une keynote bien sympa, ou après une bonne partie dédiée à l’IA heureuse, la conclusion paraît bien plus terre à terre. Je vous la conseille !</li><li><a href="https://www.youtube.com/watch?v=YNaiLUpzlso">La course à l’IA : La France risque-t-elle de devenir un “territoire servant”?</a> — Loup Cellard : à travers 2 déploiements de datacenters à Bordeaux et Marseille Loup nous démontre comment les territoires peuvent être impactés, les choix politiques locaux, et qui sont les acteurs principaux de ces installations.</li><li><a href="https://www.youtube.com/watch?v=CiSjXJNvB1Q">Et si on ouvrait le capot de PostgreSQL ?</a> — Benjamin Coenen : une bonne conférence pour comprendre comment fonctionne PostgreSQL en interne, et ce qu’implique une création d’index ou un appel vaccum. A voir !</li></ul><p>C’est tout pour cette édition 2026, j’espère que cette lecture vous aura donné envie d’aller visionner quelques conférences, personnellement je suis très satisfait de ce que j’ai pu voir cette année !</p><p><em>Si vous avez aimé cet article ou si vous l’avez trouvé utile, n’hésitez pas à </em>👏<em> ou à le partager ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7ee55ac75891" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/retours-du-devoxx-fr-2026-7ee55ac75891">Retours du Devoxx FR 2026</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Retours du Breizhcamp 2025]]></title>
            <link>https://medium.com/slickteam/retours-du-breizhcamp-2025-939cd0db0dfc?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/939cd0db0dfc</guid>
            <category><![CDATA[tech-conference]]></category>
            <category><![CDATA[junit]]></category>
            <category><![CDATA[jooq]]></category>
            <category><![CDATA[breizhcamp]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Fri, 03 Oct 2025 13:55:52 GMT</pubDate>
            <atom:updated>2025-10-03T13:55:47.589Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/554/1*s2DUgwnqIPurg1NnxJW5Xw.jpeg" /></figure><p>Cette année encore une édition sympathique du Breizhcamp malgré un contexte un peu morose dans la tech rennaise. Slickteam était de nouveau sponsor, et nous avons pu tous venir voir les conférences qui nous intéressaient, voici quelques retours.</p><p><a href="https://www.youtube.com/watch?v=6TJNfVzMRWk"><strong>Sortir des ORM avec JooQ</strong></a><strong> — Samuel Lefebvre et Sylvain Decout</strong></p><p>Samuel et Sylvain de Shodo nous ont présenté un workshop sur <a href="https://www.jooq.org/">JooQ</a>. C’est un framework qui génère une api à partir du modèle de la base de donnée, et permet d’écrire des requêtes en java directement. Avec JooQ, plus besoin d’ORM.</p><p>Ils ont commencé par nous faire une présentation technique du framework, et un retour de leur propre expérience. Ensuite nous sommes passé à la pratique avec les exercices du workshop, qui est bien fait et permet de voir l’utilisation de JooQ dans différents cas, avec une montée en puissance progressive. Les exercices consistent en un remplacement d’un appel via un repo JPA par une requête JooQ. Ainsi, ils démontrent aussi par la pratique qu’une migration peut se faire progressivement dans une base de code.</p><p>Vous pouvez trouver le code du workshop <a href="https://github.com/sylvaindecout/jooq-handson">ici</a>, si cela vous intéresse je vous conseille la vidéo puis les exercices pour avoir une bonne idée des capacités de l’outil. Personnellement, je pense que sur un futur projet nous testerons pour voir sur le long terme comment cela se passe niveau maintenance et appréhension par les équipes. Je suis plus convaincu par JooQ que la dernière conférence que j’ai vu il y a plusieurs années, ne reste plus qu’à l’utiliser pour de vrai.</p><p><a href="https://www.youtube.com/watch?v=2AjzzJEILW8"><strong>Rendre ses tests concis et évolutifs grâce à JUnit5 &amp; cie</strong></a><strong> — Juliette de Rancourt</strong></p><p>Juliette est développeuse chez Shodo et contributrice sur <a href="https://junit.org/">JUnit5</a>, et nous a presenté différents outils et méthodes de JUnit5 afin de rendre nos tests plus maintenables. JUnit 5 a déjà 8 ans, et malgré tout beaucoup d’entre nous ne le maîtrisent pas vraiment, et <a href="https://github.com/junit-team/junit-framework/releases/tag/r6.0.0-M2">JUnit6</a> est en pleine préparation.</p><p>Tout d’abord JUnit n’est pas fait pour fournir des outils d’assertion complexes, mieux vaut privilégier des librairies spécifiques du type <a href="https://assertj.github.io/doc/">AssertJ</a>. De même avec AssertJ, il est possible de créer <a href="https://assertj.github.io/doc/#assertj-core-custom-assertions-creation">ses propres assertions</a> afin de rendre les tests plus lisibles (et éviter les longues suites d’assertions en fin de test).</p><p>Il est possible de paramétrer des tests avec <em>@ParameterizedTest</em> (avec ‘name’ pour rendre le rapport plus lisible) et avoir différentes sources pour les valeurs a injecter dans le test (<em>@ValueSource</em>, <em>@CsvSource</em>, <em>@MethodSource</em>, <em>@EmptySource</em>, <em>@NullSource</em>, <em>@ArgumentsSource</em>, …). Ainsi un même test permet de valider plusieurs cas directement suivant les paramètres.</p><p>Les petites astuces dont elle nous parlé :</p><ul><li><em>@DisplayName</em> pour avoir un nom plus parlant dans le rapport, et il est possible d’utiliser un display name generator</li><li><a href="https://www.datafaker.net/">DataFaker</a> pour générer des données aléatoires</li><li>Modifier la config pour avoir le nouveau format de rapport XML</li><li><a href="https://github.com/ota4j-team/open-test-reporting">open-test-reporting-cli</a> pour transformer (entre autres) le rapport XML en HTML</li><li><a href="https://github.com/approvals/ApprovalTests.java">ApprovalTest</a> qui permet notamment avec un fichier approved.json de comparer le résultat d’un test avec juste ‘verifyJson()’</li></ul><p>Si vous utilisez Spring, il est préférable d’annoter vos classes de test avec <em>@DataJpaTest</em> ou <em>@WebMvcTest</em> suivant vos tests car cela permet de charger uniquement une partie du contexte Spring et pas tout le contexte de votre application.</p><p>Elle a évoqué pleins d’autres subtilités et astuces, sa conférence était très intéressante, je vous la recommande chaudement !</p><p><em>Si vous avez aimé cet article ou si vous l’avez trouvé utile, n’hésitez pas à </em>👏<em> ou à le partager ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=939cd0db0dfc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/retours-du-breizhcamp-2025-939cd0db0dfc">Retours du Breizhcamp 2025</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to manage a PunchOut Catalog L1 in SAP and get it done !]]></title>
            <link>https://medium.com/slickteam/how-to-manage-a-punchout-catalog-l1-in-sap-and-get-it-done-42c7de2d6356?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/42c7de2d6356</guid>
            <category><![CDATA[punchout-catalog]]></category>
            <category><![CDATA[ariba-punchout]]></category>
            <category><![CDATA[spring-boot]]></category>
            <category><![CDATA[sap]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Mon, 29 Sep 2025 08:29:32 GMT</pubDate>
            <atom:updated>2025-09-29T08:29:32.430Z</atom:updated>
            <content:encoded><![CDATA[<h3>How to manage a PunchOut Catalog L1 in SAP and get it done !</h3><figure><img alt="SAP Ariba and SpringBoot logos" src="https://cdn-images-1.medium.com/max/1024/1*63nK4yBHdT-izxMFybB7Rg.jpeg" /></figure><p>At Slickteam we get projects from clients of different sectors, and for one client we have made an application that get orders from SAP. After some time, a client of our client asked to have a PunchOut Catalog to manage their quotation requests. OK ! So, what’s a PunchOut Catalog ?</p><p>A PunchOut Catalog in SAP offer the possibility to access directly the supplier’s catalog and to get articles in the cart in SAP. For the client, it’s easier to manage authorisations, budgets limits, … in that way because all these rules are defined in the ERP. You have 2 levels of integration for PunchOut catalogs in SAP:</p><ul><li><strong>Level 1</strong>: the buyer is connected to the supplier website through an iFrame directly in SAP, and the supplier website is responsible to send the articles for the order in SAP.</li><li><strong>Level 2</strong>: all the supplier’s catalog is pushed in SAP, and the buyer can select the articles directly in SAP. It’s all integrated.</li></ul><p>In our case, since there was no real catalog, we had to create an interface that will be integrated as a PunchOut Level1. Our application was developed with <a href="https://spring.io/projects/spring-boot">SpringBoot</a> and <a href="https://www.thymeleaf.org/">Thymeleaf</a>, and we got some issues… We will see that !</p><p>There is a process to declare your PunchOut catalog in SAP, but I will not talk about it here, there is good SAP documentation for that. What interests us developers is what’s coming next !</p><p>The user session in your catalog will go like this:</p><ul><li><strong>PunchOutSetupRequest:</strong> the first request from SAP, and with that you will authenticate the request, the user, and initiate the session.</li><li><strong>PunchOutSetupResponse:</strong> the response for the request, in which you will give SAP the link to your application with a session ID or a token (we managed it with a token, to be stateless).</li><li><strong>PunchOutOrderMessage:</strong> the message that your application will send to SAP with the articles the buyer wants to order.</li></ul><p>All these objects are described in the CXML documentation, you can get that in the <a href="https://www.cxml.org/index.html">official website</a>.</p><p>Now that you have all the context, what was tricky for us ?</p><p>Our first issue was that the website is presented in an iFrame inside SAP, and SpringBoot 3.4 goes with some default configuration that does not authorise it. The HTTP header <a href="https://developer.mozilla.org/fr/docs/Web/HTTP/Reference/Headers/X-Frame-Options"><em>X-Frame-Options</em></a> is set to <em>DENY</em> by default, and since it is deprecated, you can not authorise it anymore in Spring. To make it work you have to add CSP rules, and since SAP has multiple domains, this is the rule we adopted:</p><pre>Content-Security-Policy: frame-ancestors &#39;self&#39; https://*.ariba.com</pre><p>To enable it, we added this configuration in our WebSecurityConfig:</p><pre>@Bean<br>SecurityFilterChain resourceServerFilterChain(HttpSecurity httpSecurity) throws Exception {<br>    ...<br>    httpSecurity.headers(headers -&gt; headers<br>            .contentSecurityPolicy(csp -&gt; csp<br>                    .policyDirectives(&quot;frame-ancestors &#39;self&#39; https://*.ariba.com&quot;)<br>            )<br>    );<br>    ...<br>    return httpSecurity.build();<br>}</pre><p>Our website is now correctly displayed on SAP ! Next issue, the management of the user session.</p><p>We were unsure of how the application will react inside the iFrame on the client browser, so we decided to have what we needed for the session inside a token. And since the token has a creation date, it can expire.</p><p>The token is an encrypted value that goes along the pages where the user wants to go, it is passed on each request for the backend. We added some data from the PunchOutSetupRequest, such as BuyerCookie, that is required for the PunchOutOrderMessage along the articles for the cart.</p><p>It is simple to manage and can work on any environment, without worrying about company policies, SAP rules or other stuff. And now, the last thing to do, push our articles to the cart !</p><p>To push the items in the client’s cart in SAP, the first step is to build the PunchOutOrderMessage with the items. This is simple, but you must be aware of your client process in SAP to build it correctly. In our case, the classification for an item must be set on a value that is configured in a certain way in SAP, otherwise the client can not transform the cart into an order in SAP. We learned it along our testing with the client, so be careful !</p><p>After you have prepared your POOM to be sent to SAP, this must be done by the client browser. In our implementation, we have an endpoint that returns the POOM to the frontend, and then in javascript we post it using an HTML form to SAP.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/1*3WkNTgwuLsjE_xXyj32NeA.png" /><figcaption>Sending the articles in a POOM to the card in SAP</figcaption></figure><p>Now the process is complete ! Your client’s users can use your PunchOut catalog through SAP, and push items to their cart. Well done !</p><p><em>If you liked this article or you found it useful, don’t hesitate to </em>👏<em> it or to share it ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=42c7de2d6356" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/how-to-manage-a-punchout-catalog-l1-in-sap-and-get-it-done-42c7de2d6356">How to manage a PunchOut Catalog L1 in SAP and get it done !</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[CI-CD] Comment je m'organise avec mes pipelines GitLab ?]]></title>
            <link>https://medium.com/slickteam/ci-cd-comment-je-morganise-avec-mes-pipelines-gitlab-34a9b9c62b6e?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/34a9b9c62b6e</guid>
            <category><![CDATA[cicd]]></category>
            <category><![CDATA[gitlab]]></category>
            <category><![CDATA[slickteam]]></category>
            <category><![CDATA[gitlab-ci]]></category>
            <dc:creator><![CDATA[Ronan Morel]]></dc:creator>
            <pubDate>Thu, 22 May 2025 11:02:27 GMT</pubDate>
            <atom:updated>2025-05-23T14:47:52.616Z</atom:updated>
            <content:encoded><![CDATA[<h3>[CI-CD] Comment je m&#39;organise avec mes pipelines GitLab ?</h3><p>Avoir un fichier .gitlab-ci.yml clair est essentiel pour assurer une CI/CD efficace. Comprendre ce qui déclenche chaque étape de la pipeline, comment ces déclenchements sont configurés et maintenir un flux de travail fluide et prévisible.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WDpjoWonGCFwzTGa" /><figcaption>Photo by <a href="https://unsplash.com/@xoforoct?utm_source=medium&amp;utm_medium=referral">EJ Strat</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Les pipelines, kezako ?</h3><p>Les pipelines dans GitLab sont des éléments clés de cette plateforme, automatisant des processus de développement, de test et de déploiement.</p><p>Les points clés :</p><ul><li><strong>Automatisation </strong>: Réduit les erreurs humaines et accélère le processus de développement.</li><li><strong>Intégration Continue </strong>: Assure que le code est toujours dans un état déployable.</li><li><strong>Déploiement Continu </strong>: Permet des mises à jour fréquentes et fiables des applications.</li><li><strong>Traçabilité </strong>: Fournit des logs détaillés et des rapports pour chaque job, facilitant le débogage et l’audit.</li></ul><p>Un fichier .gitlab-ci.yml ressemble à ceci :</p><pre>stages:<br>  - build<br>  - test<br>  - deploy<br><br>build_job:<br>  stage: build<br>  script:<br>    - echo &quot;Building the project...&quot;<br>    - ./build.sh<br><br>test_job:<br>  stage: test<br>  script:<br>    - echo &quot;Running tests...&quot;<br>    - ./test.sh<br><br>deploy_job:<br>  stage: deploy<br>  script:<br>    - echo &quot;Deploying the project...&quot;<br>    - ./deploy.sh</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*87pnXHo1MZZqLBVnBQCEXw.png" /><figcaption>Exemple de CI/CD tiré de la documentation de Gitlab.com</figcaption></figure><p>Une pipeline est composée de “stage”, qui eux-mêmes comprennent des jobs.</p><h3>Zoom sur les conditions de déclenchement des jobs</h3><h4>Avec only</h4><pre>job1:<br>  script: echo &quot;Ce travail s&#39;exécute uniquement pour les push sur la branche main.&quot;<br>  only:<br>    - push<br>    - main<br><br>job2:<br>  script: echo &quot;Ce travail s&#39;exécute uniquement pour les merge requests.&quot;<br>  only:<br>    - merge_requests</pre><blockquote>L’utilisation du mot-clé only dans GitLab CI est désormais dépréciée ; il est recommandé d&#39;utiliser rules pour définir les conditions d&#39;exécution des travaux.</blockquote><h4>Avec rules</h4><pre>job1:<br>  script: echo &quot;Ce travail s&#39;exécute uniquement pour les push sur la branche main.&quot;<br>  rules:<br>    - if: &#39;$CI_PIPELINE_SOURCE == &quot;push&quot; &amp;&amp; $CI_COMMIT_BRANCH == &quot;main&quot;&#39;<br><br>job2:<br>  script: echo &quot;Ce travail s&#39;exécute uniquement pour les merge requests.&quot;<br>  rules:<br>    - if: &#39;$CI_PIPELINE_SOURCE == &quot;merge_request_event&quot;&#39;</pre><p>Avec le mot-clé only, la prise en main des conditions de déclenchement des jobs dans GitLab CI était plus simple et intuitive, facilitant la définition rapide de règles basiques pour l&#39;exécution des travaux. Cependant, bien que only soit facile à utiliser pour des cas simples, il présente des limitations en termes de flexibilité et de complexité des conditions.</p><p>rules offre une approche plus puissante et expressive pour définir des conditions d&#39;exécution, permettant de créer des règles plus complexes et nuancées. Avec rules, il est possible de combiner plusieurs conditions, d&#39;utiliser des expressions logiques avancées, et de mieux contrôler le comportement des pipelines CI/CD. Ainsi, bien que only soit plus simple pour les débutants, rules permet de répondre à des besoins plus sophistiqués en matière d&#39;automatisation des workflows.</p><h3>Les events de déclenchement</h3><p>C’est le moyen par lequel sont déclenchés les pipelines Gitlab. C’est essentiellement avec la variable CI_PIPELINE_SOURCE que l’on peut déterminer la source de déclenchement (push, web, schedule merge_request_event …). Les valeurs sont affichées sur cette page de la <a href="https://docs.gitlab.com/ee/ci/jobs/job_rules.html#ci_pipeline_source-predefined-variable">documentation Gitlab</a>.</p><p>Pour ma part, je me suis inspiré de <a href="https://docs.gitlab.com/ee/ci/jobs/job_rules.html#run-jobs-only-in-specific-pipeline-types">ce tableau (présent aussi sur la doc Gitlab)</a>, pour construire les différents scénarios de déclenchement.</p><h3>Scenario de test</h3><p>Pour cet article, j’ai pris pour exemple un projet de base Node.js, avec un seul fichier source de test. L’idée est de montrer une pipeline Gitlab avec un projet type Node.js.</p><h4>Les étapes de la pipeline</h4><h4>Stages</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b55a3d767779392bc23d8e8b524b8fbf/href">https://medium.com/media/b55a3d767779392bc23d8e8b524b8fbf/href</a></iframe><h4>Jobs</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8df989b866f6a133daeb760ef196ae75/href">https://medium.com/media/8df989b866f6a133daeb760ef196ae75/href</a></iframe><p>Je reviendrai sur les triggers en peu plus loin de l’article.</p><h3>Mon organisation de branche et pipeline</h3><h4>Branche main</h4><p>Dans mon projet exemple, j’ai opté pour une structure avec une seule branche principale, à savoir la branche main. Cela ne correspond donc pas à un cas où l’on aura à gérer plusieurs versions en parallèle en production. Dans mon approche, je considère que la branche main est conçue pour être toujours prête pour la mise en production. Cette approche favorise un flux de travail direct et efficace, où chaque modification apportée à la branche main est immédiatement prête à être déployée, assurant ainsi intégrations et livraisons continues fluides et sans complications inutiles.</p><p>Il est important de noter qu’adopter une seule branche principale, telle que main, augmente considérablement le niveau de responsabilité pour ceux qui gèrent les merges vers cette branche. En effet, chaque modification fusionnée dans main est potentiellement prête à être déployée en production. Cela exige une vigilance accrue et une rigueur dans les processus de revue de code et de test, afin de garantir que chaque modification est stable, fonctionnelle et prête pour un environnement de production. Les contributeurs doivent s&#39;assurer que leur code est bien testé et revu avant d&#39;être fusionné, minimisant ainsi les risques d&#39;introduire des erreurs ou des instabilités dans l&#39;application.</p><p>Dans la configuration de l’exemple, la pipeline CI/CD est conçue pour déployer automatiquement l’application vers un environnement de staging dès qu’un push est effectué sur la branche main</p><h4>Tags</h4><p>Dans ce projet exemple, l’application d’un tag ne se limite pas à la simple identification d’une version. Elle sert également de déclencheur pour la pipeline CI/CD. Lorsqu’un tag est poussé dans le dépôt, cela initie automatiquement le processus de déploiement vers l’environnement en production. Cette méthode garantit que seules les versions explicitement marquées et validées sont mises en production, renforçant ainsi la stabilité et la fiabilité du processus de livraison.</p><h4>Branche sans MR</h4><p>Les branches qui n’ont pas de merge request associée ne déclenchent aucune pipeline CI/CD pour ce projet. Ces branches sont principalement utilisées pour permettre aux développeurs de travailler de leur côté sur une fonctionnalité spécifique, sans interférer avec le code principal, et cela évite aussi de sur-utiliser les pipelines lorsqu’on n&#39;en a pas besoin.</p><h4>Branche avec MR</h4><p>Au contraire des branches sans MR, les branches avec MR réagissent comme la branche main, à la différence, il n’y a pas exactement les mêmes jobs qui se déclenchent. Par exemple, le packaging et le déploiement vers l’environnement de staging ne se déclenchent pas automatiquement, mais manuellement par un utilisateur depuis l’interface web de Gitlab.</p><h3>Déclaration des rules</h3><pre>.rules_tags_template: &amp;rules_tags<br>  if: &quot;$CI_COMMIT_TAG != null&quot;<br><br>.rules_web_template: &amp;rules_web<br>  if: &#39;$CI_PIPELINE_SOURCE == &quot;web&quot; &amp;&amp; $CI_COMMIT_BRANCH != &quot;main&quot; &amp;&amp; $CI_COMMIT_TAG == null&#39;<br><br>.rules_main_template: &amp;rules_main<br>  if: &#39;($CI_PIPELINE_SOURCE == &quot;push&quot; || $CI_PIPELINE_SOURCE == &quot;web&quot;) &amp;&amp; $CI_COMMIT_BRANCH == &quot;main&quot;&#39;<br><br>.rules_merge_request_template: &amp;rules_merge_request<br>  if: &#39;$CI_PIPELINE_SOURCE == &quot;merge_request_event&quot;&#39;<br><br>.rules_default_template: &amp;rules_default<br>  when: never</pre><p>J’ai créé des références pour les rules afin de les définir une seule fois dans le fichier .gitlab-ci.yml. Après cela, je les ai appelées dans les jobs pour avoir une meilleure lisibilité des jobs et avoir un aperçu rapide de quand est-ce que les jobs seront déclenchés.</p><p>Voici une description de chaque rule que j’ai défini pour le projet exemple :</p><ul><li>rules_tags Déclencheur lorsqu’un tag est créé</li><li>rules_web Déclencheur depuis l’interface web de Gitlab</li><li>rules_main Déclencheur lorsqu’un push est fait sur la branche main</li><li>rules_merge_request Déclencheur lorsqu’il y a un événement sur une merge request</li><li>rules_default Règle par défaut que je mets à chaque job. Par défaut, dans cet exemple, tous les jobs ne seront jamais déclenchés.</li></ul><h4>Description des triggers du projet exemple</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/258b7dc2be0129bcdf95cbbcdbaa3987/href">https://medium.com/media/258b7dc2be0129bcdf95cbbcdbaa3987/href</a></iframe><h3>Test des scénarios</h3><h4>Sur la branche sans MR</h4><p>Par défaut, il n’y a pas de pipeline de créée dans ce cas-ci. Le seul cas où l’on peut créer une pipeline, c’est en passant par l’interface web de Gitlab.</p><h4>Sur la branche avec MR</h4><p>Suite à un push (ou via le web), une pipeline est créée avec le tag merge_request pour signifier que c’est relié à une MR.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ePJ2YXv0hP0rYw_1dWE9DA.png" /></figure><h4>Sur Main</h4><p>Suite à un push (ou via le web), une pipeline est créée et se déroule “spécifiquement” pour une mise en ligne dans l’environnement de staging.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8q2L8Lm49QDb7zpRuDLQvg.png" /></figure><h4>Avec la création d’un tag</h4><p>Enfin, sur la création d’un tag, une pipeline est créée, liée à ce dernier et déroule le processus spécifique à la mise en production.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o-V3emgE1rqJ_t6cnHVzng.png" /></figure><h3>Conclusion</h3><p>Je suis convaincu que maîtriser pleinement toute la structure liée à l’intégration continue / déploiement continue permet de gérer plus efficacement les flux de travail, en assurant que chaque modification est testée et validée avant d’être déployée.</p><p>Cependant, il est évident qu’il existe de nombreuses autres approches et configurations possibles pour gérer l’intégration et la livraison continue. L’exemple fourni ici n’est qu’une des nombreuses façons d’aborder ce sujet, et il est important de reconnaître que chaque projet peut avoir des besoins et des contraintes uniques qui nécessitent des solutions adaptées.</p><p>L’essentiel est de trouver un équilibre qui convienne à l’équipe et au projet, tout en garantissant la qualité et la stabilité du code.</p><p>Lien du dépôt Gitlab : <a href="https://gitlab.com/ronronan/gitlab-ci-cd-article">https://gitlab.com/ronronan/gitlab-ci-cd-article</a></p><p><em>Si vous avez apprécié cet article, n’hésitez pas à 👏 ou à le partager.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=34a9b9c62b6e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/ci-cd-comment-je-morganise-avec-mes-pipelines-gitlab-34a9b9c62b6e">[CI-CD] Comment je m&#39;organise avec mes pipelines GitLab ?</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Publier sur Maven Central via l’API de publication avec JReleaser et Github Action]]></title>
            <link>https://medium.com/slickteam/publier-sur-maven-central-via-lapi-de-publication-avec-jreleaser-et-github-action-9559e2ed511e?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/9559e2ed511e</guid>
            <category><![CDATA[jreleaser]]></category>
            <category><![CDATA[gradle]]></category>
            <category><![CDATA[maven-central]]></category>
            <category><![CDATA[github-actions]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Thu, 15 May 2025 15:39:32 GMT</pubDate>
            <atom:updated>2025-05-15T15:39:32.446Z</atom:updated>
            <content:encoded><![CDATA[<p>Pour un projet client, nous utilisons <a href="https://github.com/Slickteam/hubspot-java">une librairie opensource</a> qui sert d’API vers HubSpot. Afin de pouvoir l’utiliser simplement, nous l’avons publiée sur Maven Central. Voici comment :</p><p>Tout d’abord, pour pouvoir publier sur Maven Central, il vous faudra un compte sur <a href="https://central.sonatype.com/">https://central.sonatype.com/</a>. Après, dans l’interface sonatype, vous devez générer un token d’accès depuis la page <a href="https://central.sonatype.com/account">“My Account” :</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AhwZIXGNro0d_i7i4aK5KA.png" /><figcaption>Interface de Maven Central pour le génération de token</figcaption></figure><p>Une fois les paramètres du token récupérés, mettez-les de côté pour une configuration future.</p><p>Maintenant, vous allez avoir besoin d’une clé GPG. Si vous êtes sur Linux, vous pouvez utiliser la commande <em>gpg</em> pour en générer une :</p><pre>$ gpg --gen-key</pre><p>Vous pouvez vérifier que votre nouvelle clé a bien été créé ainsi :</p><pre>$ gpg --list-keys<br>[keyboxd]<br>---------<br>pub   ed25519 2025-03-24 [SC] [expire : 2028-03-23]<br>      00A000B00DF0000X00D000E000F00C00B0000<br>uid          [  ultime ] Ronan Barbot &lt;ronan.barbot@slickteam.fr&gt;<br>sub   cv25519 2025-03-24 [E] [expire : 2028-03-23]</pre><p>La chaîne <em>00A000B00DF0000X00D000E000F00C00B0000</em> correspond à l’ID de votre clé. Nous allons en avoir besoin pour publier cette clé sur un serveur de clé GPG, afin que la CI puisse la récupérer et l’utiliser pour signer l’artefact :</p><pre>$ gpg --keyserver keyserver.ubuntu.com --send-keys 00A000B00DF0000X00D000E000F00C00B0000</pre><p>Ainsi votre clé se trouve sur le serveur keyserver.ubuntu.com (ou celui de votre choix) et notre future action Github pourra la récupérer pour signer le package.</p><p>Ensuite, il faut configurer le fichier de build afin d’avoir les informations nécessaires pour le package. Notre build se fait avec Gradle et le DSL Kotlin, nous avons déclaré les plugins suivants :</p><pre>plugins {<br>    `java-library`<br>    `maven-publish`<br>}</pre><p>Puis, nous avons configuré le build :</p><pre>java {<br>    withJavadocJar()<br>    withSourcesJar()<br>}<br><br>tasks.jar{<br>    enabled = true<br>    archiveClassifier.set(&quot;&quot;)<br>}<br><br>publishing {<br>    publications {<br>        create&lt;MavenPublication&gt;(&quot;maven&quot;) {<br>            from(components[&quot;java&quot;])<br>            withBuildIdentifier()<br>            pom {<br>                name.set(&quot;hubspot-java&quot;)<br>                description.set(&quot;Java Wrapper for HubSpot API&quot;)<br>                url.set(&quot;https://github.com/Slickteam/hubspot-java&quot;)<br>                licenses {<br>                    license {<br>                        name.set(&quot;GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007&quot;)<br>                        url.set(&quot;https://www.gnu.org/licenses/gpl-3.0.txt&quot;)<br>                    }<br>                }<br>                developers {<br>                    developer {<br>                        id.set(&quot;DepositFix&quot;)<br>                        name.set(&quot;DepositFix&quot;)<br>                    }<br>                    developer {<br>                        id.set(&quot;Slickteam&quot;)<br>                        name.set(&quot;Slickteam&quot;)<br>                    }<br>                }<br>                scm {<br>                    connection.set(&quot;scm:git:https://github.com/Slickteam/hubspot-java.git&quot;)<br>                    developerConnection.set(&quot;scm:git:git@github.com:Slickteam/hubspot-java.git&quot;)<br>                    url.set(&quot;https://github.com/Slickteam/hubspot-java&quot;)<br>                }<br>            }<br>        }<br>    }<br>    repositories {<br>        maven {<br>            url = layout.buildDirectory.dir(&quot;staging-deploy&quot;).get().asFile.toURI()<br>        }<br>    }<br>}</pre><p>Les étapes de build ainsi que les informations nécessaires pour la publication de la librairie sont configurées. Nous pouvons construire un package qui sera conforme aux prérequis pour la publication sur Maven Central.</p><p>Nous avons configuré <a href="https://jreleaser.org/">JReleaser</a> afin qu’il publie notre artefact sur <a href="https://jreleaser.org/guide/latest/examples/maven/maven-central.html#_portal_publisher_api">Maven Central</a> de cette façon :</p><pre>plugins {<br>    signing<br>    id(&quot;org.jreleaser&quot;) version &quot;1.17.0&quot;<br>}<br><br>jreleaser {<br>    gitRootSearch = true<br><br>    project {<br>        description = &quot;Java Wrapper for HubSpot API&quot;<br>        license = &quot;GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007&quot;<br>    }<br><br>    signing {<br>        setActive(&quot;ALWAYS&quot;)<br>        armored = true<br>    }<br>    deploy {<br>        setActive(&quot;ALWAYS&quot;)<br>        maven {<br>            setActive(&quot;ALWAYS&quot;)<br>            mavenCentral {<br>                create(&quot;sonatype&quot;) {<br>                    setActive(&quot;ALWAYS&quot;)<br>                    url.set(&quot;https://central.sonatype.com/api/v1/publisher&quot;)<br>                    stagingRepositories.add(&quot;build/staging-deploy&quot;)<br>                }<br>            }<br>        }<br>    }<br><br>    release {<br>        github {<br>            skipRelease = true<br>            skipTag = true<br>            overwrite = false<br>            token = &quot;none&quot;<br>        }<br>    }<br>}</pre><p>Le dépôt de staging standard est configuré pour le téléversement sur Maven Central, le service fera de lui-même la promotion du package en public.</p><p>Dernier point à réaliser, l’action Github. Pour cela, nous avons fait une action Github qui est déclenchée sur la création de tag et qui lance la cible JReleaser avec Gradle (.github/workflows/release.yml) :</p><pre>name: Publish package to the Maven Central Repository<br>on:<br>  push:<br>    tags:<br>      - v*<br>  pull_request:<br>    branches: [ main ]<br>jobs:<br>  publish:<br>    runs-on: ubuntu-latest<br>    steps:<br>      - uses: actions/checkout@v3<br>      - name: Set up Java<br>        uses: actions/setup-java@v3<br>        with:<br>          java-version: &#39;17&#39;<br>          distribution: &#39;adopt&#39;<br>      - name: Run chmod to make gradlew executable<br>        run: chmod +x ./gradlew<br>      - name: Publish package to local staging directory<br>        run: ./gradlew :publish<br>      - name: Publish package to maven central<br>        env:<br>          JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }}<br>          JRELEASER_MAVENCENTRAL_PASSWORD: ${{ secrets.JRELEASER_MAVENCENTRAL_PASSWORD }}<br>          JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }}<br>          JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }}<br>          JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}<br>          JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}<br>        run: ./gradlew :jreleaserDeploy -DaltDeploymentRepository=local::file:./build/staging-deploy</pre><p>Comme vous pouvez le voir, il y a 5 variables d’environnement à configurer dans GitHub :</p><ul><li>JRELEASER_MAVENCENTRAL_USERNAME : le nom d’utilisateur de votre token sonatype</li><li>JRELEASER_MAVENCENTRAL_PASSWORD : le mot de passe de votre token sonatype</li><li>JRELEASER_GPG_PASSPHRASE : passphrase de votre clé GPG</li><li>JRELEASER_GPG_SECRET_KEY : votre clé secrète GPG en base 64 ($gpg --export-secret-keys &lt;key id&gt; | base64)</li><li>JRELEASER_GPG_PUBLIC_KEY : votre clé secrète GPG en base 64 ($gpg --export &lt;key id&gt; | base64)</li></ul><p>Une fois terminé, l’application et la CI sont prêtes, ne reste plus qu’à faire un tag !</p><p>Lorsque vous faites votre nouveau tag, vous devriez voir l’action s’exécuter dans Github :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NXXyU-1M-WRH0agCS4otvw.png" /><figcaption>Action Github “release” avec le job “publish” ok</figcaption></figure><p>Puis après quelques minutes, le déploiement doit apparaître dans votre compte sur Maven Central :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JyzwB1QejrGWilOqz8s8jQ.png" /><figcaption>Déploiement publié dans mon compte maven central</figcaption></figure><p>Si vous voulez vérifier, dans la recherche de package dans le dépôt central, que votre package doit être disponible :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sD5e9AGwQ8bVA1atxKZ7Ig.png" /><figcaption>Package apparaissant dans les résultats de la recherche sur Maven Central</figcaption></figure><p>J’espère que ce tuto vous sera utile. Pour mon premier déploiement, je me suis basé sur <a href="https://dev.to/tschuehly/how-to-publish-a-kotlinjava-spring-boot-library-with-gradle-to-maven-central-complete-guide-402a">l’article</a> de <a href="https://dev.to/tschuehly">Thomas Schühly</a> sur dev.to. J’ai adapté certaines parties, car OSSRH est désormais déprécié depuis la migration du nouveau Maven Central.</p><p><em>Si vous avez aimé cet article ou si vous l’avez trouvé utile, n’hésitez pas à </em>👏<em> ou à le partager ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9559e2ed511e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/publier-sur-maven-central-via-lapi-de-publication-avec-jreleaser-et-github-action-9559e2ed511e">Publier sur Maven Central via l’API de publication avec JReleaser et Github Action</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Devoxx France 2025 — retours à chaud après une édition une nouvelle fois très intéressante !]]></title>
            <link>https://medium.com/slickteam/devoxx-france-2025-retours-%C3%A0-chaud-apr%C3%A8s-une-%C3%A9dition-une-nouvelle-fois-tr%C3%A8s-int%C3%A9ressante-563d8b14aec9?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/563d8b14aec9</guid>
            <category><![CDATA[devoxxfr]]></category>
            <category><![CDATA[devoxx]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Wed, 30 Apr 2025 15:06:34 GMT</pubDate>
            <atom:updated>2025-05-14T08:55:48.205Z</atom:updated>
            <content:encoded><![CDATA[<h3>Devoxx France 2025 — retours à chaud après une édition une nouvelle fois très intéressante !</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*08iAMkmFts1bK0LgdbOFLQ.png" /><figcaption>Image du thème de l’année 2025 : retour aux sources</figcaption></figure><p>Cette année encore il y avait de belles conférences pour ce <a href="https://www.devoxx.fr/">Devoxx France</a> 2025, certains choix ont été durs pour déterminer quelles conférences privilégier. Je vous propose un retour à chaud sur celles qui m’ont le plus marquées.</p><p><a href="https://www.youtube.com/watch?v=F_Qyo1cCpvY&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=216"><strong>Null Safety en Java avec JSpecify et NullAway</strong></a> — <em>Sébastien Deleuze</em></p><p>Sébastien a commencé par présenter <a href="https://jspecify.dev/">JSpecify</a>, et plus précisément le chemin qui avait abouti à cette librairie. JSpecify est une librairie issue de la réflexion de plusieurs gros acteurs du monde Java (Broadcom- ex Pivotal, Google, …). Le but premier a été de réaliser <a href="https://jspecify.dev/docs/spec/">une spécification</a> pour définir la sémantique ainsi que les concepts derrière chaque nouvelle annotation. Il a fallu 5 ans pour aboutir au résultat, c’est-à-dire 4 nouvelles annotations, et une librairie sous license Apache2.</p><p>Premier point : pourquoi Optional n’est-il pas suffisant ?</p><ul><li>C’est une classe qui nécessite une encapsulation, du coup il y a un overhead en mémoire par rapport au type simple.</li><li>Cela casse les signatures des méthodes. Pour mettre à jour une base de code ou une librairie, le coût et les impacts peuvent être conséquents.</li><li>Il ne faut l’utiliser que pour des valeurs de retours, donc on ne peut couvrir tout notre code.</li><li>Son utilisation génère du bruit, le code est un peu plus long à déchiffrer pour un développeur.</li></ul><p>Les nouvelles annotations :</p><ul><li>@Nullable : un élément peut être nullable</li><li>@NonNull : un élément ne peut être null</li><li>@NullUnMarked : définit pour une classe, un package ou un module que la nullité des éléments de l’ensemble est non-spécifiée, c’est-à-dire inconnue</li><li>@NullMarked : définit pour une classe, un package ou un module que la nullité des éléments de l’ensemble n’est pas autorisée</li></ul><p>Les avantages de JSpecify :</p><ul><li>L’annotation @NullMarked peut être ajoutée dans le fichier package-info à la racine d’un package, et ainsi définir la non nullité par défaut de tout le code compris dans le package. Il faudra spécifier cas par cas avec @Nullable ce qui peut être null.</li><li>Si le code est bien spécifié, des warnings sont remontés dans l’IDE pour pouvoir traiter les cas directement durant la phase de développement initiale.</li><li>Il permet la vérification sur les génériques, la tableaux, les éléments d’un tableau.</li></ul><p>Kotlin reconnaît les annotations JSpecify depuis la version 1.5.20, les warnings remonteront donc dans l’IDE si vous utilisez des librairies avec JSpecify dans votre projet Kotlin.</p><p>Tout ça c’est bien, mais en fait la détection d’un élément nullable mal géré ne casse pas le build. C’est là qu’intervient <a href="https://github.com/uber/NullAway">NullAway</a>. C’est un plugin pour l’outil <a href="https://errorprone.info/">errorprone</a> qui permet d’effectuer un certain nombre de contrôles au build et ainsi évite que ces possibles problèmes ne se passent au runtime.</p><p>Pour l’utiliser vous devez ajouter dans votre build errorprone puis son plugin NullAway. Ainsi la vérification des annotations JSpecify sera correctement faite lors du build et celui-ci cassera en cas de mauvaise gestion des valeurs nullables dans le code.</p><p>Sébastien fait partie de l’équipe de développement de Spring, Spring Framework 7, Springboot 4 et toute la galaxie des projets Spring devrait être null-safe d’ici la fin de l’année. Il n’y a plus qu’a faire de même sur nos projets !</p><p><a href="https://www.youtube.com/watch?v=eSGbZM3XEpg&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=230"><strong>La territorialisation des infrastructures comme levier de pouvoir</strong></a> — <em>Ophélie Coelho</em></p><p>En ces temps de contexte géopolitique mouvant, la seconde keynote du jeudi était intéressante. Ophélie est chercheuse indépendante spécialisée dans la géopolitique du numérique.</p><p>Elle a commencé par nous parler des cables télégraphiques sous-marins, qui, au début du 20ème siècle, étaient la propriété exclusive de l’empire britannique. Lors du conflit entre l’empire russe et l’empire japonais l’accès au réseau est devenu un moyen de pression géopolitique pour agir contre les russes.</p><p>Ensuite elle a parlé de l’Afrique à travers différentes cartes, montrant que nos environnements virtuels sont extrêmement ancrés dans un environnement physique, et donc des territoires, et donc liés aux décisions politiques des dirigeants de ces mêmes territoires. Mais, actuellement, au-delà de la géopolitique, le pouvoir des big tech pose également question. Par exemple, Google possède plusieurs dizaines de câbles sous-marin, dont une dizaine à 100%. Cela leur donne potentiellement un pouvoir de décision et de pression énorme.</p><p>Elle a terminé sa keynote par une cartographie qu’elle en train de réaliser pour mesurer le pouvoir de chaque big tech dans différents secteurs. Cela est important car les autres big (oil, pharma, …) sont cantonné à leur secteur. Les big tech sont les seuls a être réellement multi secteurs avec un poids de plus en plus important sur des secteurs qui peuvent être critiques. D’où les questions récentes liées à l’antitrust et au démantèlement de ces groupes tentaculaires et au pouvoir souvent trop important.</p><p><strong>L’IOT pour 5 ans et + : atelier d’initiation sur carte micro:bit</strong> — <em>Jonathan Baranzini et Thomas Cami</em></p><p>Petit atelier fun en début de seconde journée sur la carte <a href="https://microbit.org/fr/">micro-bit</a> faite par une fondation de la BBC. Jonathan a commencé par nous présenter la carte :</p><ul><li>Carte assez petite</li><li>Plusieurs capacités embarquées (boussole, accéléromètre, leds, port RF, micro, haut-parleur, …)</li><li>Simple pour développer (Bloc, javascript, python nativement)</li><li>Peu chère (19€)</li><li>Développement possible directement en ligne, <a href="https://makecode.microbit.org/#">ici</a>, avec en plus un simulateur intégré qui permet de vérifier le fonctionnement avant de pousser le programme sur la carte.</li></ul><p>L’atelier permet d’aborder différentes capacités de la carte, de voir le développement par bloc ou Javascript / Typescript. Il est didactique et certains exercices nécessitent d’être en binôme, ce qui est très sympa. Je vous met le lien vers le déroulé de l’atelier si vous souhaitez vous y essayer avec votre propre carte : <a href="https://jotitan.github.io/microbit-devoxx-2025/">par ici</a>.</p><p>Dans leur société ils utilisent la carte pour faire des katas (exercices de programmation pour appréhender un concept ou une méthode), je trouve que c’est une très bonne idée. De plus, comme la carte a peu de capacité de calcul ou de mémoire, cela contraint un peu plus notre réflexion sur les ressources prises par nos logiciels, chose relativement oubliée de nos jours où les contraintes matérielles n’impactent que très peu d’équipes dans notre industrie.</p><p><a href="https://www.youtube.com/watch?v=sYOldn23bNE&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=107"><strong>PostgreSQL : Le couteau suisse dont vous avez besoin (sans le savoir)</strong></a> — <em>Lætitia Avrot</em></p><p>Après avoir pu enfin profiter des keynotes en amphi bleu, je suis allé prendre une piqûre de rappel et découvrir quelques fonctionnalités de <a href="https://www.postgresql.org/">PostgreSQL</a>.</p><p>Lætitia a commencé par un petit tip que je ne connaissais pas : pour une date ou un timestamp, plutôt que de le déclarer NULLABLE, on peut le mettre NON NULL et attribuer la valeur <em>infinity</em> pour une valeur encore non définie (une date de fin par exemple). Ainsi la valeur NULL sera synonyme d’erreur manifeste et non une valeur probablement vide.</p><p>Ensuite elle nous a présenté des fonctionnalités avec RANGE :</p><ul><li>On peut définir une plage avec soit des limites exclues (par ex: <em>‘(1:5)’::int4range</em> =&gt; plage de 2 à 4) ou incluses (par ex: <em>‘[1:5]’::int4range</em> =&gt; plage de 1 à 5).</li><li>Il existe différents types d’opérateurs pour les plages (je vous renvoie à la vidéo de son talk pour le détail), mais si on souhaite les indexer, tous les opérateurs ne sont pas supportés par tous les types d’index, il faut faire attention lors de sa déclaration.</li><li>On peut donc, avec ses opérateurs, déclarer par exemple une contrainte de non recoupement (dans son exemple, un vélo ne peut être loué sur 2 plages horaires qui se recouvrent).</li></ul><p>Après nous avons plongé dans les colonnes générées, avec de bons rappels pour nous, devs, présents dans la salle et quelques subtilités permises par PostgreSQL :</p><ul><li>Lorsqu’on déclare une séquence puis qu’on fait un nextval() dans un insert, on peut juste remplacer le type de notre id par SERIAL et le tour est joué, plus de séquence ni de nextval().</li><li>Il est possible d’empêcher l’insertion d’une valeur dans une colonne et de laisser la BDD gérer toute seule la valeur de cette colonne. Cela se fait grâce à <em>generated always as</em>.</li><li>On peut calculer la valeur d’une colonne à partir d’une autre colonne, et si la valeur de la colonne de référence change la colonne calculée sera mise à jour.</li><li>Il n’est pas possible de calculer une colonne à partir d’une autre colonne calculée.</li></ul><p>Enfin elle a abordé le full text search, une fonctionnalité présente dans PostgreSQL depuis un certains nombre d’année maintenant.</p><ul><li>Une petite précision au départ pour rappeler que définir un champ en VARCHAR avec une contrainte de taille n’est jamais que le fait d’avoir un champ TEXT avec une contrainte pas forcément cohérente avec le métier (qui peut bouger), autant tout déclarer en TEXT simplement.</li><li>Pour pouvoir effectuer une recherche full text il faut avoir déclarer sa colonne en <em>tsvector</em>, qui enregistre des vecteurs associés à une langue.</li></ul><p>Une conf très intéressante, vous pouvez retrouver les slides <a href="https://l_avrot.gitlab.io/slides/justpg_20250418.html#/">ici</a>.</p><p>Sinon, pour les autres conférences / ateliers auxquels j’ai participé :</p><ul><li><a href="https://www.youtube.com/watch?v=JdxjGZBtp_k&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=226"><strong>L’Intelligence Artificielle n’existe pas</strong></a> — <em>Keynote de Luc Julia</em> : présentation de remise en perspective de ce qu’est l’intelligence et de ce que ne sont pas les IA par Luc Julia, ingénieur spécialisé dans l’IA et co-créateur de Siri (assistant d’Apple)</li><li><strong>HTMX 2.0 et Webcomponents</strong> — <em>Horacio Gonzales et Pierre Zemb</em> : présentation avec des exemples de comment utiliser htmx 2, les web components et comment les réunir. Les slides et le code sont <a href="https://github.com/LostInBrittany/introduction-to-htmx-and-lit">ici</a>.</li><li><strong>Workshop Typescript</strong> — <em>Johan Rouve, Marjorie Aubert et Bastien Tran</em> : workshop assez didactique avec un bon support en ligne pour découvrir certains concepts de Typescript, comme les types génériques ou la hiérarchie des types. Le support est par <a href="https://typescript-workshop.github.io/typescript-workshop-companion/">ici</a> et la code par <a href="https://github.com/typescript-workshop/typescript-workshop">là</a>.</li><li><a href="https://www.youtube.com/watch?v=GDvcpgp2fn8&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=229"><strong>Langage, IA et propagande : la guerre des récits a déjà commencé</strong></a> — <em>Keynote d’Elodie Mielczareck</em> : quel sens pour les mots et discours à l’heure des LLMs et des faits “alternatifs”?</li><li><a href="https://www.youtube.com/watch?v=9KgkYktpGKI&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=82"><strong>Université Quarkus et GenIA</strong></a> —<em> Clément Escoffier et Emmanuel Bernard</em> : présentation de 3 heures sur Quarkus et l’usage des IA génératives à travers les extensions Quarkus. Explications des différentes techniques (chat, RAG, fonctions, MCP) et leur mise en place. Le code est <a href="https://github.com/cescoffier/langchain4j-deep-dive">ici</a> et vous pouvez récupérer les slides <a href="https://drive.usercontent.google.com/download?id=1QtqH6CD-mnDaD2hexiKzb9hHYmOnE1yV&amp;export=download">là</a>.</li><li><strong>BOF Ensemble faisons progresser et grandir les développeurs débutants ! </strong>— <em>Alexandre Touret </em>: un débat intéressant sur les différentes manières de faire progresser les débutants, gérer l’intégration dans l’équipe, la relation avec les managers, et plus globalement faire progresser tout le monde.</li><li><a href="https://www.youtube.com/watch?v=6iv2tbP4nd8&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=228"><strong>Plongez dans l’Ère Quantique : décryptez et anticipez la révolution à venir</strong></a> — <em>Keynote de Fanny Bouton</em> : présentation de ce qu’est l’informatique quantique, où nous en sommes actuellement, vers où nous dirigeons-nous et quelles opportunités vont s’ouvrir dans ce nouveau secteur.</li><li><a href="https://www.youtube.com/watch?v=bO96whMlB8E&amp;list=PLTbQvx84FrATiYy0se8yoHJHicXtmDbB-&amp;index=227"><strong>Les LLM rêvent-ils de cavaliers électriques ?</strong> </a>— <em>Keynote de Thibaut Giraud</em> : les LLM sont-ils des perroquets stochastiques ou peuvent-ils jouer aux échecs avec “réflexion” ? Par le créateur de la chaîne “Monsieur Phi”.</li></ul><p>Cette année encore une belle édition de Devoxx France, avec pleins de présentations et ateliers très intéressants, et l’occasion de discuter et de revoir des gens. Vivement l’année prochaine !</p><p>PS : quand les vidéos sortiront j’ajouterai les liens pour les différentes confs.</p><p>PS2 : Les liens sont là !</p><p><em>Si vous avez aimé cet article ou si vous l’avez trouvé utile, n’hésitez pas à </em>👏<em> ou à le partager ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=563d8b14aec9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/devoxx-france-2025-retours-%C3%A0-chaud-apr%C3%A8s-une-%C3%A9dition-une-nouvelle-fois-tr%C3%A8s-int%C3%A9ressante-563d8b14aec9">Devoxx France 2025 — retours à chaud après une édition une nouvelle fois très intéressante !</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Hibernate is bad for batch saving ? (And how to solve it)]]></title>
            <link>https://medium.com/slickteam/why-hibernate-is-bad-for-batch-saving-and-how-to-solve-it-faed4da4ae81?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/faed4da4ae81</guid>
            <category><![CDATA[orm]]></category>
            <category><![CDATA[spring-jpa]]></category>
            <category><![CDATA[hibernate]]></category>
            <category><![CDATA[sql]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Mon, 28 Apr 2025 08:35:31 GMT</pubDate>
            <atom:updated>2025-04-28T08:35:31.301Z</atom:updated>
            <content:encoded><![CDATA[<h3>Why Hibernate is bad for batch saving ? (And how to solve it)</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s3MRcEaTtcV1XUCVj7jPPg.png" /><figcaption>Hibernate not everywhere, don’t forget SQL !</figcaption></figure><p>Some time ago we had a performance issue on a client application (in production). At first, we saw that the CPU usage was 100%, then we restarted the app so the service can run, and I investigated further.</p><p>After some time analysing it, I found that all databases connections were taken, and no new connection was possible. Since the issue was encountered regularly, I put Spring and Hibernate in debug mode to see in more details what was going on.</p><p>After a while I saw this:</p><pre>2025-01-24T17:00:02.941Z: Hibernate: select i1_0.id,i1_0.value from items i1_0 where i1_0.id=?<br>2025-01-24T17:00:02.950Z: Hibernate: select i1_0.id,i1_0.value from items i1_0 where i1_0.id=?<br>2025-01-24T17:00:02.962Z: Hibernate: select i1_0.id,i1_0.value from items i1_0 where i1_0.id=?<br>2025-01-24T17:00:03.235Z: Hibernate: select i1_0.id,i1_0.value from items i1_0 where i1_0.id=?<br>2025-01-24T17:00:03.533Z: Hibernate: select i1_0.id,i1_0.value from items i1_0 where i1_0.id=?</pre><p>As you can see, there comes the same request again and again, each taking between 10ms and more than 100ms. I searched through the codebase and I found something like this:</p><pre>itemList.forEach(itemRepository::save);</pre><p>So, I changed my code to do it in batch, because I was a little in a hurry and I was thinking that I should search later why there was a select when I wanted to save an entity. My code became this:</p><pre>itemRepository.saveAll(itemList);</pre><p>And… nothing changed… I found this extremely strange: we wanted to save data in batch as fast as possible, but we were getting select request to check if each data we wanted to save was existing in the database. But WHY ?</p><p>After a few tries and research on the web, I found that this was the normal way of acting for Hibernate. <strong>Before saving a data it checks if it exists before. Each and every data, one by one, even in batch.</strong> We wanted to save hundreds of data fast, but this was taking a terrible long time because of this behaviour from the ORM…</p><p>Finally I decided to skip Hibernate for this part and to do a method that will save in batch in SQL directly:</p><pre>public void insertBatch(List&lt;Item&gt; entities) {<br>    if (entities == null || entities.isEmpty()) {<br>        return;<br>    }<br>    StringBuilder query = new StringBuilder(&quot;insert into items values&quot;);<br>    entities.forEach(entity -&gt; query.append(String.format(&quot; (&#39;%s&#39;,&#39;%s&#39;),&quot;,<br>                                                          entity.getId().toString(),<br>                                                          entity.getValue().toString())));<br><br>    entityManager.createNativeQuery(query.substring(0, query.length() - 1))<br>                 .executeUpdate();<br>}</pre><p>Now the code is taking less time to save the data that it was taking to check if ONE data existed.</p><pre>2025-01-24T18:00:11.585Z DEBUG [] 1672 --- [myapp]  ItemRepositoryImpl     :  -- insertBatch - entities.size() = 490<br>2025-01-24T18:00:11.595Z DEBUG [] 1672 --- [myapp]  ItemRepositoryImpl     :  -- insertBatch - done<br>2025-01-24T18:00:11.595Z DEBUG [] 1672 --- [myapp]  ItemRepositoryImpl     :  -- insertBatch - entities.size() = 490<br>2025-01-24T18:00:11.604Z DEBUG [] 1672 --- [myapp]  ItemRepositoryImpl     :  -- insertBatch - done</pre><p>This problem gave me a headache, and this happened on a Friday (obviously). I hope this article will help you if you get the same problem or that it will save you from getting through this.</p><p><em>If you liked this article or you found it useful, don’t hesitate to </em>👏<em> it or to share it ! </em>🙂</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=faed4da4ae81" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/why-hibernate-is-bad-for-batch-saving-and-how-to-solve-it-faed4da4ae81">Why Hibernate is bad for batch saving ? (And how to solve it)</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Coder pour les humains : ce que Devoxx m’a appris au-delà du code]]></title>
            <link>https://medium.com/slickteam/coder-pour-les-humains-ce-que-devoxx-ma-appris-au-del%C3%A0-du-code-a3c15a258b53?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/a3c15a258b53</guid>
            <category><![CDATA[devoxxfr]]></category>
            <category><![CDATA[conference]]></category>
            <category><![CDATA[devoxx]]></category>
            <dc:creator><![CDATA[Audrey Belhoste]]></dc:creator>
            <pubDate>Mon, 28 Apr 2025 08:22:38 GMT</pubDate>
            <atom:updated>2025-04-28T08:22:38.403Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*2ZcifXiSQuLBQSgJyr0JmA.jpeg" /></figure><h3>Coder pour les humains : ce que Devoxx m’a appris au-delà du code</h3><p>Comment choisir parmi une multitude de conférences passionnantes à Devoxx ? Mission presque impossible ! Face aux amphithéâtres parfois complets, j’ai dû improviser et assister à des présentations qui n’étaient pas sur ma liste initiale — plus orientées vers l’humain et le produit que purement techniques. Ce qui m’a rappelé une vérité simple : notre code doit avant tout servir des personnes réelles.</p><h3>Développer moins, mais mieux ?</h3><p>Combien d’entre nous continuent à maintenir des fonctionnalités dans leurs applications que personne n’utilise vraiment ? Combien de features restent dans nos produits simplement parce que personne ne s’est posé la question de leur utilité réelle ?</p><p>En assistant à “Dans les coulisses des géants de la Tech !”, j’ai découvert comment des entreprises remettent en question chaque fonctionnalité, expérimentent constamment et, surtout, suppriment ce qui n’apporte pas de valeur.</p><p><strong>Supprimer des fonctionnalités peut être plus vertueux qu’en ajouter</strong>. Si ce que je développe ne sert pas, ou si l’utilisateur n’y accède jamais, alors pourquoi le garder ? Et surtout, pourquoi continuer à le maintenir ?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vmBIGGw6E8QBQ1BeqcuEww.jpeg" /><figcaption>Slide de Rachel Dubois pendant la conférence Dans les coulisses des géants de la Tech !</figcaption></figure><h3>Et si on testait ce qui compte vraiment ?</h3><p>Dans la même veine, j’ai repensé ma vision des tests. La démonstration de Playwright était bluffante (des tests end-to-end qui s’écrivent presque tout seuls, comme par magie !). Mais après la conférence sur Gravity, une petite voix intérieure m’a soufflé : “Les parcours que tu testes avec tant de minutie, sont-ils vraiment ceux que tes utilisateurs empruntent chaque jour ? Est-ce que ce sont ceux qui génèrent de la valeur ?”</p><p>Je n’ai pas encore toutes les réponses, et à vrai dire, je ne sais pas non plus quels outils me semblent les plus pertinents mais j’ai bien envie de continuer à explorer le sujet. Atteindre 80% de couverture de code, c’est bien. Mais couvrir 100% des fonctionnalités qui créent réellement de la valeur, c’est mieux !</p><h3>Bonus : on travaille pour des humains mais aussi avec des humains</h3><p>J’ai trop aimé la conférence “Fighters, Bards, Druids and Wizards in IT” pour ne pas la mentionner. Oui, nos collègues ne pensent pas tous comme nous. Et c’est très bien.<br>Cette diversité de profils, de modes de communication, de façons de raisonner, peut devenir une vraie force si on prend le temps de l’écouter. Ça m’a rappelé que travailler dans une équipe, c’est aussi savoir se mettre à la place des autres, adapter sa façon de parler, de proposer, de convaincre.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/558/1*f6iax8ngNE9A40EcRbTqKA.png" /><figcaption>Slide de Paweł Zajączkowski pendant la conférence Fighters, Bards, Druids and Wizards in It — how to talk to them?</figcaption></figure><p>Et finalement, c’est peut-être le fil rouge de tout ça : coder pour des humains, c’est aussi coder avec des humains.</p><p>Demain, j’écrirai peut-être encore des tests qui ne sont pas les plus pertinents. Je développerai sûrement des fonctionnalités qui finiront dans les oubliettes numériques. Mais je repars avec de nouvelles question à me poser et à poser. Et ça change déjà tout !</p><h3>Les conférences qui m’ont inspirée cet article</h3><p>Les vidéos seront bientôt disponibles — je les partagerai dès leur mise en ligne :</p><ul><li><strong>Dans les coulisses des géants de la Tech !</strong> — Rachel Dubois</li><li><strong>Playwright : tester vos applications devient un jeu d’enfant</strong> — Benjamin Cavy</li><li><strong>Fighters, Bards, Druids and Wizards in IT — how to talk to them?</strong> — Paweł Zajączkowski</li><li><strong>Au secours ! Mon manager me demande des KPIs !</strong> — Geoffrey Graveaud</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a3c15a258b53" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/coder-pour-les-humains-ce-que-devoxx-ma-appris-au-del%C3%A0-du-code-a3c15a258b53">Coder pour les humains : ce que Devoxx m’a appris au-delà du code</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A la découverte des API Github (REST et GraphQL)]]></title>
            <link>https://medium.com/slickteam/a-la-d%C3%A9couverte-des-api-github-rest-et-graphql-9625e202a685?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/9625e202a685</guid>
            <category><![CDATA[project-management-tool]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[Ronan Barbot]]></dc:creator>
            <pubDate>Thu, 06 Mar 2025 16:59:43 GMT</pubDate>
            <atom:updated>2025-03-06T16:59:43.474Z</atom:updated>
            <content:encoded><![CDATA[<p>Nous avons un projet hébergé sur GitHub, et nous utilisons le module projet afin de préparer nos sprints ainsi que renseigner nos estimations et le temps passé sur chaque ticket. Après plusieurs semaines de développement, le besoin d’avoir quelques KPIs s’est fait sentir, notamment sur la pertinence des estimations de l’équipe ou l’identification des points durs rencontrés.</p><p>Nous avions créé notre projet dans Github, avec plusieurs champs personnalisés : Sprint, Estimation, Réalisation. Ces 3 champs nous servent à grouper les tickets par Sprint, et de pouvoir mettre, pour chaque ticket, une estimation ainsi que le temps passé à la réalisation. Ne trouvant pas d’outil satisfaisant sur la plateforme, je me suis lancé dans la création d’un petit outil web statique qui me permettrait de récupérer ces informations.</p><p>J’ai commencé par demander à <a href="https://chat.mistral.ai/">LeChat</a> de me créer un outil HTML + javascript pour récupérer ces données à partir de l’API Github de les mettre en forme dans un tableau. Il a utilisé cette requête pour obtenir les données :</p><pre>const response = await fetch(`https://api.github.com/repos/${repoOwner}/${repoName}/issues`, {<br>    headers: {<br>        Authorization: `token ${token}`<br>    }<br>});</pre><p>Avec ceci j’ai bien eu une partie de ce que je voulais, mais il me manquait toutes les données liées aux champs personnalisés du projet. Aucune de ces données n’apparaissait dans les données de la réponse, et dans la documentation je ne trouvais pas où les récupérer.</p><p>Après moultes pérégrinations sur les internets, j’ai fini par trouver cet article de <a href="https://some-natalie.dev/">N</a><a href="https://github.com/some-natalie">atalie Somersall</a> : <a href="https://some-natalie.dev/blog/graphql-intro/">https://some-natalie.dev/blog/graphql-intro/</a>. Dans cet article elle détaille comment accéder à l’API GraphQL de Github pour récupérer des données liées au projet. En effet, quand Github a sorti sa fonctionnalité ProjectV2, les informations liées à ces projets étaient uniquement récupérables via l’API GraphQL (et c’est toujours le cas).</p><p>Je me suis basé sur son article pour faire ma première requête, et comme elle met une alerte par rapport à la robustesse de la requête, j’ai demandé à GitHub Copilot comment il utiliserait l’API GraphQL pour récupérer ces informations. Entre ce que j’avais et sa réponse, voici la requête que j’utilise désormais :</p><pre>query {<br>    repository(owner: &quot;${repoOwner}&quot;, name: &quot;${repoName}&quot;) {<br>      projectsV2(first: 10) {<br>        nodes {<br>          title<br>          items(first: 100, after: &quot;${cursor}&quot;) {<br>            nodes {<br>              content {<br>                ... on Issue {<br>                  number<br>                  title<br>                  url<br>                  assignees(first: 10) {<br>                    nodes {<br>                      login<br>                    }<br>                  }<br>                }<br>              }<br>              sprint: fieldValueByName(name: &quot;${sprintField}&quot;) {<br>                ... on ProjectV2ItemFieldIterationValue {<br>                  title<br>                }<br>              }<br>              estimate: fieldValueByName(name: &quot;${estimateField}&quot;) {<br>                ... on ProjectV2ItemFieldNumberValue {<br>                  number<br>                }<br>              }<br>              consumed: fieldValueByName(name: &quot;${consumedField}&quot;) {<br>                ... on ProjectV2ItemFieldNumberValue {<br>                  number<br>                }<br>              }<br>            }<br>            pageInfo {<br>              hasNextPage<br>              endCursor<br>            }<br>          }<br>        }<br>      }<br>    }<br>}</pre><p>Ainsi je récupère bien la valeur des 3 champs personnalisés dans le résultat de la requête, avec une gestion de la pagination. Pour tester rapidement des requêtes vers une API GraphQL, vous pouvez utiliser <a href="https://github.com/graphql/graphiql">graphiql</a> qui, avec son IDE, permet de requêter facilement et avec de la complétion. J’ai utilisé l’appImage <a href="https://github.com/graphql/graphql-playground/releases/">graphql-playground-electron</a> pour tester différents paramètres.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zVlOdu83GWsAez1wbwrB4w.png" /><figcaption>Interface de GraphiQL montrant une requête et son résultat</figcaption></figure><p>Voici le résultat dans mon application : il y a une modale qui permet de paramétrer ses accès à GitHub (token, propriétaire du repo, projet)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TN1CB-15E81KuF8cesXydw.png" /><figcaption>Paramétrage des accès à GitHub</figcaption></figure><p>Puis on peut sélectionner un sprint ou une personne, et voir ses stats suivant les estimations et le temps passé par ticket :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ia9vt63BnQjHZQOtMAAcMw.png" /><figcaption>Tableau des stats pour un sprint, avec la liste des tickets, qui les a fait, et les temps</figcaption></figure><p>Le code de cet outil est consultable <a href="https://github.com/Slickteam/github-sprint-stats">ici</a>. J’espère que vous aurez trouvé ce article intéressant, si jamais vous voulez le modifier pour vos propres besoins projet, n’hésitez pas :).</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9625e202a685" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/a-la-d%C3%A9couverte-des-api-github-rest-et-graphql-9625e202a685">A la découverte des API Github (REST et GraphQL)</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[J’arrête les JO de la tech : retour sur cette sombre histoire de WordPress !]]></title>
            <link>https://medium.com/slickteam/jarr%C3%AAte-les-jo-de-la-tech-retour-sur-cette-sombre-histoire-de-wordpress-4824bc995623?source=rss----c233e538993b---4</link>
            <guid isPermaLink="false">https://medium.com/p/4824bc995623</guid>
            <dc:creator><![CDATA[Ronan Morel]]></dc:creator>
            <pubDate>Thu, 09 Jan 2025 12:25:26 GMT</pubDate>
            <atom:updated>2025-01-09T12:25:26.298Z</atom:updated>
            <content:encoded><![CDATA[<h3>J’arrête les JO de la tech : retour sur cette sombre histoire de WordPress !</h3><p>Vous vous demandez probablement quel est le lien entre le choix d’une technologie et l’utilisation finale de WordPress. Eh bien, je vais vous raconter mon expérience récente à ce sujet.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*izIPH0dNBy92TSZq" /><figcaption>Photo by <a href="https://unsplash.com/@victoriano?utm_source=medium&amp;utm_medium=referral">Victoriano Izquierdo</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Ma problématique</h3><p>Pour un nouveau projet, j’ai à réaliser un site vitrine pour mettre en avant le produit. Étant technophile et voulant voir ce qu’il se fait, j’ai testé pas mal d’outils existants : VitePress, Hugo, Jekyll, Docusaurus…</p><p>J’ai finalement opté pour Docusaurus pour plusieurs raisons : nous avons besoin d’une documentation, d’une section blog et d’une page d’accueil. Docusaurus répond à tous ces besoins, tout en générant un site statique, optimisé pour le référencement sur les moteurs de recherche. De plus, chez Slickteam, nous utilisons déjà cet outil pour la documentation technique de nos projets, ce qui nous donne l’expérience nécessaire pour le manipuler et le maintenir. Après quelques configurations et ajustements, une première version est en ligne et répond à nos attentes pour le moment.</p><h3>Le constat : le besoin et ses usagers</h3><p>Notre besoin principal est de mettre en avant notre travail, notre métier, notre identité, ainsi que les événements auxquels nous participons. En résumé, nous avons besoin d’un outil de communication où nous pouvons présenter et mettre à jour des informations de manière régulière et structurée. Cependant, le choix de Docusaurus pose un problème majeur : la personne responsable de la mise en place des éléments de communication est non-technique et a besoin de pouvoir mettre à jour les informations facilement et de manière autonome. Avec Docusaurus, il est nécessaire d’accéder à Git, de mettre à jour les fichiers concernés, de savoir où ils se trouvent puis de déployer les mises à jour. Ce processus est loin d’être simple pour quelqu’un qui n’a pas de compétences techniques.</p><h3>Le choix final</h3><p>Après mûre réflexion, j’ai opté pour WordPress, un choix pragmatique qui répond parfaitement à nos besoins. Tout d’abord, grâce à notre offre d’hébergement, nous pouvons déployer rapidement et simplement une instance WordPress sans surcoût, même pour une personne non-technique. Ensuite, une fois l’outil configuré, une personne avec des compétences techniques de base peut vérifier les paramètres essentiels tels que les DNS, le HTTPS, les extensions et le SMTP. Pour la personnalisation du site, WordPress est un outil no-code, et donc, une personne non-technique peut construire et gérer le contenu du site de manière autonome. Enfin, WordPress répond également à ma préoccupation concernant le référencement sur les moteurs de recherche, ce qui a définitivement confirmé mon choix.</p><h3>Conclusion</h3><p>J’ai toujours eu cette envie de découvrir de nouveaux outils et de nouvelles technologies, et cela n’a pas changé. Je pense que j’aurai toujours cette inclination technophile à vouloir explorer de nouvelles choses. Cependant, il est crucial de garder à l’esprit le besoin et le contexte associé pour choisir l’outil ou la technologie la plus pertinente. Vouloir à tout prix tester quelque chose de nouveau ou de “hype” n’est pas toujours la meilleure option. En tout cas, c’est la conclusion personnelle que j’en tire.</p><p>Merci d’avoir lu cet article. J’espère que mon point de vue sur le sujet vous a peut-être amené à vous poser des questions (ou peut-être que c’était déjà une évidence pour vous).</p><p><em>Si vous avez apprécié cet article, n’hésitez pas à 👏 ou à le partager.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4824bc995623" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slickteam/jarr%C3%AAte-les-jo-de-la-tech-retour-sur-cette-sombre-histoire-de-wordpress-4824bc995623">J’arrête les JO de la tech : retour sur cette sombre histoire de WordPress !</a> was originally published in <a href="https://medium.com/slickteam">Slickteam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>