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.javadé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.jsenregistre les composants Vue auprès du host Workbench.vite.config.jsconstruit 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 formatspark$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
dataett; ils ne doivent pas appeler directement les API de la plateforme. - Utilisez des styles
scopedet 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
configde 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.