Embulk0.10.49プラグイン作成メモ(Hishidama's Embulk 0.10.49 plugin Memo) S-JIS[2023-05-04/2023-08-11] 変更履歴

Embulk 0.10.49 プラグイン作成

Embulk0.10.49のプラグインの作成方法のメモ。


概要

従来のEmbulk0.9に対し、Embulk0.11/1.0ではプラグインの作成方法が大きく変わる。
(Rubyに依存しなくなり、よく使うクラスのモジュールやパッケージも変更されている。また、プラグインの公開方法もMavenのリポジトリーを使う)
そのため、今からプラグインを作るなら0.11/1.0対応版にしたいところだが、まだ0.11は公開されていないので、0.10を使うことになる。

ただし、0.11/1.0方式で作ったプラグインを試しに実行する正式な方法はよく分からない。(ドキュメントが見つからない)
ひとまず、Mavenのローカルリポジトリーにpublishすれば実行できる。 (依存ライブラリーも全てローカルリポジトリーに入れておく必要があるので、少しだけ面倒だが)

また、Embulk0.10は公式にはJava8しか対応していないが、例えばJava11でプラグインを作って実行することは出来る。


Embulkプラグインを作る従来の方法は、embulk newでプロジェクトおよび雛形を作成することだった。
Embulk0.11/1.0方式のプラグインを作る場合、そういったコマンドは使わず、普通にJavaプロジェクトやbuild.gradleを用意する。


自分が前回Embulk0.10のプラグイン作成を試したバージョンは0.10.41だった。今回は0.10の最終版と位置づけられている0.10.49で試した。
自分が見つけた0.10.41と0.10.49の違いは以下の通り。


OutputPluginの例

プロジェクトの作成

1. プロジェクトディレクトリーを作成する

まず、プロジェクトのディレクトリーを作成する。
例えばアウトプットプラグインの場合、「embulk-output-固有名」にするのが良さそう。

$ mkdir embulk-output-example1

2. Gradleラッパーを用意する

Gradleのgradlewコマンドを用意する。

gradle-embulk-plugins(EmbulkのGradleプラグイン)のREADME.mdによると、0.5.3でGradle6や7に対応しているらしいのだが、Embulkで参考になるサイトは6系を使っていることが多いので、ここでは6系の最新である6.9.4にしておく。
(Gradle6と7の違いは、主にdependenciesの書き方に関わる)

$ cd embulk-output-example1 

$ どこかに置かれている/gradlew wrapper --gradle-version=6.9.4
〜

$ ./gradlew --version
〜
------------------------------------------------------------
Gradle 6.9.4
------------------------------------------------------------
〜

3. build.gradleを用意する

build.gradleの内容は、gradle-embulk-pluginsのGitHubにあるREADME.mdが参考になる。

org.embulk.embulk-pluginsによると、org.embulk.embulk-pluginsの最新バージョンは0.5.5。
dependenciesの各ライブラリーのバージョンはMaven Central Repositoryで確認できる。

plugins {
    id "java"
    id "maven-publish"
    id "org.embulk.embulk-plugins" version "0.5.5"
}

group = "com.hishidama.embulk"
version = "0.1.0-SNAPSHOT"
description = "An Embulk plugin to output example."

sourceCompatibility = 11
targetCompatibility = 11

repositories {
    mavenLocal()
    mavenCentral()
}

embulkPlugin {
    mainClass = "com.hishidama.embulk.output.example1.Example1OutputPlugin"
    category = "output"
    type = "example1"
}

// このjarブロックは、実は不要[2023-08-11]
jar {
    manifest {
        attributes 'Embulk-Plugin-Spi-Version': 0
    }
}

dependencies {
    compileOnly "org.embulk:embulk-api:0.10.43" // 0.10.49ではない
    compileOnly "org.embulk:embulk-spi:0.10.49"
    compile "org.embulk:embulk-util-config:0.3.3"

//  compile "YOUR_JAR_DEPENDENCY_GROUP:YOUR_JAR_DEPENDENCY_MODULE:YOUR_JAR_DEPENDENCY_VERSION"

    testCompile "org.embulk:embulk-deps:0.10.49"
    testCompile "org.embulk:embulk-junit4:0.10.49"
}

publishing {
    publications {
        maven(MavenPublication) {
            artifactId = 'embulk-output-example1'
            from components.java
        }
    }
}

sourceCompatibilityとtargetCompatibilityでJavaのバージョンを指定できる。
Embulkはまだ正式にはJava8しかサポートしていないが、Java11でも作れる。

4. ソースディレクトリーを作成する

$ mkdir -p src/main/java
$ mkdir -p src/test/java

5. Eclipseにインポートする

Eclipseには、対応するバージョンのJDKを「Installed JREs」に追加しておく必要がある。
追加されていないのにインポートすると、ビルド時にエラーになる。

  1. EclipseのFile→importでImportダイアログを開く。
  2. Gradle→Existing Gradle Projectを選択して「Next」ボタンを押す。
  3. Project root directoryにプロジェクトディレクトリー(例:embulk-output-example1)を指定して「Finish」

PluginTask

YAMLファイルに記述されたパラメーター(オプション)を取得するのに使うのが、PluginTaskインターフェース。

旧来のnewコマンドで作られた雛形をEmbulk0.10に書き換えると、以下のようになる。

Embulk0.10では、TaskやConfigのパッケージが以前とは変わっている。
Optionalも以前はcom.google.commonのものが使われていたが、Java8のOptionalに変わっている。

import org.embulk.util.config.Config;
import org.embulk.util.config.ConfigDefault;
import org.embulk.util.config.Task;
	public interface PluginTask extends Task {
		// configuration option 1 (required integer)
		@Config("option1")
		public int getOption1();

		// configuration option 2 (optional string, null is not allowed)
		@Config("option2")
		@ConfigDefault("\"myvalue\"")
		public String getOption2();

		// configuration option 3 (optional string, null is allowed)
		@Config("option3")
		@ConfigDefault("null")
		public Optional<String> getOption3();
	}

このPluginTaskインターフェースでは、ゲッターメソッドだけを定義する。
具象クラスの作成やYAMLファイルから読み込んだ値の設定はEmbulkがやってくれる。

@ConfigアノテーションでYAMLファイル内のパラメーター名を指定する。
ゲッターメソッドの戻り値の型でデータの型を指定する。
省略可能なパラメーターの場合は@ConfigDefaultアノテーションを付けてデフォルト値を指定する。省略時にnullにしたい場合は戻り型をOptionalにする。


ConfigSourceからPluginTaskのインスタンスを取得するには、ConfigMapperを使用する。
TaskSourceからPluginTaskのインスタンスを取得するには、TaskMapperを使用する。

import org.embulk.util.config.ConfigMapper;
import org.embulk.util.config.ConfigMapperFactory;
import org.embulk.util.config.TaskMapper;
	protected static final ConfigMapperFactory CONFIG_MAPPER_FACTORY = ConfigMapperFactory.builder()
		.addDefaultModules()
		.build();

	protected static final ConfigMapper CONFIG_MAPPER = CONFIG_MAPPER_FACTORY.createConfigMapper();
	protected static final TaskMapper TASK_MAPPER = CONFIG_MAPPER_FACTORY.createTaskMapper();
//		PluginTask task = config.loadConfig(PluginTask.class); // 従来の方法
		PluginTask task = CONFIG_MAPPER.map(config, PluginTask.class);
//		PluginTask task = taskSource.loadTask(PluginTask.class); // 従来の方法
		PluginTask task = TASK_MAPPER.map(taskSource, PluginTask.class);

transactionメソッド

OutputPluginのtransactionメソッドは出力のトランザクションを処理する。

	@Override
	public ConfigDiff transaction(ConfigSource config, Schema schema, int taskCount, Control control) {
		PluginTask task = CONFIG_MAPPER.map(config, PluginTask.class);

		// retryable (idempotent) output:
		// return resume(task.toTaskSource(), schema, taskCount, control);

		// non-retryable (non-idempotent) output:
		control.run(task.toTaskSource());
//		return Exec.newConfigDiff(); // 従来の方法
		return CONFIG_MAPPER_FACTORY.newConfigDiff();
	}

冪等(べきとう)な処理(何度リトライしても問題ない処理)の場合はresumeメソッドを呼び出せばいいらしい。
そうでない場合はcontrol.run()を呼び出すらしい。

例えばRDBのテーブルへのinsertであれば1回しか実行できない(2回目以降は一意制約違反になる)ので冪等ではないし、
同じ結果になるupsert(データが既存ならupdate、無いならinsert)であれば何度実行しても構わないので冪等な処理だ。

例えばRDBで「トランザクション開始→insert→コミット(失敗した際はロールバックする)」であれば、何度でも実行できるので冪等な処理だろう。

AbstractJdbcOutputPluginの場合、 前処理を行ってからcontrol.run()を呼び出し、後処理をしてからConfigDiffを返すようになっている。
(前処理・後処理はbeginとかcommitというメソッド名になっているが、RDBへのinsertのトランザクションの開始やコミットのことではない)


resumeメソッド

OutputPluginのresumeメソッドは、引数がtransactionメソッドとちょっと違うだけ。

	@Override
	public ConfigDiff resume(TaskSource taskSource, Schema schema, int taskCount, Control control) {
		PluginTask task = TASK_MAPPER.map(taskSource, PluginTask.class);

		control.run(task.toTaskSource());
		return CONFIG_MAPPER_FACTORY.newConfigDiff();
	}

AbstractJdbcOutputPluginの場合、transactionメソッドと同様に、前処理を行ってからcontrol.run()を呼び出し、 後処理をしてからConfigDiffを返すようになっている。


resumeをサポートしない場合は例外を返しておけばいいようだ。

		throw new UnsupportedOperationException("example1 output plugin does not support resuming");

cleanupメソッド

OutputPluginのcleanupメソッドは、後処理を行う。

	@Override
	public void cleanup(TaskSource taskSource, Schema schema, int taskCount, List<TaskReport> successTaskReports) {
		PluginTask task = TASK_MAPPER.map(taskSource, PluginTask.class);
		〜
	}

AbstractJdbcOutputPluginの場合、 一時的に作ったテーブルがあれば、それを削除している。


openメソッド

OutputPluginのopenメソッドは、TransactionalPageOutputインスタンスを生成して返す。

	@Override
	public TransactionalPageOutput open(TaskSource taskSource, Schema schema, int taskIndex) {
		return new Example1PageOutput(schema);
	}

TransactionalPageOutputの具象クラスは自分で用意する。(この例ではExample1PageOutput)


TransactionalPageOutput具象クラス

import org.embulk.spi.Column;
import org.embulk.spi.ColumnVisitor;
import org.embulk.spi.Exec;
import org.embulk.spi.Page;
import org.embulk.spi.PageReader;
import org.embulk.spi.Schema;
import org.embulk.spi.TransactionalPageOutput;
private static class Example1PageOutput implements TransactionalPageOutput {

	private final PageReader pageReader;
	public Example1PageOutput(Schema schema) {
//		this.pageReader = new PageReader(schema); // 従来の方法
		this.pageReader = Exec.getPageReader(schema);
	}
	@Override
	public void add(Page page) {
		Schema schema = pageReader.getSchema();
		List<Column> columns = schema.getColumns();

		pageReader.setPage(page);
		while (pageReader.nextRecord()) {
			// TODO input/parserから渡された値を出力する
			for (Column column : columns) {
				column.visit(new ColumnVisitor() {
					@Override
					public void booleanColumn(Column column) {
						boolean value = pageReader.getBoolean(column);
					}

					@Override
					public void longColumn(Column column) {
						long value = pageReader.getLong(column);
					}

					@Override
					public void doubleColumn(Column column) {
						double value = pageReader.getDouble(column);
					}

					@Override
					public void stringColumn(Column column) {
						String value = pageReader.getString(column);
					}

					@Override
					public void timestampColumn(Column column) {
						// 新方式ではjava.timeのInstantを使う
						java.time.Instant value = pageReader.getTimestampInstant(column);
					}

					@Override
					public void jsonColumn(Column column) {
//						org.msgpack.value.Value value = pageReader.getJson(column); // 従来の方法
						org.embulk.spi.json.JsonValue value = pageReader.getJsonValue(column);
					}
				});
			}
		}
	}
	@Override
	public void finish() {
		// TODO 出力をフラッシュする
	}
	@Override
	public void close() {
		pageReader.close();
	}
	@Override
	public void abort() {
	}
	@Override
	public TaskReport commit() {
//		return Exec.newTaskReport(); // 従来の方法
		return CONFIG_MAPPER_FACTORY.newTaskReport();
	}
}

タスクが成功するとcommit、失敗するとabortが呼ばれる。
closeはcommit/abortの前後に2回呼ばれるようだ。


プラグインのテスト

自作プラグインをJUnitで実行するときに便利なクラスを作ってみた。


ビルドされたjarファイル類は公開リポジトリ―には置いていないので、現時点ではgit cloneしてMavenローカルリポジトリーにpublishする必要がある。

$ cd 〜/hm-embulk-tester
$ ./gradlew publishToMavenLocal

使う側のbuild.gradleは以下のような感じ。

〜
repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    〜
    testCompile "org.embulk:embulk-junit4:0.10.49"
    testCompile "io.github.hishidama.embulk:hm-embulk-tester:0.1.+"
}

