20
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring MVCのインデックス付き配列パラメータには上限値がある

Last updated at Posted at 2016-11-03

Spring MVCでは、リクエストパラメータをJava Bean(=フォームオブジェクト)にバインディングしてControllerのメソッドで受け取ることができ、リストや配列のプロパティについては、インデックス付き配列パラメータ(例:ids[0])を使用して値を設定する位置を明示的に指定することができます。

デフォルトの上限値

インデックス付き配列パラメータのデフォルトの上限値は256です。

以下に示すJava Beanにバインディングするとすれば・・・

public class SearchQuery {
    private List<String> ids;
    // ...
}

ids[0]ids[255]までが有効なパラメータで、ids[256]は無効なパラメータとして扱われます。

Warning:

仕組み上はintの最大値(2147483647)まで増やすことができますが、無闇に数を増やすとOutOfMemoryErrorの発生リスクが増えるので注意しましょう。

上限値の変更

上限値は、org.springframework.web.bind.WebDataBindersetAutoGrowCollectionLimitメソッドを呼び出すことで変更することができます。具体的には、@InitBinderメソッドを使用します。

上限値を256から512にする場合の設定例
@InitBinder
public void configureWebDataBinder(WebDataBinder binder){
    binder.setAutoGrowCollectionLimit(512);
}

アプリケーション全体で上限値を変更したい場合は、@ControllerAdviceを付与してクラスで上記メソッドを実装するのがよいでしょう。

Warning:

setAutoGrowCollectionLimitメソッドを呼び出す前に、registerCustomEditoraddCustomFormatterメソッドなどを呼び出してしまうと上限値の変更が無視される(無効なメソッド呼び出しになる)ので注意してください。なお、Spring 4.3.4までは無効なメソッド呼び出しを行ってもエラーになりませんが、2016/12/20リリース予定のSpring 4.3.5からはエラーになってくれます!!(SPR-14888)。

上限値を超えた時の動作

上限値を超えるインデックス付きパラメータが指定された場合は、無効なパラメータとして扱われ、デフォルトの動作ではシステムエラー(500: Internal Server Error)になります。

Note:

この動作は個人的にはバグなのでは?と思っており、クライアントエラー(400: Bad Request)として扱ってほしい!!というIssue(SPR-14874)を作成してみました。

エラーレスポンスのカスタマイズ

デフォルトの動作だと、上限値を超えるとシステムエラーになってしまいます。このケースは、クライアントからのリクエスト内容が間違っているのが原因なので、クライアントエラーとして扱いたいはずです。
上限値を超えるとorg.springframework.beans.InvalidPropertyExceptionが発生するため、@ExceptionHandlerメソッドでこの例外をハンドリングすればエラーレスポンスをカスタマイズすることができます。

上限値を超えた時のエラーレスポンスのカスタマイズ例
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleInvalidPropertyException(InvalidPropertyException e) {
    logger.warn("detected an invalid request.", e);
    return "Bad Request !!";
}

Warning:

InvalidPropertyExceptionは、上限値を超えた時以外にも発生する例外なので、作成するアプリケーションによっては、細かく例外ハンドリングする必要がでてくるかもしれません。

まとめ

おそらく、ほとんどのアプリケーションでデフォルト値(256)がそのまま使えると思います。
以外に見落としがちなのが・・・インデックス付き配列パラメータを使う場合のエラーハンドリングだと思います。どうするのがベストプラクティスなのかはまだわかっていませんが、デフォルトだとシステムエラー扱いになってしまうことは意識しておくべきでしょう。

20
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?