<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Guillaume Benoot</title>
    <description>The latest articles on DEV Community by Guillaume Benoot (@guillaumebenoot).</description>
    <link>https://dev.to/guillaumebenoot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2954594%2F2ebe8958-449a-4fb3-8dbe-b08ed0e2e360.jpeg</url>
      <title>DEV Community: Guillaume Benoot</title>
      <link>https://dev.to/guillaumebenoot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guillaumebenoot"/>
    <language>en</language>
    <item>
      <title>Migration Oracle -&gt; PostgreSQL : il n’y a que le driver à changer ! Non ?</title>
      <dc:creator>Guillaume Benoot</dc:creator>
      <pubDate>Wed, 07 May 2025 14:29:08 +0000</pubDate>
      <link>https://dev.to/onepoint/migration-oracle-postgresql-il-ny-a-que-le-driver-a-changer-non--1oc1</link>
      <guid>https://dev.to/onepoint/migration-oracle-postgresql-il-ny-a-que-le-driver-a-changer-non--1oc1</guid>
      <description>&lt;h1&gt;
  
  
  Migration Oracle -&amp;gt; PostgreSQL : il n’y a que le driver à changer ! Non ?
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Cet article n’a pas vocation à encenser PostgreSQL ni à dénigrer Oracle. Il s’agit de vous présenter les problèmes que nous avons rencontrés, comment nous les avons résolus et, pour certains, comment nous aurions pu les anticiper.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Notre client a décidé de migrer ses bases de données Oracle vers PostgreSQL et nous a sollicités pour réaliser cette migration. &lt;br&gt;
Sur le papier, cela semble simple : il suffit de changer le driver Oracle par le driver PostgreSQL et le tour est joué. &lt;br&gt;
Mais le plan ne s'est pas déroulé sans accrocs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Un peu d’histoire :
&lt;/h2&gt;

&lt;p&gt;Pour comprendre une partie des problèmes rencontrés, il faut revenir sur l’histoire de SQL :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1970&lt;/strong&gt; : IBM créé SEQUEL, un langage permettant d’interroger et éditer une base de données relationnelles, il sera renommé par la suite SQL en 1975.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1979&lt;/strong&gt; : Relational Software Inc (devenue Oracle Corporation) s’inspire des travaux d’IBM et présente la première version commerciale du SGBD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1986&lt;/strong&gt; : toutes les plus grandes entreprises du secteur se réunissent pour établir la première norme SQL. Elles sont toutes présentes sauf Oracle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1995&lt;/strong&gt; : la troisième révision de la norme SQL voit le jour. PostgreSQL est créé : ils implémentent la norme.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On remarque qu’Oracle a suivi son propre chemin vis-à-vis de la norme SQL alors que PostgreSQL en bon élève a mis en œuvre tout ou partie de cette norme.&lt;br&gt;&lt;br&gt;
Après des années d'évolution de la norme, PostgreSQL demeure parmi les plus conformes. Oracle rattrape son retard petit à petit et se rapproche de plus en plus de la norme. Néanmoins, le mal est fait. Durant des années, les fonctionnalités propres à Oracle ont été disséminées dans de trop nombreux projets. C’est pourquoi il est nécessaire de migrer ces fonctionnalités vers celles équivalentes en PostgreSQL.&lt;/p&gt;
&lt;h2&gt;
  
  
  Migration de la base de données :
&lt;/h2&gt;

&lt;p&gt;Quand on évoque la migration d’une base de données, il faut penser à tout ce qui la structure : tables, séquences, vues, vues matérialisées, procédures stockées, triggers, fonctions, grants, dblink, types etc …&lt;br&gt;&lt;br&gt;
Tout cela sans compter les données ! Heureusement, cela ne se fait pas manuellement, il existe plusieurs logiciels sur le marché capables d’effectuer cette tâche.&lt;/p&gt;