example1という名前のExample1OutputPluginクラスを実行するコードは、以下のような感じ。

import java.util.Arrays;
import java.util.List;

import org.embulk.config.ConfigSource;
import org.junit.Test;

import com.hishidama.embulk.tester.EmbulkPluginTester;
import com.hishidama.embulk.tester.EmbulkTestParserConfig;
	@Test
	public void test() {
		try (EmbulkPluginTester tester = new EmbulkPluginTester()) {
			tester.addOutputPlugin("example1", Example1OutputPlugin.class);
			tester.setInputTaskSize(2);

			List<String> inputList = Arrays.asList("abc,11", "def,22");

			// parser:
			//   type: csv
			//   columns:
			//   - {name: c1, type: string}
			//   - {name: c2, type: long}
			EmbulkTestParserConfig parser = tester.newParserConfig("csv");
			parser.addColumn("c1", "string");
			parser.addColumn("c2", "long");

			// out:
			//   type: example1
			ConfigSource out = tester.newConfigSource("example1");

			tester.runOutput(inputList, parser, out);
		}
	}

テスト実行時に遭遇したエラー

PooledBufferAllocatorが見つからない

JUnit実行時に以下のようなエラーが発生した。

java.lang.NoClassDefFoundError: org/embulk/deps/buffer/PooledBufferAllocator
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
〜
	at org.embulk.exec.PooledBufferAllocator.loadImplClass(PooledBufferAllocator.java:40)
	at org.embulk.exec.PooledBufferAllocator.(PooledBufferAllocator.java:52)
	at org.embulk.EmbulkEmbed.createBufferAllocatorFromSystemConfig(EmbulkEmbed.java:476)
	at org.embulk.EmbulkEmbed.access$000(EmbulkEmbed.java:46)
	at org.embulk.EmbulkEmbed$Bootstrap.initialize(EmbulkEmbed.java:182)
	at com.hishidama.embulk.tester.EmbulkPluginTester.getEmbulkEmbed(EmbulkPluginTester.java:134)
	at com.hishidama.embulk.tester.EmbulkPluginTester.getConfigLoader(EmbulkPluginTester.java:147)
	at com.hishidama.embulk.tester.EmbulkPluginTester.newConfigSource(EmbulkPluginTester.java:159)
	at com.hishidama.embulk.tester.EmbulkPluginTester.newConfigSource(EmbulkPluginTester.java:153)
	at jp.hishidama.embulk.output.example1.Example1Test.test(Example1Test.java:26)
