viritin / flow-viritin

Viritin inspired project for Vaadin Flow
Other
39 stars 15 forks source link

Is DynamicFileDownloader fully serializable? #52

Closed jorgheymans closed 2 months ago

jorgheymans commented 3 months ago

Hunting down serde errors in our app, I am having a difficult time solving this one which seems related to DynamicFileDownloader:

ERRORS DURING SERIALIZATION/DESERIALIZATION PROCESS:
====================================================
DESERIALIZATION_FAILED: ReflectiveOperationException during deserialization

DESERIALIZATION STACK. Process failed at depth 13
    - object (class "java.io.ObjectStreamClass")
    - field (class "java.lang.invoke.SerializedLambda", name: "capturedArgs", type: "class [Ljava.lang.Object;")
    - object (class "java.lang.invoke.SerializedLambda", SerializedLambda[capturingClass=class com.vaadin.flow.internal.StateNode, functionalInterfaceMethod=com/vaadin/flow/shared/Registration.remove:()V, implementation=invokeVirtual com/vaadin/flow/internal/StateNode.lambda$addDetachListener$f0f78019$1:(Lcom/vaadin/flow/server/Command;)V, instantiatedMethodType=()V, numCaptured=2])
    - custom writeObject data (class "java.util.HashMap")
    - object (class "java.util.HashMap", {fakesr=com.vaadin.flow.internal.StateNode$$Lambda$7967/0x0000000101d8f5f0@d306bb5})
    - field (class "com.vaadin.flow.internal.nodefeature.ElementAttributeMap", name: "pendingRegistrations", type: "interface java.util.Map")
    - object (class "com.vaadin.flow.internal.nodefeature.ElementAttributeMap", com.vaadin.flow.internal.nodefeature.ElementAttributeMap@4b72543e)
    - field (class "com.vaadin.flow.internal.nodefeature.ElementAttributeMap$2", name: "this$0", type: "class com.vaadin.flow.internal.nodefeature.ElementAttributeMap")
    - object (class "com.vaadin.flow.internal.nodefeature.ElementAttributeMap$2", com.vaadin.flow.internal.nodefeature.ElementAttributeMap$2@b23eba2)
    - custom writeObject data (class "java.util.ArrayList")
    - object (class "java.util.ArrayList", [com.vaadin.flow.internal.nodefeature.ElementAttributeMap$2@b23eba2])
    - field (class "com.vaadin.flow.internal.StateNode", name: "detachListeners", type: "interface java.util.List")
    - object (class "com.vaadin.flow.internal.StateNode", com.vaadin.flow.internal.StateNode@71608f9b)
    - field (class "com.vaadin.flow.dom.Node", name: "node", type: "class com.vaadin.flow.internal.StateNode")
    - object (class "com.vaadin.flow.dom.Element", <a download id="export_button" fakesr="VAADIN/dynamic/resource/0/1369f551-0015-4074-ad43-9788c109a481/dummy"><vaadin-button theme="primary" style="margin-right:var(--lumo-space-s)">
  Export
 </vaadin-button></a>)
    - field (class "com.vaadin.flow.component.Component", name: "element", type: "class com.vaadin.flow.dom.Element")
    - object (class "my.View$ExportButton", my.View$ExportButton@d962e91)
    - field (class "org.vaadin.firitin.components.DynamicFileDownloader$1", name: "this$0", type: "class org.vaadin.firitin.components.DynamicFileDownloader")
    - object (class "org.vaadin.firitin.components.DynamicFileDownloader$1", org.vaadin.firitin.components.DynamicFileDownloader$1@7ac360a9)
    - custom writeObject data (class "java.util.LinkedList")
    - object (class "java.util.LinkedList", [org.vaadin.firitin.components.DynamicFileDownloader$1@7ac360a9, eu.olaf.afis.ims.views.LocaleRequestHandler@3366261a])
    - field (class "com.vaadin.flow.server.VaadinSession", name: "requestHandlers", type: "class java.util.LinkedList")
    - custom writeObject data (class "com.vaadin.flow.server.VaadinSession")
    - object (class "com.vaadin.flow.spring.SpringVaadinSession", com.vaadin.flow.spring.SpringVaadinSession@68f22184)
    - custom writeObject data (class "java.util.HashMap")
    - root object (class "java.util.HashMap", {com.vaadin.flow.server.VaadinSession.springServlet=com.vaadin.flow.spring.SpringVaadinSession@68f22184, springServlet.lock=java.util.concurrent.locks.ReentrantLock@6ccdb842[Unlocked], clusterKey=a7c41cc4-9bd3-4646-a434-be2f06823124_SOURCE

Not fully grasping what's going on, should the functional interfaces ContentTypeGenerator, FileNameGenerator and ContentWriter not be made Serializable ?

My app is basically using it like this:

  static class ExportButton extends DynamicFileDownloader implements Serializable {
    @Serial private static final long serialVersionUID = 2064215684341400311L;

    public ExportButton(SerializableSupplier<List<Long>> idSupplier, Button realButton) {
      super(realButton, new RequestContentWriter(idSupplier));
      setId(UXIds.ViewRequestPage.export_button.name());
      setFileNameGenerator(new RequestFileNameGenerator(idSupplier));
      setContentTypeGenerator(new ExcelContentTypeGenerator());
      setDisableOnClick(true);
    }
  }

The implementations of the functional interfaces i'm setting are all marked Serializable.

mstahv commented 2 months ago

Good catch, this might be the reason I was just recently often logged out from my app during developement phase. I'll look into this for a moment....

mstahv commented 2 months ago

I think that did the trick 👍

jorgheymans commented 2 months ago

Cool, thanks, i'll test it out tomorrow.