99.トラブルシューティング

概要

ここでは、「実践的な‎」ことをしようとしたとき起こるかもしれない事態のトラブルシュートを

記述してみます。

ご存じのことも多いかもしれませんが、何か参考になるとうれしいです。

主に、Spring MVC、Spring Security、Eclipse、単体テストなどのトラブルを扱います。

分類や順番は適当ですので、目次からうまく解決策を見つけてもらえればと思います。

Spring

Spring MVCで、リクエストパラメタがフォームPOJO(モデル)に設定されない

@InitBinderで、binderにsetAllowedFields などでパラメタを絞っていませんか?

その場合は、パラメタ名を追加しましょう。

もし、binderでプレフィックスを設定してる場合は、プレフィックスを除いたパラメタ名を指定します。

例: binder.setFieldDefaultPrefix("member."); とプレフィックスを指定している場合、

⇒binder.setAllowedFields("id"); "member.id"ではなく"id"だけを設定します。

@ModelAttributeメソッドが呼ばれない。

以下のような設定でステータス400などのエラーになるケース。

@ModelAttribute("form")

public Form newRequest(

@RequestParam(required=false, value="member.id") Integer memberId

) {

上記のように、数値型に対して、以下のような数字でない値を渡していませんか?

http://localhost:8080/spring_mvc_sample/input.html?member.id=5H

数値を渡すようにすると動作します。

これを型変換エラーにする方法を調べたのですが、見つかりませんでした。

海外のフォーラムでも話題に挙がっていましたが、そのフォーラムでは解決策はありませんでした。

@RequestMappingメソッドであれば、引数にBindingResultを追加すれば型変換エラーを補足できるのですが、@ModelAttributeメソッドではできないようです(2016年現在)。

SpringSecurityのJSPのタグで、SpringSecurityの式を使うとエラーが出る

There must be at least one in order to support expressions in JSP 'authorize' tags.

上記のようなエラーが出る場合、設定が不足しています。

以下のbeanをSpring設定ファイルに追記してください。

<!-- JSPタグでSpringSecurity式を使用したい場合に以下を定義する -->

<bean id="webexpressionHandler"

class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>

@ResponseBodyでStringを返した時に文字化けする

@ResponseBodyを使用しているということは、HttpMessageConverterが裏で動いていると思います。

結果、StringHttpMessageConverterが返却した文字を文字コード変換していると思いますので、

defaultCharsetプロパティを変更してあげれば解決するかと思います。

方法は以下を参照ください。

12-1.return値の変換方法(HttpMessageConverter)について

具体的な方法は以下の「Stringの内容をそのまま返す方法」などを参照ください。

12-2.return値の変換方法(HttpMessageConverter)の技術的Tips

リクエスト時にContent typeエラーが出る

以下のエラーが発生するケース。

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'xxxxxx' not supported

xxxxには例えば、「text/plain;charset=UTF-8」などが入ります。

このようなケースの場合、おそらく、@RequestBodyを引数にして、Jsonを受け付けているのではないでしょうか。

RequestMappingは成功していますが、

Jackson2のConverterが、Content-typeとして"application/json"しか許していないので、エラーになっているものと思います。

クライアントの送信Content-typeを"application/json"にするとうまく動くかと思います。

<リクエスト例(jqueryの場合)>

$.post({

"url": "http://localhost:8080/xxx/ttt.html",

"data" : JSON.stringify(params),

"contentType": "application/json; charset=utf-8",

"accept" : "application/json" ,

"method": "POST",

});

Could not find acceptable representationのようなエラーが出る

以下のエラーが発生するケース。

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

このようなケースの場合、おそらく@ResponseBodyを指定しているのではないでしょうか。

また、デバッガーなどで追うと、@RequestMappingメソッドは呼び出されているのではないでしょうか?

つまり、HttpMessageConverterを使用する処理を適用していて、コンバータが見つかっていないものと思われます。

いろいろな原因が考えられますが、よくあるのは以下かと思います。

・レスポンス処理のConverterの処理で、MediaTypeもしくはreturn型にマッチするConverterが見つからなかった。

まず、URLの拡張子が、html, xml, jsonになっていないかを確認。

⇒ContentNegotiationManagerFactoryBeanでSpringの設定を変更し、Converter決定条件に拡張子を含めないようにする。

【Spring設定ファイルの記述例】

<bean id="contentNegotiationManager"

class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">

<!-- URLの拡張子でMediaTypeを決める機能をOffにする -->

<property name="favorPathExtension" value="false" />

</bean>

<!-- Make this available across all of Spring MVC -->

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />

※原理を以下の参考リンクに書いていますので、応用が利くようにお読みいただければと思います。

上記で解決しない場合は、クライアントが送信するAcceptなどを確認ですが、以下の記事を読むと他の原因も見つかると思います。

参考:12-1.return値の変換方法(HttpMessageConverter)について

環境(およびSpring以外)

eclipseでデバッグ中に、ThreadPoolExecutor というエラーが発生し、デバッグを中断させられる

デバッグ中に何もしていないのに中断され、「ThreadPoolExecutor」というエラーが発生する場合があります。

この場合は、以下のようなことを試してみてください。

eclipseで、[ウィンドウ]-[設定] で設定プロパティを開き、以下のチェックを外します。

参考: 海外のフォーラム(デバッグ中にブレーポイントが)

dbUnitのデータExcelを更新してデバッグを実行したが、DBの値が更新したとおりにならない。

eclipse上の対象のファイルのあるパスをリフレッシュ(F5)してください。

リフレッシュしないと実行のパスにコピーされないようです。

djUnit実行しようとすると、VerifyErrorが発生した。

これは、JDK6で導入されたclassファイルの検証方式変更(JSR-202)がJDK7からは有効となっており、

それでVerifyErrorが発生したようです。

実行時のVM引数に、「-noverify」を記述して実行してみてください。

参考: 05.設計7: 単体テスト

ClassNotFoundException: org.springframework.web.context.ContextLoaderListener が発生する

tomcatを起動したときに上記のエラーが出る場合は以下のことを試してみてください。

eclipseに何かゴミが残ってしまって、クリアできていないケースがあるようです。

eclipseの以下の場所を、右クリック ⇒ クリーン を選択してクリアしてみてください。

参考: 海外のフォーラム(ClassNotFound例外が発生する)

戻るボタン(もしくは javascript: history.back()) が効かない

history.back()で前の画面に戻りたい場合でも、戻れる画面と戻れない画面がある場合。

おそらく、戻れないのはフォーム送信しているPOSTをしている画面ではないでしょうか?

通常、GETの画面は戻れますが、POSTの画面は画面キャッシュが無効になって、history.back()などで戻れないと思います。

1つの解決策は、HTTPヘッダに Cache-Control:private を追加する方法です。

これが必ずしも正しい方法とは限らないので、各自、良い方法を調べてください。

一応、Spring MVCでCache-Control:privateを追加する例を示しておきます。

<mvc:interceptors>

<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="locale" />

<!-- HTTPヘッダにCache-Control:privateを追加。POSTでもブラウザにキャッシュされるようになる。 -->

<bean class="org.springframework.web.servlet.mvc.WebContentInterceptor">

<property name="CacheControl" value="#{T(org.springframework.http.CacheControl).empty().cachePrivate()}"/>

</bean>

</mvc:interceptors>

Spring MVCのinterceptorsに追加します。

CacheControlクラスは、HTTPのレスポンスヘッダの「Cache-Control」を生成するクラスです。

上記の場合はprivateを作成しています。

Cache-Controlのセキュリティ等の一般的知識は以下も参照のこと:

https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/405.html

Created Date: 2015/03/24