Aller au contenu principal

Guide de développement des plugins Spark Workbench Dashboard Gadget

Ce guide s'adresse aux développeurs qui veulent étendre Spark Workbench Dashboard Gadget. Un plugin Gadget doit être autonome : le point d'extension backend, les composants Vue frontend et les ressources générées doivent rester dans le même module plugin. Le host de la plateforme ne fait que charger et exécuter le plugin.

1. Modèle de plugin Gadget​

Un Gadget Spark Workbench comporte deux parties :

  • Extension backend : enregistre les descriptions de Gadget via Lattice et produit les données runtime.
  • Composant frontend : affiche les données avec Vue, empaqueté comme ressource UMD et chargé dynamiquement par Workbench.

Le plugin par défaut se trouve ici :

spark-plugins/spark-workbench-default-plugin/

Ce module contient à la fois le code Java et le code frontend. Les plugins tiers devraient suivre la même structure pour éviter de placer du code Gadget concret dans le host principal.

2. Structure recommandée​

my-workbench-gadget-plugin/
pom.xml
src/main/java/
.../MyGadgetRegistryExt.java
src/main/frontend/
package.json
vite.config.js
src/
index.js
GadgetMyChart.vue
GadgetMyList.vue
  • MyGadgetRegistryExt.java déclare le type de Gadget, le titre, la catégorie, l'icône, l'URL frontend et les données runtime.
  • src/main/frontend/src/index.js enregistre les composants Vue auprès du host Workbench.
  • vite.config.js construit un bundle UMD vers le répertoire de ressources statiques du jar plugin.

3. Extension backend​

Implémentez SparkEraTaskGadgetRegistryExt, généralement en héritant de l'implémentation vide :

@Realization(codes = "my.workbench.gadget")
public class MyGadgetRegistryExt extends BlankSparkEraTaskGadgetRegistryExt {

private static final String FRONTEND_RESOURCE =
"/spark-gadgets/my-workbench-gadget/index.umd.js";

@Override
public List<SparkEraTaskGadgetDescriptor> listGadgetDescriptors(SparkEraTaskGadgetCatalogContext context) {
SparkEraTaskGadgetDescriptor descriptor = new SparkEraTaskGadgetDescriptor();
descriptor.setCode("myChart");
descriptor.setTitle("My Chart");
descriptor.setCategory("charts");
descriptor.setIcon("bar");
descriptor.setComponent("spark$gadget-my-chart");
descriptor.setFrontendResource(FRONTEND_RESOURCE);
descriptor.setConfigurable(true);
return List.of(descriptor);
}

@Override
public SparkEraTaskGadgetRenderResult renderGadget(SparkEraTaskGadgetRenderContext context) {
if (!StringUtils.equals(context.getGadgetType(), "myChart")) {
return null;
}
SparkEraTaskGadgetRenderResult result =
SparkEraTaskGadgetRenderResult.of("myChart", "spark$gadget-my-chart");
result.getData().put("bars", List.of(Map.of("label", "Open", "value", 12)));
return result;
}
}

Champs importants :

  • code : code de type Gadget globalement unique.
  • component : clé du composant frontend, idéalement au format spark$gadget-xxx.
  • frontendResource : URL runtime de l'entrée frontend du plugin.
  • configurable : indique si le Gadget expose un panneau de configuration.

4. Auto-enregistrement frontend​

L'entrée frontend enregistre les composants après le chargement du script :

import GadgetMyChart from "./GadgetMyChart.vue";

const COMPONENTS = {
"spark$gadget-my-chart": GadgetMyChart
};

const api = typeof window === "undefined" ? null : window.__SPARK_DASHBOARD__;
if (api && typeof api.registerGadgetComponent === "function") {
Object.entries(COMPONENTS).forEach(([key, component]) => {
api.registerGadgetComponent(key, component);
});
}

Workbench collecte les frontendResource du catalog Dashboard, les déduplique puis injecte les scripts dynamiquement. Une fois chargé, le composant est disponible dans le registre du host.

5. Configuration Vite​

Utilisez le mode library de Vite et gardez Vue en external. Le plugin ne doit pas embarquer son propre Vue ; il utilise window.__SPARK_VUE__ fourni par le host.

import { resolve } from "node:path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
plugins: [vue()],
build: {
outDir: resolve(__dirname, "../../../target/classes/META-INF/resources/spark-gadgets/my-workbench-gadget"),
lib: {
entry: resolve(__dirname, "src/index.js"),
name: "MyWorkbenchGadget",
formats: ["umd"],
fileName: () => "index.umd.js",
cssFileName: "index"
},
rollupOptions: {
external: ["vue"],
output: {
globals: {
vue: "__SPARK_VUE__"
}
}
}
}
});

Résultat de build :

target/classes/META-INF/resources/spark-gadgets/my-workbench-gadget/index.umd.js
target/classes/META-INF/resources/spark-gadgets/my-workbench-gadget/index.css

Spring Boot sert automatiquement META-INF/resources, donc l'entrée runtime est :

/spark-gadgets/my-workbench-gadget/index.umd.js

6. Packaging Maven​

Dans le pom.xml du plugin, utilisez frontend-maven-plugin pour construire le frontend pendant prepare-package. Le jar final contient alors l'extension Java et les ressources frontend.

7. Règles de développement des composants​

  • Les composants reçoivent seulement des props du host comme data et t; ils ne doivent pas appeler directement les API de la plateforme.
  • Utilisez des styles scoped et les variables de thème Spark, par exemple --text-main, --card-bg, --primary.
  • Ne créez pas une autre application Vue dans le plugin.
  • Ne bundlez pas un second runtime Vue.
  • Les données sont retournées par renderGadget; le frontend se limite au rendu.
  • La configuration est stockée dans config de l'instance Gadget et lue au rendu backend.

8. Checklist de vérification​

cd src/main/frontend
npm ci
npm run build

Puis packagez le plugin :

mvn -DskipTests package

Vérifiez que le jar contient :

META-INF/resources/spark-gadgets/<plugin-code>/index.umd.js
META-INF/resources/spark-gadgets/<plugin-code>/index.css

Après le démarrage de Spark Console, ouvrez :

/spark-gadgets/<plugin-code>/index.umd.js

Si du JavaScript est retourné, le frontend du plugin est correctement servi.

9. Problèmes fréquents​

Le Gadget affiche Unsupported

La clé component ne correspond probablement pas à la clé enregistrée dans index.js, ou frontendResource n'a pas été chargé.

Les styles ne s'appliquent pas

Vérifiez que Vite génère index.css et que le script d'entrée l'injecte.

Erreurs runtime Vue

Vérifiez que Vue est external dans Vite et que output.globals.vue pointe vers __SPARK_VUE__. Le plugin ne doit pas embarquer son propre Vue.

Le plugin n'apparaît pas dans le catalog

Vérifiez que le jar plugin est une dépendance de Spark Console et que le business code @Realization(codes = "...") est scanné par Lattice.

10. Principe de livraison​

Un plugin Dashboard Gadget doit être un artifact autonome :

  • Extension Java dans le module plugin.
  • Composants Vue dans le module plugin.
  • Ressources frontend incluses dans le jar plugin.
  • Le host garde seulement le registre, le loader dynamique, l'enveloppe de carte et le fallback.

Avec ce modèle, ajouter un Gadget métier revient à ajouter une dépendance plugin, sans modifier le coeur de la plateforme.