Embulk0.10.41プラグイン作成メモ(Hishidama's Embulk 0.10.41 plugin Memo) S-JIS[2023-01-06] 変更履歴

Embulk 0.10.41 プラグイン作成

Embulk0.10.41(古い)のプラグインの作成方法のメモ。


概要

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

ただし、 0.10で0.11/1.0方式のプラグインを作ること自体は可能だが、作ったプラグインを実行する正式な方法は提供されていない。

また、Embulkは公式にはJava8のみに対応していて、例えばJava11には未対応。
Java11で実行するにはさらにひと手間かかる。


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


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.3にしておく。
(Gradle6と7の違いは、主にdependenciesの書き方に関わる)

$ cd embulk-output-example1 

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

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

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 = 8
targetCompatibility = 8

repositories {
    mavenCentral()
}

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

dependencies {
    compileOnly "org.embulk:embulk-api:0.10.41"
    compileOnly "org.embulk:embulk-spi:0.10.41"
    compile "org.embulk:embulk-util-config:0.3.2"

//  compile "YOUR_JAR_DEPENDENCY_GROUP:YOUR_JAR_DEPENDENCY_MODULE:YOUR_JAR_DEPENDENCY_VERSION"

    testCompile "org.embulk:embulk-api:0.10.41"
    testCompile "org.embulk:embulk-spi:0.10.41"
    testCompile "org.embulk:embulk-junit4:0.10.41"
    testCompile 'javax.xml.bind:jaxb-api:2.3.1' // for Java11
}

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);
					}
				});
			}
		}
	}
	@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.41"
    testCompile "io.github.hishidama.embulk:hm-embulk-tester:0.1.+"

    // https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api
    testCompile 'javax.xml.bind:jaxb-api:2.3.1' // Java11の場合
}

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

			EmbulkTestParserConfig parser = tester.newParserConfig("csv");
			parser.addColumn("c1", "string");
			parser.addColumn("c2", "long");

			ConfigSource out = tester.newConfigSource("example1");

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

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

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

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


実行環境の準備

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


M2_REPO

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

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

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

JRuby

JRubyのダウンロードサイトからjruby-completeのjarファイルをダウンロードする。

そして、ユーザーのホームディレクトリー(Windowsの場合は%USERPROFILE%)の下に「.embulk/embulk.properties」というファイルを作って、ダウンロードしたjruby-completeのjarファイルの場所を記載する。

jruby=file://C:/Users/hishidama/bin/embulk/0.10.41/jruby-complete-9.4.0.0.jar

embulk.gemとmsgpack.gem

Embulk本体と同じバージョンのembulk.gemをインストールする。
また、msgpack.gemもインストールする。

embulk gem install msgpack -v 1.1.0
embulk gem install embulk -v 0.10.41

ちなみに、embulk.propertiesにjrubyの指定を書かなかった場合、コマンドラインから指定することも出来る。

embulk -X jruby=file://C:/Users/hishidama/bin/embulk/0.10.41/jruby-complete-9.4.0.0.jar gem install msgpack -v 1.1.0
embulk -X jruby=file://C:/Users/hishidama/bin/embulk/0.10.41/jruby-complete-9.4.0.0.jar gem install embulk -v 0.10.41

プラグインの準備

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

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

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

mvnコマンドを使って、一括してMavenローカルリポジトリーにダウンロードすることが出来る。

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

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


プラグインの実行

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

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

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

●Java11(ブートクラスパスを使う方法)
java -Xbootclasspath/a:〜/jaxb-api-2.3.1.jar -jar 〜/embulk-0.10.41.jar -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)のアウトプットプラグイン(カテゴリーが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/embulk.properties

jruby=file://C:/Users/hishidama/bin/embulk/0.10.41/jruby-complete-9.4.0.0.jar
plugins.output.example1=maven:com.hishidama.embulk:example1:0.1.0-SNAPSHOT

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

java -jar 〜/embulk-0.10.41.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-01-06 12:01:52.086 +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.2" is not found: at "C:\Users\hishidama\.m2\repository" ("C:\Users\hishidama\.m2\repository").
        at org.embulk.deps.maven.MavenArtifactFinderImpl.findMavenArtifact(MavenArtifactFinderImpl.java:111)
        at org.embulk.deps.maven.MavenArtifactFinderImpl.findMavenPluginJarsWithDirectDependencies(MavenArtifactFinderImpl.java:84)
        at org.embulk.plugin.maven.MavenPluginRegistry.findPluginPaths(MavenPluginRegistry.java:110)
        at org.embulk.plugin.maven.MavenPluginRegistry.lookup(MavenPluginRegistry.java:65)
        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:107)
        at org.embulk.cli.EmbulkRun.run(EmbulkRun.java:24)
        at org.embulk.cli.Main.main(Main.java:55)
Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact org.embulk:embulk-util-config:jar:0.3.2
        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:108)
        ... 20 common frames omitted
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact org.embulk:embulk-util-config:jar:0.3.2
        at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:413)
        ... 24 common frames omitted
