2016年4月26日火曜日

[Gradle]依存ライブラリのバージョンの固定化

この場合、junitのバージョンは4.11に固定化される。
どこかのライブラリが新しいバージョンを落とそうとしても、強制的に4.11になる。

configurations.all {
    resolutionStrategy { 
        force 'junit:junit:4.11'
    }
}

2016年4月21日木曜日

[Oracle]パスワードの複雑度を検証する

パスワードの複雑度の検証を行うには、デフォルト(ユーザ)プロファイルのPASSWORD_VERIFY_FUNCTIONに検証を行うファンクションを設定する。
デフォルトでは、何も設定されていないので、簡単なパスワードも普通に使える状態になっている。(例えばアカウント名と同じパスワードも設定できる)

検証ロジックは、「@$ORACLE_HOME/RDBMS/ADMIN/utlpwdmg.sql」を参考にして作成すると良い。
Oracle12cの場合は、ora12c_verify_functionに検証ロジックが書かれている。

検証用ファンクションの設定方法
ALTER PROFILE default LIMIT
PASSWORD_VERIFY_FUNCTION ora12c_verify_function;

今設定されている検証用ファンクションを確認する方法
select
  profile,
  resource_name,
  resource_type,
  limit
from
  dba_profiles
where
  profile = 'DEFAULT'
  and resource_name='PASSWORD_VERIFY_FUNCTION'

結果
PROFILE         RESOURCE_NAME                  RESOURCE_TYPE   LIMIT
--------------- ------------------------------ --------------- ---------------
DEFAULT         PASSWORD_VERIFY_FUNCTION       PASSWORD        ORA12C_VERIFY_F
                                                               UNCTION

2016年4月19日火曜日

h2のバイナリリテラル表記

バイナリリテラルは、下のように文字列リテラルの前にXをつけることで表現できる。
文字列リテラルには、16進数表記の文字列を入れる。
insert into hoge (binary) values (X'3031323334353637383930');

参考→http://stackoverflow.com/questions/9320200/inline-blob-binary-data-types-in-sql-jdbc

2016年4月7日木曜日

Java8のJavadocは自己終了要素がエラーになる

Javadoc中に自己終了要素(例えば、<p />)があると、Java8のjavadocでは下のようなエラーが出力されます。

Hoge.java:3: エラー: 自己終了要素は使用できません

調べた結果、自己終了要素は使ってはダメなようです。
例えば、<p />は<p>に置き換える必要があります。

2016年4月3日日曜日

Gradleのタスクに指定できるオプションを調べる方法

Gradleのhelpタスクで、そのタスクに指定できるオプションを見ることができる。

使い方

helpタスクのオプションのtaskに対して調べたいタスク名を指定する。
gradlew help --task タスク名

実行結果

dependencyInsightタスクのhelpを見てみた結果。
このタスクは2つのオプションを指定できることなんかがわかる。
$ ./gradlew help --task dependencyInsight
:help
Detailed task information for dependencyInsight

Path
     :dependencyInsight

Type
     DependencyInsightReportTask (org.gradle.api.tasks.diagnostics.DependencyInsightReportTask)

Options
     --configuration     Looks for the dependency in given configuration.

     --dependency     Shows the details of given dependency.

Description
     Displays the insight into a specific dependency in root project 'spring-boot-in-action'.

Group
     help

2016年3月18日金曜日

H2の1.3系では、auto_incrementなカラムを持つテーブルへのバッチinsertが使いものにならない

H2の安定版の1.3系を使うと、バッチinsert後のgetGeneratedKeysが1レコードしか返さないため、データベースで設定された値を取得できない問題がある。

getGeneratedKeysのJavadocにも下の記述があるので、完全に仕様のようです。
Return a result set that contains the last generated auto-increment key
for this connection, if there was one. If no key was generated by the
last modification statement, then an empty result set is returned.
The returned result set only contains the data for the very last row.

試した結果

試したバージョンは、1.3.176となっています。
compile 'com.h2database:h2:1.3.176'

このコードを実行すると、バッチinsertで10レコード登録しているので、it.getInt(1)が10回標準出力に出力されるはずですが、実際には1回しか出力されません。
出力される値は、Javadocにあるように最後に採番された値の「it.getInt(1) = 10」となります。
jdbcDataSource.connection.use {connection ->
  connection.createStatement().use {statement ->
    statement.execute("create table test(id bigint auto_increment, name varchar(255))")
  }

  connection.prepareStatement("insert into test (name) values (?)").use { ps ->
    for (i in 1..10) {
      ps.setString(1, "name_$i")
      ps.addBatch();
    }
    ps.executeBatch()

    ps.generatedKeys.use {
      while (it.next()) {
        println("it.getInt(1) = ${it.getInt(1)}")
      }
    }
  }
}

ちなみに、Beta版の1.4系(現時点での最新の1.4.191)にするとこの問題は解消しています。

2016年3月8日火曜日

[Jackson]Java8のDate and Time APIを使ってみる

JacksonでJava8のDate and Time APIを扱うためには、依存ライブラリにjackson-datatype-jsr310を追加し、
モジュールをObjectMapperに登録する必要があります。

このモジュールを使わなかった場合、Date and Time APIのクラスのプロパティの値が、
Jsonのプロパティとして出力されるので非常に残念な結果となります。

ライブラリの追加

Gradleの場合には、以下のようになります。
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.2'

モジュールの追加

ObjectMapperのregisterModuleメソッドを使って、JavaTimeModuleを登録します。
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

実行結果

下のコードを使ってLocalDate型の値をシリアライズします。
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
System.out.println(objectMapper.writeValueAsString(LocalDate.now()));

実行結果は、以下のようになります。年月日が配列の各要素に分解されてシリアライズされます。
[ 2016, 3, 8 ]

シリアライズ時のフォーマットを変更する

シリアライズ時のフォーマットを変更する場合にはJavaTimeModuleを使わずに
jackson-datatype-jsr310に含まれるシリアライザーを直接使います。

[Jackson]特定の型に対してカスタムなシリアライザを設定する
と同じようにSimpleMoculeを使って、任意のシリアライザーを登録します。

今回は、LocalDateを使うのでjackson-datatype-jsr310に含まれるLocalDateSerializerを登録します。
LocalDateSerializerは、シリアライズ時に行うフォーマットを指定することができるのでDateTimeFormatterを使ってフォーマットを指定ます。
final ObjectMapper objectMapper = new ObjectMapper();

SimpleModule module = new SimpleModule();

// formatを指定してLocalDateSerializerを登録する。
module.addSerializer(new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyyMMdd")));
objectMapper.registerModule(module);

System.out.println(objectMapper.writeValueAsString(LocalDate.now()));

実行すると以下のように指定したフォーマットでシリアライズされます。
"20160308"