[JAVA-102] No mechanism to specify object class for DBObjects returned from DBRef.fetch() Created: 12/Apr/10  Updated: 12/Apr/10  Resolved: 12/Apr/10

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

Type: Bug Priority: Major - P3
Reporter: William Shulman Assignee: Eliot Horowitz (Inactive)
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

This is borderline bug / feature request.

I have been happily using the DBCollection.setObjectClass(CUSTOM_CLASS) feature in my app, but unfortunately, any time I have a DBRef from one DBObject to another, I cannot direct DBRef.fetch() (actually it is DBRefBase.fetch()) to use a custom DBObject class. It always uses BasicDBObject.

One solution would be to have an optional property of DBRef to configure an object class. If none is specified the default behavior is to use BasicDBObject.

Current impl code snippet (from github):

public DBObject fetch() {
if (_loadedPointedTo)
return _pointedTo;

if (_db == null)
throw new RuntimeException("no db");

if (D)

{ System.out.println("following db pointer. ref to ns:" + _ns); Throwable t = new Throwable(); t.fillInStackTrace(); t.printStackTrace(); }

final DBCollection coll = _db.getCollectionFromString(_ns);

_pointedTo = coll.findOne(_id);
_loadedPointedTo = true;
return _pointedTo;
}



 Comments   
Comment by William Shulman [ 12/Apr/10 ]

Got it! Thank Eliot.

I thought that I had initially done as you suggested and properly configured the collection in question with my custom object class, but it turns out that the DBRef.fetch() was indirectly making use of that collection before such configuration could take place. I am now configuring all my collections with their respective custom object classes at system startup (rather than lazily as I had been doing) and everything is working as expected.

All makes good sense. Thanks again. You can close/resolve (I would do it but I dont have the right permissions).

Comment by Eliot Horowitz (Inactive) [ 12/Apr/10 ]

I don't think thats the right place to put it.

If you set it on the linked collection, it should work as is correctly.
Can you try that?

Comment by William Shulman [ 12/Apr/10 ]

I now realize that it is more complicated than this. You need to serialize the new objectClass field when you persist the ref. We dont want our json representation for dbrefs to know about and be coupled to this feature of the Java driver, that would be bad. One solution here might be to add a 'meta' field in dbref json documents that hold whatever the client wants it to, and drivers pass it along uninterpreted. Then the Java driver can stuff this objectClass info in there but it wont be semantically coupled to the Java driver, it will just be some opaque meta info as far as the system is concerned.

Might be some more gotchas as well, I'm new to mongodb

Comment by William Shulman [ 12/Apr/10 ]

Here is an impl of the solution I mention above (there may be other, better solutions):

package com.mongodb;

/**

  • Base class for DBRefs.
    */
    public class DBRefBase {

static final boolean D = Boolean.getBoolean( "DEBUG.DBREF" );

public DBRefBase(DB db , String ns , Object id)

{ this(db, ns, id, null); }

public DBRefBase(DB db , String ns , Object id, Class objectClass)

{ _db = db; _ns = ns; _id = id; _objectClass = objectClass; }

public DBObject fetch() {
if (_loadedPointedTo)
return _pointedTo;

if (_db == null)
throw new RuntimeException("no db");

if (D)

{ System.out.println("following db pointer. ref to ns:" + _ns); Throwable t = new Throwable(); t.fillInStackTrace(); t.printStackTrace(); }

final DBCollection coll = _db.getCollectionFromString(_ns);
coll.setObjectClass(_objectClass);

_pointedTo = coll.findOne(_id);
_loadedPointedTo = true;
return _pointedTo;
}

public String toString(){
return "

{ \"$ref\" : \"" + _ns + "\", \"$id\" : \"" + _id + "\" }

";
}

/**

  • Get this ref's $id.
    */
    public Object getId() { return _id; }

/**

  • Get this ref's $ref (the collection name).
    */
    public String getRef() { return _ns; }

/**

  • Get this ref's database.
    */
    public DB getDB() { return _db; }

final Object _id;
final String _ns;
final DB _db;
final Class _objectClass;

private boolean _loadedPointedTo = false;
private DBObject _pointedTo;
}

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