2023-01-06 12:01:52.095 +0900 [INFO] (0001:transaction): Embulk system property "plugins.default.output.example1" is not set.
org.embulk.config.ConfigException: OutputPlugin 'example1' is not found.

JAXBExceptionが見つからない

Java11のjavaコマンドで実行すると、JAXBExceptionクラスが見つからないというエラーが出る。

java -jar 〜/embulk-0.10.41.jar run config.yml
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
        at org.apache.bval.jsr303.ConfigurationImpl.parseValidationXml(ConfigurationImpl.java:268)
        at org.apache.bval.jsr303.ConfigurationImpl.prepare(ConfigurationImpl.java:258)
        at org.apache.bval.jsr303.ConfigurationImpl.doPrivBuildValidatorFactory(ConfigurationImpl.java:248)
        at org.apache.bval.jsr303.util.SecureActions$5.run(SecureActions.java:131)
        at org.apache.bval.jsr303.util.SecureActions$5.run(SecureActions.java:129)
        at org.apache.bval.jsr303.ConfigurationImpl.run(ConfigurationImpl.java:337)
        at org.apache.bval.jsr303.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:244)
        at org.embulk.deps.config.ModelManagerDelegateImpl.(ModelManagerDelegateImpl.java:42)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at org.embulk.deps.config.ModelManagerDelegate.of(ModelManagerDelegate.java:15)
        at org.embulk.config.ModelManager.(ModelManager.java:8)
        at org.embulk.EmbulkEmbed.createModelManager(EmbulkEmbed.java:525)
        at org.embulk.EmbulkEmbed.(EmbulkEmbed.java:86)
        at org.embulk.EmbulkEmbed.(EmbulkEmbed.java:46)
        at org.embulk.EmbulkEmbed$Bootstrap.initialize(EmbulkEmbed.java:185)
        at org.embulk.cli.EmbulkRun.runInternal(EmbulkRun.java:91)
        at org.embulk.cli.EmbulkRun.run(EmbulkRun.java:24)
        at org.embulk.cli.Main.main(Main.java:55)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
        at org.embulk.deps.SelfContainedJarAwareURLClassLoader.defineClassFromEmbulkSelfContainedJarFiles(SelfContainedJarAwareURLClassLoader.java:216)
        at org.embulk.deps.SelfContainedJarAwareURLClassLoader.access$000(SelfContainedJarAwareURLClassLoader.java:32)
        at org.embulk.deps.SelfContainedJarAwareURLClassLoader$1.run(SelfContainedJarAwareURLClassLoader.java:62)
        at org.embulk.deps.SelfContainedJarAwareURLClassLoader$1.run(SelfContainedJarAwareURLClassLoader.java:58)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at org.embulk.deps.SelfContainedJarAwareURLClassLoader.findClass(SelfContainedJarAwareURLClassLoader.java:57)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 21 more

JAXBはJava11で標準ライブラリーから外された。
EmbulkはJAXBを使っているらしいので、Java11でそのまま実行するとこのエラーが出る。

解決策としては、クラスパスにjaxb-apiのjarファイルを追加してやればいいのだが、javaコマンドでは-cpと-jarを同時に指定できない(-cpが無視される)。
-jarを使うのを辞めるか、苦肉の策としてブートクラスパスを使う方法がある。

jaxb-apiのjarファイルは、build.gradleのdependenciesに定義を入れておけば、Gradleのディレクトリーにダウンロードされているはず。

●Windowsの例
java -cp "〜/embulk-0.10.41.jar;〜/jaxb-api-2.3.1.jar" org.embulk.cli.Main run config.yml
ブートクラスパスを使う例
java -Xbootclasspath/a:〜/jaxb-api-2.3.1.jar -jar 〜/embulk-0.10.41.jar run config.yml

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