&lt;p&gt;Nous allons vous présenter celui qui a été utilisé sur notre projet : &lt;a href="https://ora2pg.darold.net/" rel="noopener noreferrer"&gt;ora2pg&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Cet utilitaire a été créé en 2001, il est open source et est toujours maintenu par la communauté. Il fait partie des leaders du marché.&lt;/p&gt;

&lt;p&gt;L’utilisation la plus simple de cet utilitaire s’effectue en quelques étapes :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Exécution des scripts d’export de la structure de la base de données Oracle ainsi que des données au format SQL.
&lt;/li&gt;
&lt;li&gt;Conversion vers un format SQL compatible PostgreSQL.
&lt;/li&gt;
&lt;li&gt;Exécution des scripts d’import dans la base de données PostgreSQL.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://ora2pg.darold.net/" rel="noopener noreferrer"&gt;ora2pg&lt;/a&gt; est également capable de convertir du PL/SQL en PL/pgSQL. Il propose beaucoup plus de fonctionnalités. Il permet notamment de choisir les objets que nous souhaitons migrer, convertir certains types vers d’autres ou encore, d’estimer le coût en jour-homme et la complexité de tout ce qui n’a pas pu être migré de manière automatique. La documentation est bien écrite et complète.&lt;br&gt;&lt;br&gt;
La théorie ayant été énoncée, place au concret et à l’analyse de l’application à migrer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Étude du patrimoine applicatif :
&lt;/h2&gt;

&lt;p&gt;Lorsqu’un ORM (Object-Relational Mapping) tel que Spring Data JPA ou Hibernate est utilisé dans les composants, cela apporte une couche d’abstraction vis-à-vis de l’utilisation de la base de données. Bien évidemment, cette abstraction facilite grandement la migration d’un SGBD vers un autre.&lt;/p&gt;

&lt;p&gt;Malheureusement, ce n’est pas le cas sur les projets que nous avons dû migrer. Les accès à la base de données sont réalisés via des requêtes SQL natives. Les composants sont développés en Java, il s’agit d’une IHM et de quelques batchs.&lt;br&gt;&lt;br&gt;
La particularité de l’IHM est qu’elle intègre des dépendances d’applications tierces utilisant d’autres bases de données Oracle ne faisant pas partie du projet de migration à court terme. La stratégie de notre client est de ne plus utiliser ces dépendances au profit d’appels HTTP à des API tierces. Nous avons pu retrouver toutes les fonctionnalités qu’offraient ces dépendances via les ressources exposées par les API tierces.&lt;/p&gt;

&lt;p&gt;Le périmètre de la migration semble plutôt simple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrer la base de données Oracle en PostgreSQL
&lt;/li&gt;
&lt;li&gt;Remplacer le driver Oracle par le driver PostgreSQL dans chaque composant
&lt;/li&gt;
&lt;li&gt;Remplacer les dépendances tierces par des appels HTTP à des API tierces
&lt;/li&gt;
&lt;li&gt;Adapter les requêtes SQL utilisant des fonctions spécifiques à Oracle
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Début des travaux :
&lt;/h2&gt;

