Serialize / Deserialize entity

Hi

I want to save all the versions of entities as serialized objects in the database, so to provide users with history of the full entity (I know Cuba has audit, but it is for administrators and you can see only the modified fields.
so I have an entity which stores serialized entities


public class DocumentRevision extends StandardEntity {
    private static final long serialVersionUID = 421722419472421448L;

    @Column(name = "ID_DOCUMENT", nullable = false)
    protected UUID idDocument;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "DATA_", nullable = false)
    protected Date data;

    @Column(name = "BLOB_")
    protected byte[] blob;

    public void setData(Date data) {
        this.data = data;
    }

    public Date getData() {
        return data;
    }

    public void setBlob(byte[] blob) {
        this.blob = blob;
    }

    public byte[] getBlob() {
        return blob;
    }


    public void setIdDocument(UUID idDocument) {
        this.idDocument = idDocument;
    }

    public UUID getIdDocument() {
        return idDocument;
    }
    
}

than, in Oferta Entity, I have


    @Override
    public void onBeforeDetach(Oferta entity, EntityManager entityManager) {

        byte[] data = SerializationUtils.serialize(entity);
        entity.setRevision(data);
        
    }

and


    @Override
    public void onAfterUpdate(Oferta entity, Connection connection) {

        try (Transaction tx = persistence.createTransaction()) {
        log.error("Entity after update!");

        DocumentRevision docRev = metadata.create(DocumentRevision.class);
        docRev.setBlob(entity.getRevision());

        docRev.setIdDocument(entity.getId());
        docRev.setData(entity.getCreateTs());
        persistence.getEntityManager().persist(docRev);
        tx.commit();
        }

    }

which successfully adds data to the database
when I edit Oferta Entity I want to read revision and I use


   protected void testRevision(Oferta oferta){

        LoadContext loadContext = LoadContext.create(DocumentRevision.class)
                .setQuery(LoadContext.createQuery("Select d from spica$DocumentRevision d where d.idDocument = :id")
                .setParameter("id",oferta.getId()))
                .setView(View.LOCAL);

        List<DocumentRevision> revisions = dataManager.loadList(loadContext);
        showNotification(" " + revisions.size());
        for (DocumentRevision revizie : revisions) {

            if (revizie.getBlob() != null) {

                Object obiect = SerializationUtils.deserialize(revizie.getBlob());
                Oferta ofertaVeche = (Oferta) obiect;   <---- THIS LINE GIVES THE ERROR
                showNotification(" am deserializat " + ofertaVeche.getValuta());
            }
        }
    }

and i get the error
ClassNotFoundException: com.company.spica.entity.Oferta
but com.company.spica.entity.Oferta Is actually the class of the entity and i have


import com.company.spica.entity.*;

inside the testing file …
this is the fullstack error


java.lang.ClassNotFoundException: com.company.spica.entity.Oferta
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:626)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
	at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:163)
	at org.apache.commons.lang.SerializationUtils.deserialize(SerializationUtils.java:193)
	at com.company.spica.web.oferta.OfertaEdit.testRevision(OfertaEdit.java:136)
	at com.company.spica.web.oferta.OfertaEdit.postInit(OfertaEdit.java:105)
	at com.haulmont.cuba.gui.components.AbstractEditor.setItem(AbstractEditor.java:70)
	at com.haulmont.cuba.gui.WindowManager.openEditor(WindowManager.java:721)
	at com.haulmont.cuba.web.WebWindowManager.openEditor(WebWindowManager.java:157)
	at com.haulmont.cuba.gui.components.WindowDelegate.openEditor(WindowDelegate.java:250)
	at com.haulmont.cuba.web.gui.WebWindow.openEditor(WebWindow.java:444)
	at com.haulmont.cuba.gui.components.actions.EditAction.internalOpenEditor(EditAction.java:232)
	at com.haulmont.cuba.gui.components.actions.EditAction.actionPerform(EditAction.java:225)
	at com.haulmont.cuba.web.gui.components.WebAbstractTable.handleClickAction(WebAbstractTable.java:779)
	at com.haulmont.cuba.web.gui.components.WebAbstractTable.lambda$initComponent$4fd149ee$1(WebAbstractTable.java:663)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
	at com.vaadin.ui.Table.handleClickEvent(Table.java:3221)
	at com.vaadin.ui.Table.changeVariables(Table.java:2998)
	at com.haulmont.cuba.web.toolkit.ui.CubaTable.changeVariables(CubaTable.java:252)
	at com.haulmont.cuba.web.toolkit.ui.CubaGroupTable.changeVariables(CubaGroupTable.java:144)
	at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:634)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:468)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:418)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.lambda$synchronizedHandleRequest$0(CubaVaadinServletService.java:314)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService.withUserSession(CubaVaadinServletService.java:196)
	at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.synchronizedHandleRequest(CubaVaadinServletService.java:314)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:384)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:276)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:185)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:108)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:95)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1437)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

Thank you

Sorry for not answering your question directly, but have you looked at the Entity Snapshots functionality provided by the platform? We use it extensively for the purpose you defined: “to provide users with history of the full entity”.

Entity Snapshot looks very good… I will take a couple of days to reread the full documentation :slight_smile:
I would still want to save serialized entities because I want to migrate a legacy application which has many relationships which do not use constraints and I will manually set and look for IDs.

Thank you

I am using EntitySnapshotService to save revisions and extractEntity. This covers my use case, snapshotservice is doing all the hardwork, thank you!