eclipse-ee4j / mojarra

Mojarra, a Jakarta Faces implementation
Other
160 stars 109 forks source link

2.3: java.io.NotSerializableException: org.primefaces.model.file.UploadedFileWrapper #5117

Closed melloware closed 2 years ago

melloware commented 2 years ago

Describe the bug

Original Report: https://github.com/primefaces/primefaces/issues/1805

To Reproduce

Reproducer: pf-1805.zip

Set...

<context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

Set to server it works fine.

Steps to reproduce the behavior:

  1. Run mvn clean jetty:run
  2. Try and upload a file inside the datatable
  3. See error
Jun 16, 2022 9:08:11 AM com.sun.faces.context.AjaxExceptionHandlerImpl handlePartialResponseError
SEVERE: java.io.NotSerializableException: org.primefaces.model.file.UploadedFileWrapper
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
        at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
        at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
        at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
        at java.base/java.util.ArrayList.writeObject(ArrayList.java:897)
        at java.base/jdk.internal.reflect.GeneratedMethodAccessor54.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1145)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
        at java.base/java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1379)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
        at java.base/java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1379)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
        at java.base/java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1379)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
        at java.base/java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1379)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
        at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
        at java.base/java.util.HashMap.internalWriteEntries(HashMap.java:1840)
        at java.base/java.util.HashMap.writeObject(HashMap.java:1411)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1145)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
        at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
        at com.sun.faces.renderkit.ClientSideStateHelper.doWriteState(ClientSideStateHelper.java:383)
        at com.sun.faces.renderkit.ClientSideStateHelper.writeState(ClientSideStateHelper.java:154)
        at com.sun.faces.renderkit.ResponseStateManagerImpl.getViewState(ResponseStateManagerImpl.java:117)
        at javax.faces.application.StateManager.getViewState(StateManager.java:562)
        at com.sun.faces.context.PartialViewContextImpl.renderState(PartialViewContextImpl.java:519)
        at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:324)
        at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:65)
        at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:1102)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1648)
        at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:442)
        at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:170)
        at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:132)
        at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:132)
        at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:102)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:76)
        at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:199)
        at javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:708)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:451)
        at org.eclipse.jetty.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1450)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1631)
        at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:292)
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:191)
        at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.Server.handle(Server.java:516)
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
        at java.base/java.lang.Thread.run(Thread.java:834)

Expected behavior

No error is thrown

Run mvn clean jetty:run-exploded -Pmojarra23 and navigate to http://localhost:8080/primefaces-test/test.xhtml

As a note it fails with Mojarra 2.2.20 and 2.3.17 but works with MyFaces 2.2 and 2.3.

mvn clean jetty:run-exploded -Pmojarra22 (fails)

mvn clean jetty:run-exploded -Pmojarra23 (fails)

mvn clean jetty:run-exploded --Pmyfaces22 (passes)

mvn clean jetty:run-exploded --Pmyfaces23 (passes)

melloware commented 2 years ago

Figured the issue out its not serializing on either MyFaces or Mojarra because its a PF issue storing state.

The problem is with Native JSF uploading its using Servlet 3.0 to do the upload instead of Apache Commons Upload.

See: https://github.com/primefaces/primefaces/blob/dc062460b17ac3564118b78e1e44eae2467a05c5/primefaces/src/main/java/org/primefaces/model/file/NativeUploadedFile.java#L42

The NativeUploadedFile.java stores a javax.servlet.http.Part which is NOT Serializable and thus the error. I could make that Part transient but then it really hasn't serialized the upload to the client it would only make the error go away.

Apache Commons Upload has the same issue where private FileItem fileItem; is not Serializable.

https://github.com/primefaces/primefaces/blob/dc062460b17ac3564118b78e1e44eae2467a05c5/primefaces/src/main/java/org/primefaces/model/file/CommonsUploadedFile.java#L43