メインコンテンツまでスキップ

Spark Workbench Dashboard Gadget プラグイン開発ガイド

このガイドは Spark Workbench Dashboard Gadget を拡張する開発者向けです。Gadget プラグインは自己完結型にするべきです。バックエンド拡張点、フロントエンド Vue コンポーネント、生成されたフロントエンド資産を同じプラグインモジュールに置き、プラットフォーム本体は読み込みと実行だけを担当します。

1. Gadget プラグインモデル​

Spark Workbench の Gadget は2つの要素で構成されます。

  • バックエンド拡張点:Lattice Ability で Gadget の記述情報を登録し、実行時データを生成します。
  • フロントエンドコンポーネント:Vue コンポーネントでデータを表示し、UMD リソースとしてパッケージして Workbench が動的に読み込みます。

既定プラグインは次の場所にあります。

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

このモジュールには Java とフロントエンドコードの両方が含まれます。サードパーティプラグインも同じ構造にすると、具体的な Gadget コードをプラットフォーム本体に置かずに済みます。

2. 推奨構成​

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 は Gadget の種類、タイトル、カテゴリ、アイコン、フロントエンドリソース URL、実行時データを定義します。
  • src/main/frontend/src/index.js は Vue コンポーネントを Workbench ホストに登録します。
  • vite.config.js は library モードで UMD をビルドし、成果物をプラグイン jar の静的リソースディレクトリへ出力します。

3. バックエンド拡張点​

SparkEraTaskGadgetRegistryExt を実装します。通常は空実装を継承します。

@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;
}
}

重要なフィールド:

  • code:グローバルに一意な Gadget タイプコード。
  • component:フロントエンド登録キー。spark$gadget-xxx 形式を推奨します。
  • frontendResource:プラグインのフロントエンド入口 JS の実行時 URL。
  • configurable:Dashboard で設定パネルを開けるかどうか。

4. フロントエンドの自己登録​

フロントエンド入口は、スクリプト読み込み後にコンポーネントを登録します。

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 は Dashboard catalog から frontendResource を収集し、重複を除いて <script> を動的に注入します。読み込み後、コンポーネントはホストの登録表で利用可能になります。

5. Vite ビルド設定​

プラグインのフロントエンドは Vite library モードを使い、Vue を external にします。プラグインは独自の Vue を同梱せず、ホストが提供する window.__SPARK_VUE__ を使います。

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__"
}
}
}
}
});

成果物:

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 は META-INF/resources を静的リソースとして提供するため、実行時 URL は次のようになります。

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

6. Maven パッケージング​

プラグイン pom.xml で frontend-maven-plugin を使い、prepare-package フェーズでフロントエンドをビルドします。最終的な plugin jar には Java 拡張点とフロントエンド資産が両方含まれます。

7. コンポーネント開発ルール​

  • コンポーネントは data や t などホストから渡される props だけを受け取り、プラットフォーム API を直接呼びません。
  • スタイルは scoped と Spark テーマ変数を使います。例:--text-main、--card-bg、--primary。
  • プラグイン内で別の Vue app を作成しないでください。
  • 2つ目の Vue ランタイムをバンドルしないでください。
  • データは renderGadget が返し、フロントエンドは表示に集中します。
  • 設定値は Gadget instance の config に保存し、バックエンドレンダリング時に読み取ります。

8. 検証チェックリスト​

cd src/main/frontend
npm ci
npm run build

次にプラグインモジュールで実行します。

mvn -DskipTests package

jar に以下が含まれることを確認します。

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

Spark Console 起動後、次を開きます。

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

JavaScript が返れば、プラグインフロントエンドは正しく提供されています。

9. よくある問題​

Gadget が Unsupported と表示される

component key と index.js の登録 key が一致していない、または frontendResource が読み込まれていない可能性があります。

スタイルが効かない

Vite が index.css を生成しているか、入口スクリプトが CSS を注入しているかを確認してください。

Vue 実行時エラー

Vite の Vue external 設定と output.globals.vue = "__SPARK_VUE__" を確認してください。プラグインは独自の Vue をバンドルしてはいけません。

Catalog にプラグインが表示されない

プラグイン jar が Spark Console の依存関係に入り、@Realization(codes = "...") の business code が Lattice にスキャンされているか確認してください。

10. 提供原則​

Dashboard Gadget プラグインは1つの自己完結 artifact として提供します。

  • Java 拡張点はプラグインモジュール内。
  • Vue コンポーネントもプラグインモジュール内。
  • フロントエンド成果物はプラグイン jar に格納。
  • プラットフォーム本体は登録表、動的ローダー、カード外枠、フォールバックコンポーネントだけを保持。

このモデルなら、業務 Gadget を追加するときにプラットフォーム本体を変更せず、プラグイン依存を追加するだけで拡張できます。