Modifier le fichier

Documentation du Système de Chargement des Templates OpenSearch

Introduction

Cette documentation explique en détail le fonctionnement du chargement des templates OpenSearch, où ils sont stockés et dans quel ordre ils sont chargés.

Architecture du Système de Chargement

Types de Templates

Le système gère deux types principaux de templates OpenSearch :

  1. Component Templates (templates de composants)

    • Emplacement : com/kosmos/search/mapping/component_template/**/*.json
    • Fragments réutilisables de configuration de mapping
    • Chargés automatiquement depuis le classpath
  2. Index Templates (templates d'index)

    • Définis via des beans Spring IndexTemplateReference
    • Templates complets pour la création d'index
    • Peuvent référencer des component templates

Processus de Chargement

Le chargement des templates est orchestré par la classe TemplateLoader, qui est un composant Spring activé au démarrage de l'application. Le processus se déroule en deux phases distinctes :

  1. Chargement des Component Templates

    • Exécuté en premier
    • Scanne le classpath pour trouver tous les fichiers JSON dans le répertoire des component templates
    • Charge chaque template trouvé dans OpenSearch
  2. Chargement des Index Templates

    • Exécuté après les component templates
    • Récupère tous les beans Spring de type IndexTemplateReference
    • Charge chaque template référencé dans OpenSearch

Mécanisme de Découverte des Templates

Découverte des Component Templates

Les component templates sont découverts par un scan du classpath, en utilisant le pattern suivant :

classpath*:com/kosmos/search/mapping/component_template/**/*.json

Ce pattern permet de trouver tous les fichiers JSON dans le répertoire des component templates, y compris ceux qui se trouvent dans des JAR dépendants.

Le processus de découverte utilise une chaîne de responsabilité avec deux lecteurs :

  1. ClasspathFileListReader : Pour lire les fichiers depuis les JARs
    • Bootstrap ClassLoader
      • Classes de la JVM (rt.jar, java.base, etc.)
    • System ClassLoader / Common ClassLoader (Tomcat level)
      • Fichiers JAR dans ${CATALINA_HOME}/lib
  2. FileSystemFileListReader : Pour lire les fichiers depuis le système de fichiers local
    • Webapp ClassLoader (ParallelWebappClassLoader)
      • Fichiers WEB-INF/classes/
      • Fichiers WEB-INF/lib/*.jar

Découverte des Index Templates

Les index templates sont découverts par l'inspection du contexte Spring, en recherchant tous les beans de type IndexTemplateReference. Chaque bean définit :

  • Un nom de template
  • Un chemin vers le fichier JSON du template
  • Une priorité
  • Des patterns d'index
  • Optionnellement, un chemin vers des component templates à utiliser

Ordre de Chargement et Mécanisme de Surcharge

Ordre de Chargement des Fichiers

L'ordre de chargement des fichiers dans le classpath est déterminé par plusieurs facteurs :

  1. Ordre de Découverte

    • Les fichiers sont découverts dans l'ordre du classpath Java
    • Les JARs sont scannés dans l'ordre défini par le classloader
    • Les fichiers du système de fichiers local sont généralement traités en dernier
  2. Déduplication

    • Les templates avec le même nom sont dédupliqués
    • Le premier template trouvé est conservé

Mécanisme de Surcharge

Lorsqu'un projet inclut koreparent en tant que dépendance JAR, il peut surcharger les templates existants de deux façons :

  1. Surcharge par Nom

    • En plaçant un fichier avec le même nom au même chemin relatif
    • Exemple : pour surcharger com/kosmos/search/mapping/component_template/content/template_fiche.json du JAR koreparent, placer un fichier avec le même nom au même chemin dans le projet
  2. Surcharge par Priorité (pour les Index Templates)

    • En définissant un bean IndexTemplateReference avec une priorité plus élevée
    • Les templates avec une priorité plus élevée sont appliqués en priorité par OpenSearch

Diagramme du Processus de Chargement

Diagramme du processus de chargement des templates

Ordre de Priorité des Templates

Component Templates

Pour les component templates, l'ordre de priorité est déterminé par l'ordre de chargement :

  1. Les templates définis dans le projet ont priorité sur ceux définis dans les JARs dépendants
  2. En cas de conflit de noms, le dernier template chargé (selon l'ordre du classpath) écrase les précédents

Index Templates

Pour les index templates, l'ordre de priorité est explicitement défini par le paramètre priority :

  1. Plus la valeur de priorité est élevée, plus le template est prioritaire
  2. En cas d'égalité de priorité, le dernier template chargé a la priorité

Exemple de Surcharge de Templates

Surcharge d'un Component Template

Pour surcharger un component template existant dans koreparent :

  1. Identifiez le template à surcharger, par exemple :

    com/kosmos/search/mapping/component_template/content/template_fiche.json
    
  2. Créez un fichier avec le même nom au même chemin dans votre projet :

    src/main/resources/com/kosmos/search/mapping/component_template/content/template_fiche.json
    
  3. Le template de votre projet sera chargé avant celui de koreparent et sera conservé.

Ajout d'un Nouveau Component Template

Pour ajouter un nouveau component template :

  1. Créez un fichier JSON dans le répertoire approprié :

    src/main/resources/com/kosmos/search/mapping/component_template/custom/mon_template.json
    
  2. Le template sera automatiquement découvert et chargé.

Surcharge d'un Index Template

Pour surcharger un index template existant :

  1. Créez un bean IndexTemplateReference avec une priorité plus élevée :

    @Bean
    public IndexTemplateReference monTemplateIndex() {
        return new IndexTemplateReference(
            "nom_template",
            "chemin/vers/mon_template.json",
            300, // Priorité plus élevée que le template original
            null,
            "pattern_index"
        );
    }
    
  2. Le template avec la priorité la plus élevée sera appliqué par OpenSearch.

Génération des templates dynamiques OpenSearch

Fonctionnement

Au démarrage de l'application, le système scanne tous les beans qui implémentent l'interface TemplateField et génère un template JSON contenant tous les champs déclarés. Ce template est injecté dans OpenSearch sous le nom "template_fiche_dynamique".

Comment déclarer un nouveau champ de template

Vous pouvez déclarer un bean XML dans votre fichier de configuration Spring qui utilise la classe MultiPathKeywordTemplateField ou MultiPathDateTemplateField et spécifier une liste de chemins à mapper. Exemple :

<bean id="monKeywordTemplate" class="com.kosmos.search.mapping.fields.MultiPathKeywordTemplateField">
    <property name="paths">
        <list>
            <value>*.diffusionPublicVise</value>
            <value>*.diffusionPublicViseRestriction</value>
            <value>*.etatObjet</value>
            <value>*.id</value>
        </list>
    </property>
</bean>

<bean id="coreDateTemplate" class="com.kosmos.search.mapping.fields.MultiPathDateTemplateField">
    <property name="match" value="date*" />
</bean>

Chaque extension peut déclarer son propre bean avec sa liste de champs à mapper. Les différents beans sont lus au démarrage pour générer le template. Un nom unique est généré automatiquement pour chaque chemin dans la liste, en supprimant les "." et en convertissant les segments en CamelCase (par exemple, "DiffusionPublicViseTemplate" pour le chemin ".diffusionPublicVise" ou "ActualiteTypeEvenementLabelCodeTemplate" pour le chemin ".actualite.typeEvenement..label_code").

Le mapping peut être effectué sur une liste de chemins paths, ou sur une regex correspondant au nom du champ match.

Surcharger un template dynamique

Pour surcharger un template dynamique il faut effectuer un AttributeToOverrideBean pour redéfinir les paths ou le match du bean de template.

Exemple :

<bean id="coreKeywordTemplateOverride" class="com.kportal.core.context.AttributeToOverrideBean">
   <property name="idExtensionToMerge" value="core"/>
   <property name="idBeanToMerge" value="coreKeywordTemplate"/>
   <property name="attributes">
      <map>
         <entry key="paths">
            <list>
               <value>*toto</value>
            </list>
         </entry>
      </map>
   </property>
</bean>

Classes de base disponibles

  • KeywordTemplateField : Classe de base abstraite pour créer des champs de type keyword
  • DateTemplateField : Classe de base abstraite pour créer des champs de type date
  • MultiPathKeywordTemplateField : Implémentation concrète de KeywordTemplateField pour définir plusieurs chemins via XML
  • MultiPathDateTemplateField : Implémentation concrète de DateTemplateField pour définir plusieurs chemins via XML

Créer une nouvelle classe de base pour un nouveau type de champ

Si vous avez besoin d'un nouveau type de champ, créez d'abord une classe abstraite qui étend AbstractTemplateField et définit les propriétés communes à ce type de champ. Ensuite, créez des implémentations concrètes qui étendent cette nouvelle classe de base.

// Classe de base pour un nouveau type de champ
public abstract class NewFieldTypeTemplateField extends AbstractTemplateField {
    @Override
    public String getFieldType() {
        return "new_field_type";
    }
}

Exemple de template généré

Le template généré aura une structure similaire à celle-ci :

{
  "template": {
    "mappings": {
      "dynamic_templates": [
        {
          "dateTemplate": {
            "match_mapping_type": "long",
            "match": "date*",
            "mapping": {
              "type": "date",
              "format": "strict_date_optional_time||epoch_millis"
            }
          }
        },
        {
          "idTemplate": {
            "match_mapping_type": "string",
            "path_match": "*.id",
            "mapping": {
              "type": "keyword"
            }
          }
        },
        {
          "DiffusionPublicViseTemplate": {
            "match_mapping_type": "string",
            "path_match": "*.diffusionPublicVise",
            "mapping": {
              "type": "keyword"
            }
          }
        },
        {
          "DiffusionPublicViseRestrictionTemplate": {
            "match_mapping_type": "string",
            "path_match": "*.diffusionPublicViseRestriction",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ]
    }
  }
}

Création du template

Le template est créé au démarrage de l'application via le ComponentTemplateLoader. Voici le processus :

  1. Le DynamicTemplateGenerator génère le template JSON en scannant tous les beans TemplateField
  2. Le ComponentTemplateLoader vérifie si le template existe déjà sur OpenSearch
  3. S'il existe, le loader compare la version existante avec la nouvelle version générée
  4. Si les versions sont différentes ou si le template n'existe pas, le nouveau template est créé/mis à jour sur OpenSearch

Le template est stocké comme un component template nommé "template_fiche_dynamique".

Bonnes Pratiques

  1. Nommage Unique

    • Utilisez des préfixes spécifiques à votre projet pour éviter les collisions de noms
    • Exemple : projet_template_fiche.json au lieu de template_fiche.json
  2. Priorités Cohérentes

    • Utilisez des plages de priorités cohérentes :
      • 0-100 : Templates de base (koreparent)
      • 101-200 : Templates de modules
      • 201+ : Templates spécifiques aux projets
  3. Documentation

    • Documentez les templates que vous ajoutez ou surchargez
    • Indiquez clairement les modifications apportées aux templates existants
  4. Tests

    • Testez vos templates avant déploiement
    • Vérifiez que les surcharges fonctionnent comme prévu

Conclusion

Le système de chargement des templates OpenSearch dans koreparent offre une grande flexibilité pour personnaliser et étendre les fonctionnalités d'indexation. En comprenant l'ordre de chargement et les mécanismes de surcharge, les projets peuvent adapter les templates à leurs besoins spécifiques tout en bénéficiant des fonctionnalités de base fournies par koreparent.

La clé pour une utilisation efficace de ce système est de comprendre que :

  1. Les component templates sont chargés avant les index templates
  2. Les fichiers sont chargés selon l'ordre du classpath Java
  3. Les templates avec le même nom sont dédupliqués
  4. Les index templates peuvent définir des priorités explicites pour contrôler l'ordre d'application