〜
Caused by: java.lang.ClassNotFoundException: org.embulk.deps.buffer.PooledBufferAllocator
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 46 more

build.gradleのdependenciesにembulk-depsを追加する必要がある。

※embulk-coreにも同名のクラスがあるが、パッケージ名が異なる別クラスである。


embulkコマンドでの自作プラグインの実行

(従来の方式では、runの引数の-Lで自作プラグインの場所を指定するだけで実行できたが)
Embulk0.11/1.0方式で作ったプラグインを簡単に実行する方法は(Embulk0.10.49時点では)提供されていない。

が、ローカルのMavenリポジトリ―に置かれたモジュールを取り込む方法は用意されているので、それを使って実行することが出来る。
ただ、依存ライブラリーも全てローカルのMavenリポジトリ―に置いておく必要があるので、少し手間がかかる。


実行環境の準備

Dai MIKURUBEさんのEmbulk v0.11 でなにが変わるのか: ユーザーの皆様へを参考に、実行環境を準備する。


embulk.properties

Embulk homeの下に embulk.properties というファイルを作っておくと便利。
Javaのプロパティーファイル形式(つまり「キー=値」)で設定を記述できる。

Embulk homeは環境変数EMBULK_HOME、もしくは実行時のjavaコマンドの引数「-Xembulk_home=ディレクトリー」で指定する。
それらが指定されない場合のデフォルトは、ユーザーのホームディレクトリー(Windowsの場合は%USERPROFILE%)の下の「.embulk」。(Embulk 0.9以前と同じ)