&lt;p&gt;Une fois la base de données migrées en utilisant &lt;a href="https://ora2pg.darold.net/" rel="noopener noreferrer"&gt;ora2pg&lt;/a&gt; décrit précédemment, nous sommes passés sur l’adaptation des requêtes SQL.&lt;br&gt;&lt;br&gt;
Il existe plus d’une centaine de fonctions dans Oracle et PostgreSQL. Celles qui respectent la norme sont équivalentes. Nous allons passer en revue les fonctions couramment utilisées et spécifiques à Oracle et leur équivalence PostgreSQL.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fonctionnalité Oracle&lt;/th&gt;
&lt;th&gt;Équivalent PostgreSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table DUAL&lt;/td&gt;
&lt;td&gt;On peut créer une vue se nommant DUAL dans PostgreSQL pour faciliter la migration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CREATE SEQUENCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;fonctionne aussi. Utilisation avec &lt;code&gt;nextval('seq')&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Préfixe des colonnes lors d’un UPDATE &lt;code&gt;UPDATE t SET t.col = ...&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;même syntaxe supportée mais pas nécessaire.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sous-requête &lt;code&gt;SELECT * FROM (SELECT * FROM ma_table) MON_ALIAS;&lt;/code&gt; ok&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM (SELECT * FROM ma_table) AS MON_ALIAS;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MINUS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;EXCEPT&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DECODE&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CASE WHEN ... THEN ... ELSE ... END&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;COALESCE(val, remplacement)&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opérateur (+)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;LEFT JOIN&lt;/code&gt;, &lt;code&gt;RIGHT JOIN&lt;/code&gt;, &lt;code&gt;FULL OUTER JOIN&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chaînes vides &lt;code&gt;''&lt;/code&gt; est traité comme &lt;code&gt;NULL&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;''&lt;/code&gt; ≠ &lt;code&gt;NULL&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Le traitement des dates est un &lt;strong&gt;vaste sujet&lt;/strong&gt;. Voici quelques exemples : &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fonctionnalité Oracle&lt;/th&gt;
&lt;th&gt;Équivalent PostgreSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;DATE&lt;/code&gt; = date et heure&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DATE&lt;/code&gt; = date uniquement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;CURRENT&lt;/code&gt; = fuseau horaire de la session&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CURRENT&lt;/code&gt; = fuseau horaire de l’OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;date1 - date2&lt;/code&gt; (en jours)&lt;/td&gt;
&lt;td&gt;Retourne un &lt;code&gt;interval&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Il s’agit là que d’un échantillon mais comme vous pouvez le voir, cela peut être long et fastidieux de tout adapter. Sachez qu’il existe une extension nommée &lt;a href="https://github.com/orafce/orafce" rel="noopener noreferrer"&gt;orafce&lt;/a&gt; permettant d’émuler une partie des fonctions et packages d’Oracle au sein de PostgreSQL. Cette extension prend la forme d’un fichier SQL à exécuter avec les bons droits sur le serveur PostgreSQL.&lt;br&gt;&lt;br&gt;
Cette extension est supportée par AWS Aurora et Azure Database depuis respectivement 2018 et 2019. Voici quelques extraits du fichier d’installation :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- emulation of dual table&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dual&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="s1"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;varchar&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;REVOKE&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dual&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dual&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;coalesce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt; &lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;sql&lt;/span&gt; &lt;span class="k"&gt;IMMUTABLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L’installation de cette extension peut faciliter l’adaptation des requêtes SQL si votre projet est contraint par le temps ou le coût. &lt;br&gt;
Néanmoins, votre projet continuera d’utiliser des spécificités d’Oracle ne faisant pas partie de la norme SQL. &lt;br&gt;
Charge à vous de poursuivre ou non la migration au fil de l’eau par la suite.  &lt;/p&gt;

&lt;p&gt;Une fois la base de données migrée, les drivers changés, et requêtes adaptées, nous débutons la campagne de tests de non-régression sur l’application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Premiers tests post-migration :
&lt;/h2&gt;

&lt;p&gt;Très rapidement une erreur est remontée par l’un des composants :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;org.postgresql.util.PSQLException: ERROR: relation "articles” does not exist&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;La table “ARTICLES” n’existe pas … Nous nous rendons compte que notre application utilise une autre base de données. Pour comprendre pourquoi nous ne l’avons pas vu, il est nécessaire de vous expliquer comment est structurée une base de données.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dépendances Oracle tierces :
&lt;/h2&gt;

