しおしお

IntelliJ IDEAのことなんかを書いてます

JBeretでスクリプト言語を使用してバッチアーチファクトを作ってみる

JBeretのユーザーズガイド見てたら、「Develop Batch Artifacts in Script Languages」なる章*1があったので試してみた。

JBeretのバージョンは1.3系にする

Gradleだとこんな感じです

  compile 'org.jberet:jberet-se:1.3.0.Beta3'

使用するスクリプト言語のライブラリをdependencyに追加する

Groovyだとこんな感じになります

  compile 'org.codehaus.groovy:groovy-jsr223:2.4.7'
  compile 'org.codehaus.groovy:groovy:2.4.7'

ジョブ定義をしてみる

簡単そうなBatchletで試してみました。
このれいでは、batchletタグ内にscriptタグでBatchletの実装を定義しています。
stepContextやjobContextの参照もできます。

<job id="script-sample" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
  <step id="myStep">
    <batchlet>
      <script type="groovy">
        <![CDATA[
          println("Groovy Script!")
          println("ステップ名:${stepContext.stepName}")
        ]]>
      </script>
    </batchlet>
  </step>
</job>

実行結果

ちゃんと動いた!!!

[main] INFO org.jboss.weld.Version - WELD-000900: 2.4.1 (Final)
[main] INFO org.jboss.weld.Bootstrap - WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
[main] INFO org.jboss.weld.Bootstrap - WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
Groovy Script!
ステップ名:myStep
[Thread-1] INFO org.jboss.weld.Bootstrap - WELD-ENV-002001: Weld SE container STATIC_INSTANCE shut down
Weld SE container STATIC_INSTANCE shut down by shutdown hook

使うシーンがイメージできないけど。。。

H2データベースに複数プロセスから接続する

こんな感じに、URLに;AUTO_SERVER=TRUEをくっつけるだけでいける。

jdbc:h2:./h2/db/nablarch_example;AUTO_SERVER=TRUE

アプリ実行中にIntelliJから繋いで状態確認するレベルであればこれで問題なさそう。

Featuresによると、最初の接続を閉じた場合に実行中のトランザクションロールバックされる的なこと書いてあるので、使い方には注意が必要かな。

Spring Bootの@Valueに指定するプレースホルダのプレフィックスを変更する方法

@Valueアノテーションを使ってプロパティの値をインジェクションする場合、デフォルトではプレフィックスに${を指定する必要がある。
Javaで書いてる場合は問題ないけど、Kotlinを使うと文字列内の$は変数を展開するために使うので下のコードのようにエスケープしないとダメで残念な感じになります。

@Value("\${target.host}") private val host:String

プレフィックスはこんな感じに、PropertySourcesPlaceholderConfigurerを使うことで変更できます。

@Bean
open fun propertyConfigurer() : PropertySourcesPlaceholderConfigurer {
  val propertySourcesPlaceholderConfigurer = PropertySourcesPlaceholderConfigurer()
  propertySourcesPlaceholderConfigurer.setPlaceholderPrefix("&{")
  eturn propertySourcesPlaceholderConfigurer
}

これで、$のエスケープが不要になります。

@Value("&{target.host}") private val host:String

参考にした情報です。
stackoverflow.com

※ConfigurationPropertiesを使えばValueアノテーション使わなくていいので、単純にこの問題を回避できる。
そもそも、プロパティの値を保持するBeanはJavaで書いたほうが幸せになりそうな気もする。

IntelliJ小ネタ:Compact Empty Middle Packagesでも好きなパッケージ配下にファイルを作る!

IntelliJさんの、Project Viewでパッケージの表示状態をCompact Empty Middle packagesな状態にしていると、間のパッケージにファイルを作成することができません。

例えば、下の画像の状態でdomaパッケージを選択してファイルを作ると、domaの下に作られます。
f:id:sioiri:20160804225540p:plain

これを、siosio配下に作るかdoma配下に作るかを選択できるようにする方法です。

Registry画面を開く

Find ActionからRegistry画面を開きます。
f:id:sioiri:20160804225802p:plain

設定を変更する

「projectView.choose.directory.on.compacted.middle.packages」のチェックをオンにすることで、作成するパッケージを選択できるようになります。

f:id:sioiri:20160804230626p:plain

ファイルを作ってみると

どこに作るか聞いてくれます。いい感じです。
f:id:sioiri:20160804230110p:plain

おわり。

Spring Bootでjackson-module-kotlinを使う

Jacksonのkotlin対応モジュール をSpring Bootで使ってみる。

バージョンなど

Spring Boot:1.3.5
Jackson:2.6.6

Jacksonのkotlinモジュールを依存に追加

Gradleだとこんな感じですね

compile 'com.fasterxml.jackson.module:jackson-module-kotlin:2.6.6'

Jsonマッピングするクラス

こんな感じのクラスにマッピングする

data class Param(val str:String, val num:Int)

JacksonのKotlinモジュールを有効にする

Developing Spring Boot applications with Kotlinを参考にして追加してあげる。

  @Bean
  open fun objectMapperBuilder(): Jackson2ObjectMapperBuilder
      = Jackson2ObjectMapperBuilder().modulesToInstall(KotlinModule())

コントローラの実装

Jsonマッピングされたdata classを文字列表現で返すだけのシンプルな実装です。

@RestController
@RequestMapping("test")
open class Controller {

  @RequestMapping(consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE), method = arrayOf(RequestMethod.POST))
  @ResponseBody
  fun post(@RequestBody param: Param): String {
    return param.toString()
  }
}

