今日もプログラミング

IT技術とかプログラミングのこととか特にJavaを中心に書いていきます

Embulkプラグインのテストを楽にやりたい

EmbulkではJavaRubyプラグインを開発することができる。

自分は今のところJavaで開発しているので、それについて書いてみたい。

 

どうやってプラグインをテストする?

EmbulkのプラグインRubyのgemとして配布される。

そして、embulk gem install ~ で簡単にインストールできる。

また、開発時には-Iオプションを使うとgemを作らなくてもプラグインを組み込んで実行することができる。

(参考:Java で Embulk Output Plugin を書く

だが、JUnitとかでテストしたりデバッグしようとすると、プロセス起動するのはちょっと重いしめんどい。

できればJavaクラス内から実行したいところだ。

 

JavaからEmbulkを呼び出す

frsyukiさんによると、Embulkは他のJavaクラスからも呼び出せる。「EmbulkServiceをインスタンス化してInjectorを取り出し、あとはRunnerを参考に…」とのことだ。

自分はEclipseで開発しているが、この方法ならEclipse上でデバッグすることもできる!

しかし、当然この方法ではインストール済みのプラグインしか動かない。

どうやって開発中のプラグインを簡単に組み込むか、だ。

 

開発中のプラグインを組み込んでEmbulkを起動する

で、Embulkのソースを追って、プラグインを組み込むのはInjectedPluginSource.registerPluginToで、そこに必要なBinderインスタンスはModule.configureで渡されて、Moduleを登録するには…、などと調べて、結局下のようなソースでうまくいくようだ。

public class EmbulkPluginTester {
    
    private final Class<?> iface;
    private final String name;
    private final Class<?> impl;
    
    public EmbulkPluginTester(Class<?> iface, String name, Class<?> impl) 
    {
        this.iface = iface;
        this.name = name;
        this.impl = impl;
    }

    public void run(String ymlPath) throws Exception 
    {
        EmbulkService service = new EmbulkService(new EmptyConfigSource()) {
            protected Iterable<? extends Module> getAdditionalModules(ConfigSource systemConfig)
            {
                return Arrays.asList(new Module()
                {
                    @Override
                    public void configure(Binder binder)
                    {
                        InjectedPluginSource.registerPluginTo(binder, iface, name, impl);
                    }
                });
            }
        };
        Injector injector = service.getInjector();
        ConfigSource config = injector.getInstance(ConfigLoader.class).fromYamlFile(new File(ymlPath));
        ExecSession session = new ExecSession(injector, config);
        LocalExecutor executor = injector.getInstance(LocalExecutor.class);
        ExecutionResult result = executor.run(session, config);
    }

 

使い方はこんな感じ。

    // "filesplit"はymlのtypeに対応する
    EmbulkPluginTester tester = new EmbulkPluginTester(InputPlugin.class, "filesplit", LocalFileSplitInputPlugin.class);
    tester.run("/embulk/test.yml");    

なお、EmptyConfigSourceのソースはこちら。nullを渡すとぬるぽで落ちるので、ダミーのクラスを作った。

これで、EmbulkのJARファイルと、開発中のプラグインをクラスパスに置けば、実行・デバッグできるはず。

 

Java JDK 8u31
Embulk 0.5.0

 

hiroysatoさんに教えて頂き-Iオプションを追記しました