&lt;p&gt;Un serveur de base de données contient une ou plusieurs instances. Chaque instance contient un ou plusieurs schémas. Chaque schéma contient une ou plusieurs tables.&lt;br&gt;
Dans Oracle, il est possible d’autoriser un schéma à accéder à une table d’un autre schéma en lecture ou modification. Cela s’effectue via des &lt;em&gt;GRANT&lt;/em&gt;. Il est également possible d’autoriser un schéma à accéder à un autre schéma d’une autre instance (voir d’une autre base de données) via le mécanisme de &lt;em&gt;DBLINK&lt;/em&gt;.&lt;br&gt;
A l’utilisation, cela revient à exécuter les requêtes SQL suivantes :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;SCHEMA_DIST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARTICLES&lt;/span&gt;      &lt;span class="c1"&gt;-- grant&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ARTICLES&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;SCHEMA_DIST&lt;/span&gt;      &lt;span class="c1"&gt;-- dblink&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L’écriture de ces requêtes n’est pas commune, nous aurions dû nous en rendre compte. Mais c’est sans compter l’utilisation de SYNONYM !&lt;br&gt;
Les SYNONYM permettent de créer une sorte d’alias pour faciliter l’écriture de requête. Concernant les GRANT et DBLINK, il est possible de déclarer un SYNONYM de cette manière :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SYNONYM&lt;/span&gt; &lt;span class="n"&gt;ARTICLES&lt;/span&gt;  &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;SCHEMA_DIST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARTICLES&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SYNONYM&lt;/span&gt; &lt;span class="n"&gt;ARTICLES2&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;ARTICLES&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;SCHEMA_DIST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce qui donne à l’utilisation :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ARTICLES&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ARTICLES2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L’utilisation des GRANT et DBLINK est donc tout simplement cachée. Si l’application est mal ou peu documentée, on perd la visibilité sur ce couplage fort entre deux schémas distincts.&lt;br&gt;
Il est nécessaire de bien identifier les dépendances lors de l’étude initiale. Les trois requêtes suivantes permettent respectivement de retrouver les GRANT, DBLINK et SYNONYM déclarés dans votre schéma.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;GRANTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ALL_TAB_PRIVS&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;GRANTEE&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MON_USER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PUBLIC'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;DB_LINK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;HOST&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ALL_DB_LINKS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;SYNONYM_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TABLE_OWNER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DB_LINK&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ALL_SYNONYMS&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;OWNER&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MON_USER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PUBLIC'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Poursuite des tests :
&lt;/h2&gt;

&lt;p&gt;Une fois ces dépendances remplacées par des appels HTTP à des API tierces, nous avons repris les tests de non-régression sur l’ensemble de l’application.&lt;br&gt;
Nous avons été confrontés à une dernière anomalie : il s’agissait d’un bug présent dans le driver PostgreSQL. N’hésitez pas à aller consulter le bug tracker de PostgreSQL si vous faites face à des comportements étranges ou insolubles à l’exécution de vos tests : &lt;a href="https://github.com/pgjdbc/pgjdbc/issues" rel="noopener noreferrer"&gt;https://github.com/pgjdbc/pgjdbc/issues&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion :
&lt;/h2&gt;

&lt;p&gt;Pour conclure, nous aimerions rappeler qu’il faut bien s’outiller pour effectuer une migration Oracle vers PostgreSQL. &lt;a href="https://ora2pg.darold.net/" rel="noopener noreferrer"&gt;ora2pg&lt;/a&gt; semble indispensable pour la phase initiale concernant la structure et les données. N’hésitez pas à utiliser les types de données natifs dans PostgreSQL. L’installation d’extension telle que &lt;a href="https://github.com/orafce/orafce" rel="noopener noreferrer"&gt;orafce&lt;/a&gt; dépendra des contraintes de votre projet.&lt;br&gt;
L’étude initiale est importante, prenez le temps d’identifier toutes les dépendances externes à votre application. Notamment en exécutant les trois requêtes fournies précédemment qui vous permettront d’éviter les surprises.&lt;br&gt;
La phase de test de non-régression est nécessaire pour déceler les derniers problèmes que pourrait engendrer une migration de ce type. Consultez le bug tracker du driver si cela est nécessaire.&lt;br&gt;
Enfin, sachez qu’il n’existe pas d’outil miracle permettant de faire une migration de manière complètement automatisée. Des ajustements manuels seront nécessaires. Nous espèrons avoir levé le voile sur ce qu’était une migration et vous éviter de tomber dans les mêmes pièges que nous avons rencontrés.&lt;/p&gt;