動かしてみると

いい感じに動きました。

curl  -H "Content-Type: application/json" -X POST -d '{"str": "12345", "num": 100}' http://localhost:8080/test
Param(str=12345, num=100)

Spring Boot1.4系になると

Spring Boot1.4系になると、 jackson-module-kotlinを追加してあげるだけでいい感じに動いてくれます。
上の例で書いたような、KotlinModuleの設定がいらなくなる感じです。

この辺の実装が追加されてるからですかね。
spring-framework/Jackson2ObjectMapperBuilder.java at master · spring-projects/spring-framework · GitHub

おわり。

IntelliJさん標準で背景画像が設定できるようになってた

IntelliJさんの最新のEAP(build no:162.646.4)にしてみたら、
標準機能でIDEの背景画像設定できるようになってたので試してみた。

背景画像を設定する画面を開く

Find Actionから「Set Background Image」を検索して、設定画面を開きます。

下の画像の設定画面が開かれるので、お好きな画像を設定します。
f:id:sioiri:20160602114411j:plain



オプションは試してないのでよくわかりません。

背景画像が設定された!

こんな感じになります。

f:id:sioiri:20160602094103p:plain

おわり。

JBeretでジョブ定義をロジックで構築して実行する

JBeretでは、ロジックでジョブ定義を構築することが出来るみたいなので試してみた。
これを使うと、xmlでジョブ定義をすることなくバッチを実行することができるようになる。
ただし、JSRで定められているわけではないので、バッチ実行時にJBeretを直接扱う必要がある。

ドキュメントはこちら→Programmatic Job Definition with Java | JBeret User Guide

ジョブ定義を構築する

JobBuilderやStepBuilderを使ってジョブ定義を構築していく感じになる。
batchletやreaderなんかに指定する名前は、xmlに定義する時と同じようにBeanの名称を設定する。

この例だと、sample-jobジョブに2つのステップがあって、batchlet-step -> chunk-stepの順に実行される。

val job = JobBuilder("sample-job")
    .step(
        StepBuilder("batchlet-step")
            .batchlet("sampleBatchlet")
            .next("chunk-step")
            .build()
    )
    .step(
        StepBuilder("chunk-step")
            .reader("sampleItemReader")
            .writer("sampleItemWriter")
            .itemCount(2)
            .build()
    )
    .build()

ジョブを実行する

ジョブを実行するには、BatchRuntimeから取得したJobOperatorをJBeretの実装(JobOperatorImpl)にダウンキャストしてあげる。
JobOperatorImplには、JobBuilderで構築したJobオブジェクトを指定してジョブを実行するメソッドが用意されているので、それを使ってジョブを実行してあげる。

val jobOperator = BatchRuntime.getJobOperator() as JobOperatorImpl
val executionId = jobOperator.start(job, null)

ソースは全体はこちら→GitHub

おわり。