SAStrutsはTomcat7で動作しますか?
SAStruts、Tomcat6で動作しているアプリケーションがあり、
Tomcat7に移行することになりました。
しかし、javax.servlet.ServletRequestWrapper.isAsyncStarted(ServletRequestWrapper.java:396)
でAbstractMethodErrorが発生しております。
このメソッドには「@since Servlet 3.0」と記載があり、
requestの実体であるStruts1.2.9の「org.apache.struts.upload.MultipartRequestWrapper」には
実装されておりません。
(Javadocには「Servlet 2.3」という記載がありました。)
よって、Struts1.2.9を使用しているSAStrutsはServlet3.0に非対応で、
Servlet3.0であるTomcat7は非対応と考えました。
しかし、それならばWeb上でその情報があるかと思ったのですが全く見つからないため質問させて頂きました。
実際のコード
RequestUtil.getRequest().getRequestDispatcher(input).forward(RequestUtil.getRequest(),ResponseUtil.getResponse());
StackTrace
10 29, 2015 10:11:13 午前 org.apache.catalina.core.ApplicationDispatcher invoke
重大: サーブレット action のServlet.service()が例外を投げました
java.lang.AbstractMethodError
at javax.servlet.ServletRequestWrapper.isAsyncSupported(ServletRequestWrapper.java:407)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:225)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
その他環境
- Eclipse 4.4.1
- Java 1.7.0_67
- コンパイラー準拠レベル 1.7
- Tomcat 7.0.61
- SAStruts 1.0.4-sp7
追記1
今回の事象が発生した「MultipartRequestWrapper」はファイル送信時(htmlのformに「enctype="multipart/form-data"」が設定される場合)にStrutsがラップしてくれるクラスのようです。
(通常の場合はrequestの実体は「org.apache.catalina.core.ApplicationHttpRequest」クラスでした。)
つまり、通常はStrutsがRequestをラップしないので、Tomcatが使用しているClassそのままなので特に問題なし。
ファイル送信時にはStrutsがServlet2.3準拠?のクラスでラップしてしまうため、その後Tomcatが使用しているクラスからrequestインスタンスを使用しようとするとエラーが発生してしまうという流れかと思われます。
追記2
本来ならばコメントに書くべきと思いますが、記載できないため本文に記載させて頂きます。
ご指摘頂いた内容を試したことで、色々わかってきた気がします。ありがとうございます。
Eclipse上ではWTPで、プロジェクトファセットの設定は2.5になります。
また、mavenを使用しており、servlet-apiは以下のように指定しています。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
このため、コンパイル時には2.5が使用され、ビルド、デプロイ後には含まれないため、動作時にはTomcat7に含まれる3.0.1?が使用されているかと思われます。
tutorialでも動作確認をした所、A-pZさんのご指摘の通りアップロードのサンプルも動作致しました。(1.0.4-sp7で試しました。)
チュートリアルで「/sa-struts-tutorial/src/main/java/tutorial/action/UploadAction#upload」に今回の問題が発生したコードを追加してみた所、
RequestUtil.getRequest().getRequestDispatcher("index.jsp").forward(RequestUtil.getRequest(),ResponseUtil.getResponse());
「RequestUtil.getRequest()」で返ってくるHttpServletRequest(MultipartRequestWrapper)のgetRequestDispatcherメソッド呼び出しで呼ばれる実メソッドはlib内の「geronimo-servlet_2.4_spec-1.0.jar」が呼ばれているように見受けられます。
障害が発生している環境ではここで、Tomcat内の「servlet-api.jar」クラスが親となり3.0のメソッドが呼ばれている事が原因かと思われますがいかがでしょうか?
この場合、「servlet-api.jar」を含めて、Tomcatにもこちらを使ってもらうというのが対処になるのでしょうか?
追記3
記載が漏れておりましたが、web.xmlは2.5を指定しております。
filterも調査致しましたが、特に今回の問題と関係あるような処理は行っておりませんでした。
追記4
RequestUtil は org.seasar.struts.util.RequestUtil になります。
確かにここで3.x系のRequestを取得してしまっています。
getRequestの実装は以下の通りです。
public static HttpServletRequest getRequest() {
return SingletonS2Container.getComponent(HttpServletRequest.class);
}
追記5
現象の再現ありがとうございます!
遥か昔からあるアプリケーションの保守のため、何故ここでforwardを行っているのかはわからないというのが正直な所です。(forward後にnullを返しています。)
ただ、jspのファイル名を指定した所、問題の現象が発生せず正しく動作することを確認できました。