&lt;p&gt;Références&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://db-engines.com/en/ranking_trend/system/Oracle%3BPostgreSQL" rel="noopener noreferrer"&gt;https://db-engines.com/en/ranking_trend/system/Oracle%3BPostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/postgresql/migrate/how-to-migrate-from-oracle" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/postgresql/migrate/how-to-migrate-from-oracle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/community/tutorials/migrate-oracle-postgres-using-ora2pg" rel="noopener noreferrer"&gt;https://cloud.google.com/community/tutorials/migrate-oracle-postgres-using-ora2pg&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>oracle</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>La vie d'une JEP n'est pas un long fleuve tranquille</title>
      <dc:creator>Guillaume Benoot</dc:creator>
      <pubDate>Tue, 29 Apr 2025 14:32:31 +0000</pubDate>
      <link>https://dev.to/onepoint/la-vie-dune-jep-nest-pas-un-long-fleuve-tranquille-23ch</link>
      <guid>https://dev.to/onepoint/la-vie-dune-jep-nest-pas-un-long-fleuve-tranquille-23ch</guid>
      <description>&lt;p&gt;Tous les 6 mois, une nouvelle version de JAVA sort.&lt;br&gt;
Le JDK est mis à jour, de nouvelles fonctionnalités sont ajoutées et parfois certaines sont retirées.&lt;br&gt;
Le JDK c'est le &lt;em&gt;JAVA developpement kit&lt;/em&gt;, il contient des outils et des bibliothèques qui permettent d'écrire des applications en JAVA.&lt;/p&gt;

&lt;p&gt;Avec chaque mise à jour du JDK on entend parler des JEP qu'elle intègre.&lt;br&gt;
Mais c'est quoi exactement une JEP ?&lt;/p&gt;

&lt;h2&gt;
  
  
  JEP ou JDK Enhancement Proposal
&lt;/h2&gt;

&lt;p&gt;Une JEP c'est un document texte qui va permettre de définir une nouvelle fonctionnalité.&lt;/p&gt;

&lt;p&gt;C'est un document &lt;em&gt;vivant&lt;/em&gt; qui va évoluer au cours de sa vie.&lt;br&gt;
Des sections vont être ajoutées, modifiées ou supprimées.&lt;/p&gt;

&lt;p&gt;Une JEP doit être rédigée:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pour toutes &lt;u&gt;modifications significatives&lt;/u&gt; du JDK&lt;/li&gt;
&lt;li&gt;si une modification demande plus de &lt;u&gt;2 semaines de travail&lt;/u&gt;
&lt;/li&gt;
&lt;li&gt;ou si cette modification vient suite à une grande &lt;u&gt;demande des développeurs&lt;/u&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Toutefois, il y à beaucoup de modifications qui ne remplissent pas ces conditions et qui sont tout de même intégrées au JDK. On pourra trouver la liste de ces modifications dans la &lt;em&gt;release note&lt;/em&gt; qui accompagne la sortie de la nouvelle version du JDK.&lt;/p&gt;

&lt;p&gt;Pour proposer une JEP, on va la créer à partir d'un &lt;a href="https://openjdk.org/jeps/2" rel="noopener noreferrer"&gt;template&lt;/a&gt;, puis la soumettre par mail à &lt;em&gt;OpenJDK&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;C'est a partir de ce document que l'on va pouvoir commencer à discuter de cette modification dans la communauté OpenJDK et que le travail va pouvoir commencer.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenJDK
&lt;/h2&gt;

&lt;p&gt;La &lt;em&gt;communauté OpenJDK&lt;/em&gt;, c'est une association de développeurs qui collaborent autour de l'implémentation open source de la plateforme JAVA Standard Edition (JAVA SE).&lt;/p&gt;

&lt;p&gt;Elle a été créée en 2006 quand une partie du code source de JAVA a été publié sous &lt;a href="https://fr.wikipedia.org/wiki/Licence_publique_g%C3%A9n%C3%A9rale_GNU" rel="noopener noreferrer"&gt;license GPLv2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La communauté est composée de développeurs avec différents statuts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Qui est qui chez OpenJDK ?
&lt;/h3&gt;

