質問: 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は以下のように指定しています。 ``` javax.servlet servlet-api 2.5 provided ``` このため、コンパイル時には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のファイル名を指定した所、問題の現象が発生せず正しく動作することを確認できました。
回答: Tomcat7系でもSAStrutsは動作します。 また、Tomcat7はServlet3.0"でも"動作しますが、Servlet2.x系も動作します。 確認なのですが、web.xmlにてサーブレットバージョン3.0を指定してはいないでしょうか。 ないしはservlet-api.jarの3.0をwarファイルの中へ独自で入れてはいないでしょうか。 動作確認は以下の環境で行いました。 * Preiades All in one Eclipse 4.5.0 * jdk 1.7.0_71 * コンパイラ準拠レベル 1.7 * Tomcat 7.0.61 * 動作アプリケーション : SA-Struts-tutorial 1.0.4-sp9 追記1 WEB-INF/lib 内に配置されているjarファイルを列挙します。こちらはsa-struts-tutorialのものですので、過不足がないかご確認ください。 * antlr.jar * aopalliance-1.0.jar * commons-beanutils-1.7.0.jar * commons-collections-3.1.jar * commons-digester-1.6.jar * commons-el-1.0.jar * commons-fileupload-1.2.jar * commons-io-1.3.2.jar * commons-logging-1.1.jar * commons-validator-1.2.0.jar * geronimo-annotation_1.0_spec-1.0.jar * geronimo-ejb_3.0_spec-1.0.jar * geronimo-interceptor_3.0_spec-1.0.jar * geronimo-jpa_3.0_spec-1.0.jar * geronimo-jta_1.1_spec-1.0-tsr.jar * geronimo-jta_1.1_spec-1.0.jar * jakarta-oro-2.0.8.jar * javassist-3.4.ga.jar * jstl-1.1.2.jar * log4j-1.2.13.jar * ognl-2.6.9-patch-20070908.jar * poi-3.0-FINAL.jar * s2-extension-2.4.44.jar * s2-framework-2.4.44.jar * s2-tiger-2.4.44.jar * sa-struts-1.0.4-sp9.jar * standard.jar * struts-1.2.9.jar 追記2 WTPをお使いとのことでしたので、私もWTPを使って、念のためweb.xmlにてサーブレット3.0を指定しましたが動作に問題ありませんでした。 他に考えられるとすれば、独自に追加されているjarファイルや、マルチパートリクエストを検知して動作するサーブレットフィルタがある場合は影響があるかもしれません。 追記3 情報ありがとうございます。フィルタやjarファイルの過不足などには問題はなさそうですね。 そうなると新たに疑問点が1つありまして、元々のソースにありました ``` RequestUtil.getRequest() ``` ですが、このRequestUtilはStruts1.2.9のものではなく、別のクラスでしょうか? というのも、Struts2のrequestUtilにはgetRequest()は存在しませんでした。 (おそらくMultipartRequestWrapperのgetRequest()のことかと思いますが) ここで取得しているサーブレットリクエスト(ServletRequest)の取得で、2.x系のサーブレットリクエストを取得できていないのではないか、と思います。 追記4 こちらで現象を確認できました。RequestDispatcherを取得してforward()することで同様のエラーを検出しました。 ひとつ気になるのが、SAStrutsではActionからreturnする値はjspのファイル名を指定するだけで良く(例えば、return "index.jsp")、Servlet+JSPを使った場合のようにフォワードをする必要はないのですが、フォワードしなければならない理由はありますか。 参考になれば幸いです。