M2_REPO

環境変数M2_REPOを定義する。(Mavenのローカルリポジトリーの場所を指定する)

Windowsの例
> set M2_REPO=%USERPROFILE%\.m2\repository

実質的には
> set M2_REPO=C:\Users\hishidama\.m2\repository

もしくは、embulk.propertiesにm2_repoを定義しておく。

m2_repo=C:/Users/hishidama/.m2/repository

プラグインの準備(インストール)

まず、依存ライブラリーをMavenローカルリポジトリーに入れる必要がある。[/2023-08-11]
依存ライブラリーはGradleのディレクトリーに入っているのでそこからコピーすればいいのだが、ディレクトリー構成が違うので、手でコピーするのは面倒くさい。

mvnコマンドを使って、一括してMavenローカルリポジトリーにダウンロードすることが出来る。
mvnコマンドに指定するpomファイルは、GradleのgeneratePomFileForMavenJavaPublicationタスクで生成できる。

cd 〜/embulk-output-example1
./gradlew generatePomFileForMavenJavaPublication
mvn install -f build/publications/maven/pom-default.xml

参考: oker1007さんのEmbulk v0.11.0, v1.0に向けたMavenプラグインのCI環境構築とMavenプラグインの導入方法 (2021/5/28版)

※このmvnコマンドを実行した場合、プラグイン本体のjarファイルもMavenによって生成される。
 このjarファイルにはGradleのembulkPluginが適用されない。すなわち、必要な情報(Embulk-Plugin-Spi-Version等)がjarファイルに入らない。
 したがって、mvnコマンドを実行した後にGradleのpublishToMavenLocalが必須。