&lt;p&gt;En souscrivant à une mailing list d'OpenJDK, on obtient le rôle de  &lt;strong&gt;Participant&lt;/strong&gt;.&lt;br&gt;
C'est le tout premier rôle qui va permettre de participer aux discussions de ces mailing list.&lt;/p&gt;

&lt;p&gt;Pour pouvoir passer aux choses sérieuses et commencer à écrire du code qui va changer (ou pas) la face de JAVA, il va falloir signer l'&lt;em&gt;&lt;a href="https://www.oracle.com/technetwork/oca-405177.pdf" rel="noopener noreferrer"&gt;Oracle Contributor Agreement (OCA)&lt;/a&gt;&lt;/em&gt;.&lt;br&gt;
C'est un document juridique qui va donner les droits de ton code à Oracle.&lt;br&gt;
À partir de ce moment, on devient &lt;strong&gt;Contributor&lt;/strong&gt; et les choses sérieuses commencent.&lt;br&gt;
Dorénavant on peut soumettre des modifications du code, proposer de nouveaux projets et assumer divers rôles au sein de groupes ou de projets.&lt;/p&gt;

&lt;p&gt;Au fil de des contributions, on va être amené à échanger avec d'autres développeurs, et notamment des OpenJDK Members. Et une fois que l'on aura participé à plusieurs modifications significatives, notre nom pourra être proposé afin de devenir &lt;strong&gt;OpenJDK Member&lt;/strong&gt; (après un vote des OpenJDK Members).&lt;br&gt;
On aura la possibilité proposer la création de nouveaux groupes, devenir leader de groupe et participer à tout un tas de votes réservés aux OpenJDK Members. (nouveaux projets, nouveaux membres, membres extraordinaires du conseil d'administration...)&lt;/p&gt;

&lt;p&gt;Le dernier rôle c'est celui d'&lt;strong&gt;OpenJDK Lead&lt;/strong&gt;, mais là, il faudra être nommé par Oracle pour le devenir.&lt;br&gt;
Il  dirige les principaux efforts de la communauté, à savoir les nouvelles releases du JDK et il siège au conseil d'administration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les groupes
&lt;/h3&gt;

&lt;p&gt;Tout ce petit monde va se réunir dans des &lt;em&gt;groupes&lt;/em&gt; en fonction des appétences de chacun. (ex: Compiler, Security, Web...)&lt;/p&gt;

&lt;p&gt;Un groupe peut avoir pour intérêt la création, l'amélioration ou la maintenance d'une partie spécifique de code ou bien des sujets annexes comme la documentation par exemple.&lt;/p&gt;

&lt;p&gt;Un groupe peut devenir &lt;strong&gt;sponsor&lt;/strong&gt; d'un projet. Cela veut dire qu'il estime qu'un projet est intéressant et que des membres du groupe pourront travailler sur ce projet.&lt;/p&gt;

&lt;p&gt;Le groupe sera constitué de membres et d'un leader.&lt;br&gt;
Le leader a toute autorité pour choisir de sponsoriser un projet, il sera le contact pour communiquer avec le groupe et il devra écrire un rapport sur les activités du groupe une fois par trimestre.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les projets
&lt;/h3&gt;

&lt;p&gt;Un &lt;em&gt;projet&lt;/em&gt; est un effort collaboratif qui a &lt;strong&gt;pour but de produire&lt;/strong&gt; du code, de la documentation, ou tout autre type de matériel en lien avec le projet.&lt;br&gt;
Un projet peut contenir une ou plusieurs fonctionnalités, ou même l'entièreté du JDK.&lt;/p&gt;

&lt;p&gt;Tout &lt;strong&gt;contributeur&lt;/strong&gt; peut proposer la création d'un projet.&lt;br&gt;
S'il est supporté par au moins un Group Lead, dont le groupe sera sponsor du projet et approuvé par les OpenJDK Members, alors le projet sera créé.&lt;/p&gt;

&lt;p&gt;Un  projet peut être &lt;strong&gt;sponsorisé par plusieurs groupes&lt;/strong&gt;, mais si un projet n'a plus de sponsor, alors il est dissous et le matériel d'un projet est archivé car un projet dissous peut être recréé.&lt;/p&gt;

&lt;p&gt;On va y trouver là aussi différents rôles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;un &lt;strong&gt;Author&lt;/strong&gt; est un contributeur qui a reçu les droits pour créer des changements dans le code, mais il n'a pas les droits pour pousser directement sur le dépôt GIT.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;un &lt;strong&gt;committer&lt;/strong&gt; est un auteur qui a le droit de "pousser" sur le depôt.&lt;br&gt;
Il peut nommer de nouveaux committers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;un &lt;strong&gt;reviewer&lt;/strong&gt; est une committer expérimenté qui a l'autorité d'approuver les changements dans le code. Il peut nommer ou révoquer un autre reviewer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;un &lt;strong&gt;Project lead&lt;/strong&gt; est un committer qui a la responsabilité de diriger et coordonner les activités de ce projet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il a toute autorité sur la &lt;strong&gt;partie technique&lt;/strong&gt; du projet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il peut &lt;strong&gt;ajouter ou retirer des auteurs&lt;/strong&gt; qui ne sont pas committers sur le projet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il peut demander des &lt;strong&gt;modifications de code&lt;/strong&gt; dans un repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il a l'obligation d'être le &lt;strong&gt;point d'entrée du projet&lt;/strong&gt; pour les mailing lists, le contenu web et les repositories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il doit &lt;strong&gt;publier&lt;/strong&gt; une fois par trimestre &lt;strong&gt;un rapport&lt;/strong&gt; sur les activités du projet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il est considéré comme &lt;strong&gt;reviewer&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il est &lt;strong&gt;nommé par les group leads&lt;/strong&gt; qui sponsorisent le projet.&lt;br&gt;
Lors de la &lt;strong&gt;création du projet&lt;/strong&gt;, c'est lui qui &lt;strong&gt;nomme les auteurs, committers et reviewers&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Le Governing Board
&lt;/h3&gt;

&lt;p&gt;C'est un groupe qui manage la structure et les opérations de la communauté OpenJDK.&lt;br&gt;
Il est composé de &lt;u&gt;5 contributeurs&lt;/u&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le Président, nommé par &lt;strong&gt;Oracle&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Le Vice Président, nommé par &lt;strong&gt;IBM&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;L'OpenJDK Lead nommé par &lt;strong&gt;Oracle&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;2 membres extraordinaires, qui sont nommés suite à un &lt;strong&gt;vote des OpenJDK Members&lt;/strong&gt; pour une durée de 1 an à compter du 1er Avril de chaque année.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il gère la structure et les opérations de la communauté via règlement qu'il maintient et fait respecter.&lt;br&gt;
Il peut trancher des litiges procéduraux.&lt;br&gt;
Il n'a &lt;strong&gt;pas d'autorité directe sur des décisions techniques&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le cycle de vie d'un JEP
&lt;/h2&gt;

&lt;p&gt;Maintenant que nous connaissons mieux OpenJDK et surtout le rôle de chacun, il va être très facile de comprendre le schéma ci dessous fournis par OpenJDK.&lt;br&gt;
En noir nous aurons les différents états de la JEP et en vert, qui modifie cet état.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb0sq868w6zjx907lrru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb0sq868w6zjx907lrru.png" alt="Diagramme du workflow d'une JEP" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La JEP va donc passer par différents états et c'est la personne en vert sur le schéma qui la fera passer d'un état à un autre.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Draft&lt;/u&gt; - c'est le 1er état de la JEP, &lt;em&gt;le template correctement rempli a été fourni à OpenJDK et un numéro JBS&lt;/em&gt; lui a été attribué*. On va pouvoir commencer à la diffuser dans la communauté afin de valider que l'idée est bonne et réalisable.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Submitted&lt;/u&gt; - La JEP est soumise pour être évaluée par &lt;strong&gt;toute&lt;/strong&gt; la communauté afin d'être ajoutée à la roadmap.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Candidate&lt;/u&gt; - La JEP a été ajoutée à la roadmap. C'est à ce moment qu'elle reçoit un numéro officiel. Le propriétaire de la JEP va commencer à établir un plan d'ingénierie.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Proposed to target&lt;/u&gt; - Une fois qu'un plan d'ingénierie crédible est établi,  une release du JDK est ciblée pour la livraison.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Targeted&lt;/u&gt; - le plan d'ingénierie a été validé par les committers et reviewers du projet.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Integrated&lt;/u&gt; - le développement et les tests unitaires sont faits.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Complete&lt;/u&gt; - les tests fonctionnels, de performance et de conformité sont livrés.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Rejected&lt;/u&gt; - Une JEP peut être rejetée si l'openJDK Lead estime qu'elle est trop complexe à mettre en oeuvre.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Withdrawn&lt;/u&gt; - Une JEP peut aussi être retirée par son propriétaire s'il estime qu'elle a besoin d'être retravaillée par exemple.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il existe des JEP de procédures (elles décrivent le fonctionnement d'openJDK) et d'infrastructure (elles décrivent les systèmes et outils utilisés pour développer et maintenir le JDK).&lt;br&gt;
Ces JEP ont un numéro inférieur à 100 et elles n'ont évidemment pas d'étape de développement et elles passent directement du statut &lt;em&gt;Candidate&lt;/em&gt; à &lt;em&gt;Delivered&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Envie de te lancer ?
&lt;/h2&gt;

