[JAVA-1067] Rhino NativeDate not serialized properly Created: 02/Jan/14  Updated: 23/Jun/15  Resolved: 23/Jun/15

Status: Closed
Project: Java Driver
Component/s: Codecs
Affects Version/s: 2.11.3
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Michael Schwartz Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

rhino 1.7R5


Attachments: File exhibit-bug.tgz    
Issue Links:
Depends

 Description   

For this object (note "when" field):

var o = {
    "_id" : id,
    "when" : new Date(),
    "name"  : "MongoDB" + 'def',
    "type"  : "database",
    "count" : 1,
    "info"  : {
        x : 203,
        y : 102
    }
};

This call:

new BasicDBObject(o);

Throws the following error:

org.mozilla.javascript.WrappedException: Wrapped java.lang.IllegalArgumentException: can't serialize class org.mozilla.javascript.NativeDate 

There was a similar issue with ConsString that was fixed in the latest driver build. The "name" field above should cause the ConsString instance to be passed to the function, which works. It did not in previous version of the driver.

A fix for this would be awesome.



 Comments   
Comment by Trisha Gee [ 13/Jan/14 ]

Hi Michael,

I'm afraid we're not going to support NativeDate in the core Java driver, for the same reason that we don't support Joda dates either - we would need to add dependencies on external libraries, and we currently have no additional dependencies and do not wish to introduce any. I agree with your arguments for supporting NativeDate, but you could equally argue that Joda dates are at least as widely used as java.util.Date - we'd love to support all these date formats but we cannot without changing our policy on external dependencies.

Your comment on Nashorn is also very valid, but Java 8 also introduces the new Date/Time API for Java, which will also not be supported immediately in the new Java driver as we do not mandate Java 8 for using the driver. We are looking at ways to easily support these different Date formats, but all of them will probably require the user's application to configure their Date encoding/decoding in some way.

This problem is often handled by the layers above the driver, i.e. ODMs like Spring Data and Morphia - these libraries are designed to map different classes into the primitives the Java driver understands. The best place for a mapping between Rhino types and the Java driver would be a layer that understands the Javascript classes, like https://code.google.com/p/mongodb-jvm/

Comment by Michael Schwartz [ 12/Jan/14 ]

What I'm looking for is for the Driver to properly serialize org.mozilla.javascript.NativeDate.

I'd make the following case for supporting it:

1) Rhino is one of the oldest JavaScript engines around.
2) It is written in Java
3) All of the mongodb documentation uses JavaScript shell examples
4) supporting the proper serialization makes Rhino do #3 perfectly

The alternative is to complicate life for JavaScript developers who want to use Rhino.

http://en.wikipedia.org/wiki/Rhino_(JavaScript_engine)
(Been around since 1998)

You're going to have similar issues with the new Nashorn JavaScript engine in Java 8.

Comment by Trisha Gee [ 08/Jan/14 ]

Hi Michael,

The Java driver is only going to be able to serialise java.util.Date objects, we don't provide support for serialising any other sort of Date object - it looks like Rhino is creating a org.mozilla.javascript.NativeDate, which the Java driver doesn't know how to serialise. There's nothing else on the path that would understand how to convert a Rhino date into a plain Java date.

I can, however, get this code to work by using java.util.Date instead, by changing the the first few lines to:

var MongoClient = Packages.com.mongodb.MongoClient,
BasicDBObject = Packages.com.mongodb.BasicDBObject,
ObjectId = Packages.org.bson.types.ObjectId,
Date = Packages.java.util.Date;

There are no plans to support any other types of Date serialisation natively in the Java driver, as we can't add dependencies to other libraries that aren't needed by the majority of our users, however, if different Date types are required it is possible to create hooks to tell the driver how to encode and decode different types - this is the responsibility of the application using the driver.

When you say you're looking for a fix for this issue, are you saying you'd like the driver to support javascript Date types, or are you saying you want a solution that will do the serialisation correctly (i.e. another library)?

Comment by Michael Schwartz [ 02/Jan/14 ]

Thanks Jeff!

Feel free to contact me if you need me to test anything or provide more information or code.

Comment by Michael Schwartz [ 02/Jan/14 ]

One more thing I need to point out. I was mistaken that it was new BasicDBObject() that was failing, it is the collection.insert() call with that BasicDBObject() that is throwing the error.

Sorry for the confusion.

Comment by Michael Schwartz [ 02/Jan/14 ]

Test program created for you.

See attached tar.gz file, which contains:

mschwartz@presto  ~/src  tar tzvfp exhibit-bug.tgz
drwxrwxr-x mschwartz/mschwartz 0 2014-01-02 08:44 mongo/
rw-rr- mschwartz/mschwartz 419054 2014-01-02 08:35 mongo/mongo-java-driver-2.11.3.jar
rw-rw-r- mschwartz/mschwartz 528 2014-01-02 09:06 mongo/test.js
rw-rr- mschwartz/mschwartz 1006296 2014-01-02 08:44 mongo/rhino-1.7R5-20130223-1.jar
-rwxr-xr-x mschwartz/mschwartz 590 2014-01-02 08:44 mongo/testit.sh

testit.sh is a version of /usr/bin/rhino for Ubuntu that I hacked up a bit to use the 1.7R5 rhino and include mongo driver on the class path:

mschwartz@presto  ~/src/mongo  cat testit.sh
#!/bin/sh

JAVA_CMD="/usr/bin/java"
JAVA_OPTS=""
JAVA_CLASSPATH="./rhino-1.7R5-20130223-1.jar:./mongo-java-driver-2.11.3.jar"
JAVA_MAIN="org.mozilla.javascript.tools.shell.Main"

##

    1. Remove bootclasspath overriding for OpenJDK since
    2. it now use a mangled version of Rhino (in sun.org.mozilla.rhino package)
      ##
    3. References:
    4. <https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/255149>
    5. <http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=179>
    6. <http://www.openoffice.org/issues/show_bug.cgi?id=91641>
      ##

$JAVA_CMD $JAVA_OPTS -classpath $JAVA_CLASSPATH $JAVA_MAIN "$@"

mschwartz@presto  ~/src/mongo  cat test.js
var MongoClient = Packages.com.mongodb.MongoClient,
BasicDBObject = Packages.com.mongodb.BasicDBObject,
ObjectId = Packages.org.bson.types.ObjectId;

var client = new MongoClient(),
db = client.getDB('test'),
collection = db.getCollection('test');

var id = new ObjectId();
var o = {
"_id" : id,
"when" : new Date(),
"name" : "MongoDB" + 'def',
"type" : "database",
"count" : 1,
"info" :

{ x : 203, y : 102 }

};

var bson = new BasicDBObject(o);

collection.insert(bson);

mschwartz@presto  ~/src/mongo  ./testit.sh test.js
org.mozilla.javascript.WrappedException: Wrapped java.lang.IllegalArgumentException: can't serialize class org.mozilla.javascript.NativeDate
at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1754)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:148)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)
at org.mozilla.javascript.gen.test_js_1._c_script_0(Unknown Source)
at org.mozilla.javascript.gen.test_js_1.call(Unknown Source)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:394)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3090)
at org.mozilla.javascript.gen.test_js_1.call(Unknown Source)
at org.mozilla.javascript.gen.test_js_1.exec(Unknown Source)
at org.mozilla.javascript.tools.shell.Main.processFileSecure(Main.java:597)
at org.mozilla.javascript.tools.shell.Main.processFile(Main.java:556)
at org.mozilla.javascript.tools.shell.Main.processSource(Main.java:527)
at org.mozilla.javascript.tools.shell.Main.processFiles(Main.java:176)
at org.mozilla.javascript.tools.shell.Main$IProxy.run(Main.java:100)
at org.mozilla.javascript.Context.call(Context.java:489)
at org.mozilla.javascript.ContextFactory.call(ContextFactory.java:504)
at org.mozilla.javascript.tools.shell.Main.exec(Main.java:158)
at org.mozilla.javascript.tools.shell.Main.main(Main.java:136)
Caused by: java.lang.IllegalArgumentException: can't serialize class org.mozilla.javascript.NativeDate
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:273)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
at com.mongodb.OutMessage.putObject(OutMessage.java:289)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:76)
at com.mongodb.DBCollection.insert(DBCollection.java:60)
at com.mongodb.DBCollection.insert(DBCollection.java:105)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
... 17 more

Comment by Michael Schwartz [ 02/Jan/14 ]

I found the ConsString issue in the 2.11.2 version of the driver.

I mentioned the problem in the rhino-users google groups, or to one of the guys working with RingoJS, and was told the ConsString issue is fixed in the latest driver. Sure enough, the ConsString issue is gone in 2.11.3.

This project might help:

https://code.google.com/p/mongodb-jvm/

I think it has code to serialize the various Rhino classes. In the mean time, I'll construct a simple test case for you.

Comment by Jeffrey Yemin [ 02/Jan/14 ]

Hi Michael,

We don't have a lot of experience with users interacting with the driver via Rhino, so it would be helpful if you could provide a standalone Java program that demonstrates the exception.

Regarding the ConsString, I'm not aware of any change that was made that would effect this. Exactly which version of the driver did this not work/work in, and are you sure nothing else changed in the environment (like the version of Rhino/Java)?

Generated at Thu Feb 08 08:53:44 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.