Uploaded image for project: 'Spring Web Flow'
  1. Spring Web Flow
  2. SWF-1463

JpaFlowExecutionListener shouldn't assume that EntityManager is Serializable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 2.3.0
    • Fix Version/s: None
    • Labels:
      None

      Description

      JpaFlowExecutionListener stores EntityManager into Flow Scope, assuming it will be Serializable (each object stored into this scope should be Serializable, according to the documentation). This assumption is wrong, EntityManager doesn't extend Serializable, and doesn't have to implement this interface.

      Using EclipseLink 2.2 I'm getting following exception in this case:

      org.springframework.webflow.execution.repository.snapshot.SnapshotCreationException: Could not serialize flow execution; make sure all objects stored in flow or flash scope are serializable
      org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.<init>(SerializedFlowExecutionSnapshot.java:75)
      org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory.createSnapshot(SerializedFlowExecutionSnapshotFactory.java:70)
      org.springframework.webflow.execution.repository.snapshot.AbstractSnapshottingFlowExecutionRepository.snapshot(AbstractSnapshottingFlowExecutionRepository.java:75)
      org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.putFlowExecution(DefaultFlowExecutionRepository.java:126)
      org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:145)
      org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:193)
      org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
      ...
      java.io.NotSerializableException: org.eclipse.persistence.internal.jpa.EntityManagerImpl
      java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
      java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
      java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
      java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
      ...
      java.util.HashMap.writeObject(HashMap.java:1001)
      ...
      org.springframework.webflow.core.collection.LocalAttributeMap.writeObject(LocalAttributeMap.java:327)
      sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      ...
      org.springframework.webflow.engine.impl.FlowSessionImpl.writeExternal(FlowSessionImpl.java:154)
      ...
      org.springframework.webflow.engine.impl.FlowExecutionImpl.writeExternal(FlowExecutionImpl.java:312)
      ...
      org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.serialize(SerializedFlowExecutionSnapshot.java:173)
      org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.<init>(SerializedFlowExecutionSnapshot.java:70)
      org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory.createSnapshot(SerializedFlowExecutionSnapshotFactory.java:70)
      org.springframework.webflow.execution.repository.snapshot.AbstractSnapshottingFlowExecutionRepository.snapshot(AbstractSnapshottingFlowExecutionRepository.java:75)
      org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.putFlowExecution(DefaultFlowExecutionRepository.java:126)
      org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:145)
      org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:193)
      org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)

        Activity

        Hide
        vardlokkur Michał Jaśtak added a comment -

        It looks like there is some thread related to this issue in forum - http://forum.springsource.org/showthread.php?t=59443 - Keith wrote in it: "I would bring this up with the EclipseLink team--perhaps they have this capability factored into their feature roadmap" - This issue has nothing to do with the EclipseLink - If you demand from the developers to store only Serializable objects to the Flow Scope you have to follow this guidance yourself Today we have problem with EclipseLink, tomorrow we will encounter the same with OpenJPA, or any other JPA provider you can imagine (well, except the Hibernate maybe )

        In short: The reason of this issue is wrong assumption that all implementations of EntityManager should be Serializable, while they don't have to.

        Show
        vardlokkur Michał Jaśtak added a comment - It looks like there is some thread related to this issue in forum - http://forum.springsource.org/showthread.php?t=59443 - Keith wrote in it: "I would bring this up with the EclipseLink team--perhaps they have this capability factored into their feature roadmap" - This issue has nothing to do with the EclipseLink - If you demand from the developers to store only Serializable objects to the Flow Scope you have to follow this guidance yourself Today we have problem with EclipseLink, tomorrow we will encounter the same with OpenJPA, or any other JPA provider you can imagine (well, except the Hibernate maybe ) In short: The reason of this issue is wrong assumption that all implementations of EntityManager should be Serializable, while they don't have to.
        Hide
        rstoya05-aop Rossen Stoyanchev added a comment -

        Lowering the priority since you have the option of merging your flow variables with EntityManager rather than using the persistence-context feature.

        Show
        rstoya05-aop Rossen Stoyanchev added a comment - Lowering the priority since you have the option of merging your flow variables with EntityManager rather than using the persistence-context feature.
        Hide
        koen.serneels Koen Serneels added a comment -

        Rossen: as I understand it correctly, the <persistence-context> feature is broken if the provider does not offer Serializable EntityManger.
        What do you mean with "you have the option of merging your flow variables with EntityManager" ?
        Is this an alternative somehow? Can you explain this in more detail please with maybe a small example?

        I'm facing the same problem with Hibernate 4.0 final and using the Spring embedded database:
        Caused by: java.io.NotSerializableException: org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy

        As far as I can see, the EmbeddedDatabase is a DataSource, so the EntityManager is trying to serialize a reference to a DataSource, which should be rather transient instead...

        Show
        koen.serneels Koen Serneels added a comment - Rossen: as I understand it correctly, the <persistence-context> feature is broken if the provider does not offer Serializable EntityManger. What do you mean with "you have the option of merging your flow variables with EntityManager" ? Is this an alternative somehow? Can you explain this in more detail please with maybe a small example? I'm facing the same problem with Hibernate 4.0 final and using the Spring embedded database: Caused by: java.io.NotSerializableException: org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy As far as I can see, the EmbeddedDatabase is a DataSource, so the EntityManager is trying to serialize a reference to a DataSource, which should be rather transient instead...
        Hide
        rstoya05-aop Rossen Stoyanchev added a comment -

        Koen, the flow managed PersistenceContext is indeed stored with other flow-scoped data and by default is expected to be serializable. It makes it easy to implement a "long conversation". However, I've personally ran into cases where persistence provider specific classes are not serializable, which means you can't use the feature. It is possible to turn off snapshotting by setting max-execution-snapshots=0 but that also effectively disables the back button.

        The alternative to not using a flow managed PersistenceContext is to obtain and release an EntityManager instance on every request. Objects stored in flow or other scopes longer than request scope would need to be merged with the current EntityManager instance on the last step before being saved.

        That said the error you mention above is from a Spring class and maybe within our control to address. Helping to reproduce the issue would accelerate the process if this is important to you. Have you tried using a different database?

        Show
        rstoya05-aop Rossen Stoyanchev added a comment - Koen, the flow managed PersistenceContext is indeed stored with other flow-scoped data and by default is expected to be serializable. It makes it easy to implement a "long conversation". However, I've personally ran into cases where persistence provider specific classes are not serializable, which means you can't use the feature. It is possible to turn off snapshotting by setting max-execution-snapshots=0 but that also effectively disables the back button. The alternative to not using a flow managed PersistenceContext is to obtain and release an EntityManager instance on every request. Objects stored in flow or other scopes longer than request scope would need to be merged with the current EntityManager instance on the last step before being saved. That said the error you mention above is from a Spring class and maybe within our control to address. Helping to reproduce the issue would accelerate the process if this is important to you. Have you tried using a different database?

          People

          • Assignee:
            kdonald Keith Donald
            Reporter:
            vardlokkur Michał Jaśtak
          • Votes:
            4 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:

              Development