自作プラグイン本体をMavenのローカルリポジトリーに格納する。

export JAVA_HOME=JDKのディレクトリー

cd 〜/embulk-output-example1
./gradlew publishToMavenLocal

プラグインの実行

javaコマンドでプラグインを実行する。

●Java8
java -jar 〜/embulk-0.10.49.jar -X plugins.output.example1=maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT run config.yml

●Java11(Windowsの例)
java -cp 〜/embulk-0.10.49.jar org.embulk.cli.Main -X plugins.output.example1=maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT run config.yml

config.yml

in:
  type: file
  path_prefix: 〜
  parser:
    type: csv
    columns:
    - {name: text, type: string}

out:
  type: example1

自作プラグインを使う場合、そのjarファイルの場所をEmbulk本体に教えてやる必要がある。

Embulk0.10にはMavenローカルリポジトリーからjarファイルを読み込む機能がある。(依存ライブラリーも全て読み込む)
これを使う場合、「plugins.カテゴリー.名前」というプロパティー(Embulk system property)で自作プラグインの場所を指定する。

example1という名前のアウトプットプラグイン(typeがexample1でカテゴリーがoutput)の場合、プロパティー名は「plugins.output.example1」となる。
config.ymlに「out: type: example1」という記述があると、「plugins.output.example1」プロパティーが使われるというわけだ)

プロパティーに指定する値の形式は「maven:グループ名:名前:バージョン」。
グループ名が「com.hishidama.embulk」、プラグインの名前(type)がexample1、バージョンが0.1.0-SNAPSHOTの場合、「maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT」となる。
(名前の部分はアーティファクトIDの「embulk-output-example1」を書く方が自然な気がするが、そうはなっていない)


なお、プロパティーは引数の-Xで指定する他に、embulk.propertiesで指定する方法が使える。

embulk.properties:

plugins.output.example1=maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT

実行する際に-Xでplugins.output.example1を指定する必要が無くなる。

java -jar 〜/embulk-0.10.49.jar run config.yml

実行した際に遭遇したエラーや警告

embulk runが非推奨

embulk run config.yml」のような従来の実行方法を使うと、警告が出る。

================================== [ NOTICE ] ==================================
 Embulk will not be executable as a single command, such as 'embulk run'.
 It will happen at some point in v0.11.*.

 Get ready for the removal by running Embulk with your own 'java' command line.
 Running Embulk with your own 'java' command line has already been available.

 For instance in Java 1.8 :
  java -XX:+AggressiveOpts -XX:+UseConcMarkSweepGC -jar embulk-X.Y.Z.jar run ...
  java -XX:+AggressiveOpts -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none -jar embulk-X.Y.Z.jar guess ...

 See https://github.com/embulk/embulk/issues/1496 for the details.
================================================================================

embulkコマンドは非推奨になったらしい。

java -jarでEmbulk本体のjarファイルを指定して実行する。


プラグインが見つからない

org.embulk.config.ConfigException: OutputPlugin 'example1' is not found.

自作プラグインを使うにはplugins.カテゴリー.名前」というプロパティーを指定する必要がある。

