- PR -

Struts のファイルアップロードでNotSerializableException が発生

1
投稿者投稿内容
ken
会議室デビュー日: 2004/11/11
投稿数: 3
投稿日時: 2004-11-11 15:36
こんにちは。kenと申します。

現在 Servlet + JSP + Struts を使用してシステム開発をしています。
Struts のファイルアップロード機能を使用しているのですが
使用している AP サーバー のログに以下のようなエラーメッセージが
出力されます。

例外: java.io.NotSerializableException: org.apache.commons.fileupload.DeferredFileOutputStream

AP サーバーは複数台設置してロードバランサーで処理を振り分けています。
この org.apache.commons.fileupload.DeferredFileOutputStream は
commons-fileupload.jar に含まれていました。
java.io.Serializable を implements していないためだと思うのですが
このような場合どのようにすればよいのでしょうか?
自身で定義している JavaBeans などには Serializable を implements
しています。

ファイルアップロードは Action クラスで以下のように実装しています。


import org.apache.struts.upload.FormFile;
import org.apache.struts.validator.DynaValidatorForm;

public class xxxxxAction extends Action {

private static final int READ_BUFFER_SIZE = 8192;

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {

DynaValidatorForm theForm = (DynaValidatorForm) form;
FormFile formFile = (FormFile) theForm.get(BeanConst.UPLOAD);

InputStream stream = formFile.getInputStream();
byte[] buffer = new byte[READ_BUFFER_SIZE];
stream.read(buffer, 0, READ_BUFFER_SIZE)


環境
Redhat Linux AS 2.1
IBM JDK 1.4.1
Struts 1.1
IBM WebSphere 5.1

どなたかご存知のかたがおられましたらよろしくお願いいたします。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-11-11 15:44
どういった文脈で NotSerializableException が発生しているのでしょうか?

負荷分散しているとのことなのでセッションの属性をレプリケートしている際に発生しているのでしょうか。
DeferredFileOutputStream ってクラスを使ったことはありませんがクラスタ化するのであればもちろんセッションにセットする属性は Serializable である必要がありますね。
OutputStream のサブクラスを Serializable に実装するのは難しいと思いますので、セッションにセットしないようにしてはいかがでしょうか?
#それともセッションにセットしていないのに発生している?
ken
会議室デビュー日: 2004/11/11
投稿数: 3
投稿日時: 2004-11-11 17:09
ご回答ありがとうございます。

DeferredFileOutputStream クラスはプログラム中では使用していません。
org.apache.struts.upload.FormFile の内部で
Jakarta Commons の commons-fileupload.jar 内にある
DeferredFileOutputStream クラスを使用しているのだと思います。

ActionForm を struts-config.xml 内で以下のように記述しています。

<form-bean name="UserCsvUploadForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="viewId" type="java.lang.String" />
<form-property name="preViewId" type="java.lang.String" />
<form-property name="uploadFile" type="java.lang.String" />
<form-property name="upload" type="org.apache.struts.upload.FormFile" />
</form-bean>

ActionForm に org.apache.struts.upload.FormFile を
セットしていますので HTTP セッションにセットされるのでしょうね。

NotSerializableException がログに出力されているのですが処理自体は正常に行われます。
また AP サーバが1台の場合は NotSerializableException は出力されません。

試しに Jakarta Commons の DeferredFileOutputStream クラス で
Serializable を implements するように修正したのですが
今度はその中で使用されている ByteArrayOutputStream で NotSerializableException
が発生してしまいます。
これは java.io パッケージに属するクラスですので触っていません。
分散セッションの環境ではこのようなコーディングではダメなのでしょうか?

以下はログに出力されているメッセージです。

[04/11/08 10:37:44:643 JST] 312d95d8 DRSCacheApp E DRSW0008E: 例外: java.io.NotSerializableException: org.apache.commons.fileupload.DeferredFileOutputStream
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java(Inlined Compiled Code))
at java.util.ArrayList.writeObject(ArrayList.java(Compiled Code))
at sun.reflect.GeneratedMethodAccessor995.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java(Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java(Compiled Code))
at java.util.HashMap.writeObject(HashMap.java(Compiled Code))
at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java(Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java(Inlined Compiled Code))
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java(Compiled Code))
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java(Compiled Code))
at com.ibm.ws.drs.DRSUtils.getBytes(DRSUtils.java(Compiled Code))
at com.ibm.ws.drs.DRSCacheApp.getBytes(DRSCacheApp.java(Inlined Compiled Code))
at com.ibm.ws.webcontainer.httpsession.DRSHttpSessCache.setJCMPropObj(DRSHttpSessCache.java(Compiled Code))
at com.ibm.ws.drs.DRSAPI.updateEntryProp(DRSAPI.java(Compiled Code))
at com.ibm.ws.drs.DRSCacheApp.updateEntryProp(DRSCacheApp.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.DRSBackedHashtable.handlePropertyHits(DRSBackedHashtable.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.DRSBackedHashtable.persistSession(DRSBackedHashtable.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.BackedHashtable.ejbStore(BackedHashtable.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.BackedHashtable.storeSession(BackedHashtable.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.BackedHashtable.put(BackedHashtable.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.DatabaseSessionContext.sync(DatabaseSessionContext.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.SessionData.releaseSession(SessionData.java(Compiled Code))
at com.ibm.ws.webcontainer.httpsession.SessionContext.sessionPostInvoke(SessionContext.java(Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppDispatcherContext.sessionPostInvoke(WebAppDispatcherContext.java(Inlined Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java(Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java(Compiled Code))
at org.apache.struts.action.RequestProcessor.doForward(RequestProcessor.java:1069)
at org.apache.struts.action.RequestProcessor.processForwardConfig(RequestProcessor.java:455)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:279)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java(Compiled Code))
at javax.servlet.http.HttpServlet.service(HttpServlet.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.StrictServletInstance.doService(StrictServletInstance.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet._service(StrictLifecycleServlet.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.IdleServletState.service(StrictLifecycleServlet.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet.service(StrictLifecycleServlet.java(Inlined Compiled Code))
at com.ibm.ws.webcontainer.servlet.ServletInstance.service(ServletInstance.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.ValidServletReferenceState.dispatch(ValidServletReferenceState.java(Compiled Code))
at com.ibm.ws.webcontainer.servlet.ServletInstanceReference.dispatch(ServletInstanceReference.java(Inlined Compiled Code))
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java(Compiled Code))
at jp.co.calm.sec.authserver.filter.AuthorityFilter.doFilter(Unknown Source)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java(Compiled Code))
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java(Compiled Code))
at jp.co.calm.sec.authserver.filter.SetCharacterEncodingFilter.doFilter(Unknown Source)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java(Compiled Code))
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java(Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.handleWebAppDispatch(WebAppRequestDispatcher.java(Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java(Compiled Code))
at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java(Compiled Code))
at com.ibm.ws.webcontainer.srt.WebAppInvoker.doForward(WebAppInvoker.java(Compiled Code))
at com.ibm.ws.webcontainer.srt.WebAppInvoker.handleInvocationHook(WebAppInvoker.java(Compiled Code))
at com.ibm.ws.webcontainer.cache.invocation.CachedInvocation.handleInvocation(CachedInvocation.java(Compiled Code))
at com.ibm.ws.webcontainer.srp.ServletRequestProcessor.dispatchByURI(ServletRequestProcessor.java(Compiled Code))
at com.ibm.ws.webcontainer.oselistener.OSEListenerDispatcher.service(OSEListener.java(Compiled Code))
at com.ibm.ws.webcontainer.http.HttpConnection.handleRequest(HttpConnection.java(Compiled Code))
at com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java(Compiled Code))
at com.ibm.ws.http.HttpConnection.run(HttpConnection.java(Compiled Code))
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java(Compiled Code))

山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-11-11 17:15
ローカルのディスクに書き込んだファイルを参照しているオブジェクトをレプリケートしても他のサーバでは役に立ちませんから、FormFile を含む FormBean をセッションに放り込むべきではありませんね。

または、フェールオーバを必要としないのであればクラスタリングを行わず、セッションIDでロード場欄寝具させればOkです。レプリケートさせなければシリアライズ-デシリアライズは行われないと思いますので。
ken
会議室デビュー日: 2004/11/11
投稿数: 3
投稿日時: 2004-11-26 13:52
ご返事が遅くなり申し訳ありませんでした。

現象が発生する環境で試すことができました。
以下そのご報告です。
struts-config.xmlファイルのアクションクラスの定義の
スコープを session から request にすることで解消されました。

<action path="/xxxx/xxxx"
type="xx.xx.xx.xxxxxx"
name="xxxxxx"
validate="false"
scope="session">

scope="request">

ご教示いただきましてありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)