&lt;p&gt;La première chose à faire, c'est de &lt;strong&gt;souscrire aux mailing lists&lt;/strong&gt; des sujets qui t’intéressent.&lt;br&gt;
Ensuite, la contribution à OpenJDK peut prendre &lt;em&gt;plusieurs formes&lt;/em&gt;.&lt;br&gt;
De l'écriture de code pour de nouvelles fonctionnalités ou de patchs bien sûr, mais pas que.&lt;/p&gt;

&lt;p&gt;La participation aux discussions dans les mailing lists (propositions fonctionnelles, participation aux choix techniques...), le &lt;em&gt;test des nouvelles features&lt;/em&gt;, et le &lt;em&gt;feedback&lt;/em&gt; qui va avec, le retour sur des bugs que tu as pu constater ou que d'autres ont constaté (sur des forums par exemple) accompagné d'un travail de recherche pour les rendre &lt;em&gt;reproductibles&lt;/em&gt; sont très appréciés et sont aussi considérés comme des contributions.&lt;/p&gt;

&lt;p&gt;Si tu veux écrire du code, signe l'OCA ou vois si ton entreprise l'a déjà signée.&lt;br&gt;
Avant de proposer un changement dans le code, il est important d'échanger avec les membres de la communauté afin d'en valider l'utilité et les choix techniques de ce changement par exemple.&lt;br&gt;
Cela permettra par la même occasion de trouver un &lt;strong&gt;contributeur qui acceptera de devenir ton sponsor&lt;/strong&gt; et de t'accompagner dans toutes les tâches administratives (mise à jour des JBS*, revue de code, tests additionnels...)&lt;/p&gt;

&lt;p&gt;Enfin, même si tu choisis de ne pas participer, s'intéresser aux JDK Enhancement Proposals te permet de rester informé des futures nouveautés de JAVA et de mieux appréhender celles qui viennent d'être livrées dans le dernier JDK. De plus, les discussions sur les mailing lists peuvent s'avérer très enrichissantes pour approfondir ta compréhension du fonctionnement du JDK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;*JBS&lt;/strong&gt; pour &lt;strong&gt;JDK Bug System&lt;/strong&gt;, un outil Jira qui permet de suivre les problèmes remontés pour chaque JEP.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