また、その他の原因(依存ライブラリーが見つからないとか)でプラグインが初期化できない場合もこのエラーになる。
(依存ライブラリーが見つからない場合でも「'example1' is not found」というメッセージが出るのは混乱の元だが^^;)


自作プラグインをMavenローカルリポジトリーから読み込む場合、依存ライブラリーも全てMavenローカルリポジトリーから読み込まれる。

依存ライブラリーがMavenローカルリポジトリーから見つからない場合は以下のようなエラーになる。

2023-05-04 16:02:11.751 +0900 [WARN] (0001:transaction): Plugin maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT specified in "plugins.output.example1" was not found. Falling back to "plugins.default.output.example1".
org.embulk.deps.maven.MavenArtifactNotFoundException: Maven artifact "org.embulk:embulk-util-config:jar:0.3.3" is not found: at "C:\Users\hishidama\.m2\repository" ("C:\Users\hishidama\.m2\repository").
        at org.embulk.deps.maven.MavenArtifactFinderImpl.findMavenArtifact(MavenArtifactFinderImpl.java:113)
        at org.embulk.deps.maven.MavenArtifactFinderImpl.findMavenPluginJarsWithDirectDependencies(MavenArtifactFinderImpl.java:86)
        at org.embulk.plugin.maven.MavenPluginRegistry.findPluginPaths(MavenPluginRegistry.java:108)
        at org.embulk.plugin.maven.MavenPluginRegistry.lookup(MavenPluginRegistry.java:63)
        at org.embulk.plugin.maven.MavenPluginSource.newPlugin(MavenPluginSource.java:33)
        at org.embulk.plugin.PluginManager.newPlugin(PluginManager.java:82)
        at org.embulk.spi.ExecSessionInternal.newPlugin(ExecSessionInternal.java:358)
        at org.embulk.spi.ExecInternal.newPlugin(ExecInternal.java:50)
        at org.embulk.exec.BulkLoader$ProcessPluginSet.(BulkLoader.java:442)
        at org.embulk.exec.BulkLoader.doRun(BulkLoader.java:516)
        at org.embulk.exec.BulkLoader.access$000(BulkLoader.java:36)
        at org.embulk.exec.BulkLoader$1.run(BulkLoader.java:353)
        at org.embulk.exec.BulkLoader$1.run(BulkLoader.java:350)
        at org.embulk.spi.ExecInternal.doWith(ExecInternal.java:26)
        at org.embulk.exec.BulkLoader.run(BulkLoader.java:350)
        at org.embulk.EmbulkEmbed.run(EmbulkEmbed.java:278)
        at org.embulk.EmbulkRunner.runInternal(EmbulkRunner.java:288)
        at org.embulk.EmbulkRunner.run(EmbulkRunner.java:153)
        at org.embulk.cli.EmbulkRun.runInternal(EmbulkRun.java:108)
        at org.embulk.cli.EmbulkRun.run(EmbulkRun.java:24)
        at org.embulk.cli.Main.main(Main.java:53)
Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact org.embulk:embulk-util-config:jar:0.3.3
        at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:423)
        at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:225)
        at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:202)
        at org.eclipse.aether.internal.impl.DefaultRepositorySystem.resolveArtifact(DefaultRepositorySystem.java:257)
        at org.embulk.deps.maven.MavenArtifactFinderImpl.findMavenArtifact(MavenArtifactFinderImpl.java:110)
        ... 20 common frames omitted
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact org.embulk:embulk-util-config:jar:0.3.3
        at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:413)
        ... 24 common frames omitted
2023-05-04 16:02:11.754 +0900 [INFO] (0001:transaction): Embulk system property "plugins.default.output.example1" is not set.
org.embulk.config.ConfigException: OutputPlugin 'example1' is not found.

SPIバージョンが指定されていない

org.embulk.config.ConfigException: OutputPlugin 'example1' is not found.
SPI version of JAR plugin is not specified.

生成されるjarファイルの中にSPIバージョンというものが必要だが、入っていない。[/2023-08-11]
(build.gradleのjar.manifest.attributesでEmbulk-Plugin-Spi-Versionを指定すれば入るが、)jarファイルの作成方法が間違っている可能性がある。

embulkPlugin(今はorg.embulk.embulk-plugins 0.5.5)を使っていれば、gradlewによってjarファイルを作成すれば自動的に入るのだが、mvnコマンドでjarファイルを生成した場合は入らない。


プラグイン作成へ戻る / Embulk目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま