Search code examples
javaxpagesssjs

Cannot serialize JavaScript function


I'm trying to change the page persistence in our XPages application, intending to move from "Keep pages in memory" to "Keep only the current page in memory". And of course I get run-time errors telling me that XPages cannot serialize a JavaScript function. But which function? The stack trace only shows the standard Java error stuff, but nothing about which variable or function cannot be serialized?

I had similar issues before, and it always cost me a lot of time to dig deep in the code and solve the problem. It takes ages... and I've really had it by now.

Is there a clever way to find out which function cannot be serialized??

UPDATE

What OpenLog Logger comes up with:

Client Version
Release 9.0.1FP3
January  12, 2015
Database    aalto803.nsf
Agent   /aASK.xsp
Method  class java.lang.StackTraceElement.writeValue
Error Num   -
Error Line  364
Error Msg   Impossible de sérialiser une fonction JavaScript
Language    Java

Stack Trace
java.io.IOException: Impossible de sérialiser une fonction JavaScript
at com.ibm.jscript.types.FBSValue.writeValue(FBSValue.java:364)
at com.ibm.jscript.types.FBSDefaultObject.writeExternal(FBSDefaultObject.java:746)
at com.ibm.jscript.std.ObjectObject.writeExternal(ObjectObject.java:106)
at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at java.util.HashMap.writeObject(HashMap.java:942)
at sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1020)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1502)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
at java.io.ObjectOutputStream.writeUnshared(ObjectOutputStream.java:413)
at com.ibm.xsp.application.AbstractSerializingStateManager$FastObjectOutputStream.writeObjectEx(AbstractSerializingStateManager.java:438)
at com.ibm.xsp.application.AbstractSerializingStateManager$FastObjectOutputStream.writeObjectEx(AbstractSerializingStateManager.java:417)
at com.ibm.xsp.application.AbstractSerializingStateManager$FastObjectOutputStream.writeObjectEx(AbstractSerializingStateManager.java:417)
at com.ibm.xsp.application.AbstractSerializingStateManager$FastObjectOutputStream.writeObjectEx(AbstractSerializingStateManager.java:417)
at com.ibm.xsp.application.AbstractSerializingStateManager$FastObjectOutputStream.writeObjectEx(AbstractSerializingStateManager.java:417)
at com.ibm.xsp.application.AbstractSerializingStateManager.saveSerializedView(AbstractSerializingStateManager.java:294)
at com.ibm.xsp.application.AbstractSerializingStateManager.doSaveSerializedView(AbstractSerializingStateManager.java:269)
at com.ibm.xsp.application.FileStateManager.doSaveSerializedView(FileStateManager.java:290)
at com.ibm.xsp.application.FileStateManager.doSaveSerializedView(FileStateManager.java:270)
at com.ibm.xsp.application.AbstractStateManager.saveSerializedView(AbstractStateManager.java:114)
at com.ibm.xsp.application.StateManagerImpl.saveSerializedView(StateManagerImpl.java:152)
at com.ibm.xsp.application.ViewHandlerExImpl._saveViewState(ViewHandlerExImpl.java:455)
at com.ibm.xsp.application.ViewHandlerExImpl.saveViewState(ViewHandlerExImpl.java:449)
at com.ibm.xsp.application.ViewHandlerExImpl._renderView(ViewHandlerExImpl.java:324)
at com.ibm.xsp.application.ViewHandlerExImpl.renderView(ViewHandlerExImpl.java:336)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:103)

Solution

  • A recent discovery of mine answers this question too IMHO, see XPages: how to put a Java Date value in an ObjectObject . A few years back, I started with moving my code from SSJS to Java, and I had some (better: a lot of) trouble with the ObjectObject and ArrayObject classes, mostly with the rather ugly way values have to be converted using a class called FBSUtility.

    My main issue was with the fact that I couldn't manage to store a Date in an ObjectObject object. In a later stage, I was happy to have found a call with a JSContext parameter, FBSUtility.wrap(jsContext, someDate), which permits storing a Date value. Call me clueless, about what the JSContext actually does here (which I am), but I thought that was the end to it.

    Recently, in order to test our application, I changed the Persistence Mode, from a few pages in memory to everything on disk, hence forcing the serialization of all objects. I found out that a specific element of my application no longer worked, always stopping on a Serialization error. Further tests proved that there were no errors when I removed all Date values from the OO object.

    Earlier, I had already adopted JsonJavaObject and JsonJavaArray classes for some other parts of the application (yeah I know, messy coding, big application, never time to do things right, 50 Mb template db, etc.). I rewrote the code to remove all use of the classes JSContext, FBSUtility, ObjectObject and ArrayObject, to replace them with the JsonJava classes, and there's no longer the dreaded message that a JS function cannot be serialized.

    So, what I learned is: if your Persistence Mode is set to Keep pages on Disk or Keep only the current page in memory, try avoid ObjectObject objects and never use FBSUtility in combination with JSContext.