Une approche d’interface utilisateur basée sur les métadonnées est particulièrement utile dans les équipes de projet avec une compétence back-end ou DBA élevée plutôt que l’interface utilisateur. En général, il fournit l’alignement des éléments en invoquant un seul point de terminaison qui fournit toutes les données requises telles que la cardinalité, la langue, la taille de la police et la police elle-même.
La bibliothèque elle-même vise à fournir un moteur de métadonnées configurable et un ensemble de points de terminaison. Dans le même temps, l’interface utilisateur doit être écrite à partir de zéro, en tenant compte des spécificités des cas d’utilisation correspondants pour pouvoir gérer correctement les métadonnées et se construire en fonction de celles-ci.
Commencer
Pour commencer à utiliser un fournisseur de métadonnées, ajoutez simplement la dépendance maven suivante à l’application principale :
<dependency>
<groupId>io.github.sergeivisotsky.metadata</groupId>
<artifactId>metadata-selector</artifactId>
</dependency>
Et la dépendance suivante à une application de déploiement :
<dependency>
<groupId>io.github.sergeivisotsky.metadata</groupId>
<artifactId>metadata-deploy</artifactId>
</dependency>
Pour avoir une version compatible des deux dépendances, il est également fortement recommandé d’ajouter un démarreur de bibliothèque à votre dependencyManagement
section du POM parent :
<dependency>
<groupId>io.github.sergeivisotsky.metadata</groupId>
<artifactId>metadata-provider-bom</artifactId>
<version>0.0.7</version>
<scope>import</scope>
<type>pom</type>
</dependency>
Il sera chargé depuis Maven Central.
Extension
Imaginons que nous ayons le fournisseur de métadonnées de formulaire préconfiguré suivant, qui a été conçu à partir du modèle préconfiguré suivant.
@Component
public class FormMetadataMapper implements MetadataMapper<FormMetadata> {
@Override
public String getSql() {
return "SELECT fm.id,n" +
" fm.form_name,n" +
" fm.cardinality,n" +
" fm.language,n" +
" fm.offset,n" +
" fm.padding,n" +
" fm.font,n" +
" fm.font_size,n" +
" fm.description,n" +
" fm.facet,n" +
" vf.enabled_by_default,n" +
" vf.ui_controln" +
"FROM form_metadata fmn" +
" LEFT JOIN view_field vf on fm.id = vf.form_metadata_idn" +
"WHERE fm.form_name = :formNamen" +
" AND fm.language = :lang";
}
@Override
public ExtendedFormMetadata map(ResultSet rs) {
try
ExtendedFormMetadata metadata = new ExtendedFormMetadata();
metadata.setFormName(rs.getString("form_name"));
metadata.setCardinality(rs.getString("cardinality"));
metadata.setLang(Language.valueOf(rs.getString("language")
.toUpperCase(Locale.ROOT)));
metadata.setOffset(rs.getInt("offset"));
metadata.setPadding(rs.getInt("padding"));
metadata.setFont(rs.getString("font"));
metadata.setFontSize(rs.getInt("font_size"));
metadata.setDescription(rs.getString("description"));
ViewField viewField = new ViewField();
viewField.setEnabledByDefault(rs.getInt("enabled_by_default"));
viewField.setUiControl(rs.getString("ui_control"));
metadata.setViewField(viewField);
metadata.setFacet(rs.getString("facet"));
return metadata;
} catch (SQLException e) {
throw new RuntimeException("Unable to get value from ResultSet for Mapper: {}" +
FormMetadataMapper.class.getSimpleName(), e);
}
}
}
Dès le premier coup d’œil, c’est plus que suffisant. Cependant, pour les besoins spécifiques d’un projet de livraison, il est nécessaire d’ajouter une structure supplémentaire qui représentera de mystérieuses données de pied de page.
Cela nécessite les étapes suivantes :
- Créez une table de base de données/de nouveaux champs correspondants en ajustant les scripts de déploiement Liquibase.
- Ajoutez une nouvelle structure dans un modèle de domaine préconfiguré comme « ExtendedFormMetadata » ou créez-en une entièrement nouvelle qui fera partie des métadonnées du formulaire.
- Ajustez `FormMetadataMapper` ou créez un tout nouveau mappeur en cas de nouvelles exigences.
Cependant, passons à notre exemple de pied de page mystérieux.
Nous avons une exigence :
- Le pied de page de la page Web doit être généré à partir des métadonnées.
- Il doit être augmenté dans la réponse du point de terminaison de métadonnées OOTBS.
La première étape
Créez un nouveau script de déploiement Liquibase.
Dans notre cas, il s’appelle simplement db.changelog-12-09-2021.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<changeSet id="1" author="svisockis">
<createTable tableName="footer">
<column name="id" type="java.sql.Types.BIGINT" autoIncrement="true">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="resizable" type="java.sql.Types.BOOLEAN"/>
<column name="displayable" type="java.sql.Types.BOOLEAN"/>
<column name="defaultText" type="java.sql.Types.VARCHAR(150)"/>
<column name="form_metadata_id" type="java.sql.Types.BIGINT"/>
</createTable>
<addForeignKeyConstraint baseTableName="footer" baseColumnNames="form_metadata_id"
constraintName="footer_form_view_metadata_fk"
referencedTableName="form_metadata"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>
Nos métadonnées de pied de page doivent contenir des informations indiquant si le pied de page sera redimensionnable et affichable, ainsi que le texte par défaut que l’utilisateur verra après la génération de la page et une clé étrangère vers la table de base des métadonnées.
Deuxième étape
Créez une classe POJO correspondante.
public class Footer {
private Long id;
private Boolean displayable;
private Boolean resizable;
private String defaultText;
// Constructor, getter and setters omitted
}
Ajoutez une référence au parent POJO comme ceci :
public class ExtendedFormMetadata extends FormMetadata {
private String facet;
private Footer footer;
// Constructor, getters and setters omitted
}
Troisième étape
Ajuster un mappeur correspondant — `FormMetadataMapper`
dans notre cas.
- SQL doit être ajusté.
- L’extraction de l’ensemble de résultats doit être ajustée.
@Component
public class FormMetadataMapper implements MetadataMapper<FormMetadata> {
@Override
public String getSql() {
return "SELECT fm.id,n" +
" fm.form_name,n" +
" fm.cardinality,n" +
" fm.language,n" +
" fm.offset,n" +
" fm.padding,n" +
" fm.font,n" +
" fm.font_size,n" +
" fm.description,n" +
" fm.facet,n" +
" vf.enabled_by_default,n" +
" vf.ui_control,n" +
" ft.displayable,n" + // new
" ft.resizable,n" + // new
" ft.default_Textn" + // new
"FROM form_metadata fmn" +
" LEFT JOIN view_field vf on fm.id = vf.form_metadata_idn" +
" LEFT JOIN footer ft on fm.id = ft.form_metadata_idn" + // new
"WHERE fm.form_name = :formNamen" +
" AND fm.language = :lang";
}
@Override
public ExtendedFormMetadata map(ResultSet rs) {
try {
ExtendedFormMetadata metadata = new ExtendedFormMetadata();
metadata.setFormName(rs.getString("form_name"));
metadata.setCardinality(rs.getString("cardinality"));
metadata.setLang(Language.valueOf(rs.getString("language")
.toUpperCase(Locale.ROOT)));
metadata.setOffset(rs.getInt("offset"));
metadata.setPadding(rs.getInt("padding"));
metadata.setFont(rs.getString("font"));
metadata.setFontSize(rs.getInt("font_size"));
metadata.setDescription(rs.getString("description"));
ViewField viewField = new ViewField();
viewField.setEnabledByDefault(rs.getInt("enabled_by_default"));
viewField.setUiControl(rs.getString("ui_control"));
metadata.setViewField(viewField);
metadata.setFacet(rs.getString("facet"));
// --- New block ---
Footer footer = new Footer();
footer.setResizable(rs.getBoolean("resizable"));
footer.setDisplayable(rs.getBoolean("displayable"));
footer.setDefaultText(rs.getString("default_text"));
metadata.setFooter(footer);
// --- End new block ---
return metadata;
} catch (SQLException e) {
throw new RuntimeException("Unable to get value from ResultSet for Mapper: {}" +
FormMetadataMapper.class.getSimpleName(), e);
}
}
}
Quatrième étape
Exécutez l’application de déploiement pour mettre à jour le schéma de base de données et l’application elle-même.
Résultat
Dans le résultat, vous pouvez voir la nouvelle section suivante dans le point de terminaison des métadonnées.
}
// ...
"footer": {
"id": null,
"displayable": true,
"resizable": false,
"defaultText": "This is some footer needed to fulfill our business requirements"
}
// ...
}
Un code source de cette démo peut être trouvé dans le référentiel suivant.
Exemple d’utilisation OOTB (out-of-the-Box)
La page suivante décrit une fonctionnalité de métadonnées de zone de liste déroulante OOTB (Out-of-the-Box).
Pour un style et des valeurs de zone de liste déroulante, les métadonnées sont également utilisées. Par exemple:
[
{
"id": 1,
"codifier": "CD_001",
"font": "Times New Roman",
"fontSize": 12,
"weight": 300,
"height": 20,
"displayable": true,
"immutable": false,
"comboContent": [
{
"key": "initial",
"defaultValue": "Some initial value",
"comboId": 1
},
{
"key": "secondary",
"defaultValue": "Some secondary value",
...