SSG
SSG

Reputation: 314

Issue in JSON return type with Morphia & MongoDB via REST

I'm using jersey-quickstart-webapp (Glassfish, v2.22.1) to build a REST API for my MongoDB database.

The application server is Tomcat 8 (running inside IntelliJ Idea) & Morphia (v1.1.0).

a. My Org class is as follows...

@Entity(value = "orgs", noClassnameStored = true)
public class Org
{
    @Id
    @Property("id")
    private ObjectId id;
    private String name = null;
    // Some other properties

    // Getter/Setter for Object ID
    public ObjectId getId(){return id;}
    public void setId(ObjectId id){this.id = id;}

    // Getter & Setter for name...
    // the other Getter & Setter methods
}

b. My OrgResource (POST Method) is as follows...

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Org createOrg(Org org)
{
    Morphia morphia = new Morphia();
    morphia.mapPackage("com.dgfx.entity");

    try
    {
        Datastore ds = morphia.createDatastore(MongoDBHelper.getMongoClient(), "dgfx-admin");
        ds.save(org);
        System.out.println("org name = " + org.getName() + ", id = " + org.getId()); // Prints the new Org ID perfectly fine!!!
        return org;

    } catch (UnknownHostException e)
    {
        e.printStackTrace();
        return null; //TODO: Better return type
    }
}

c. The POST Request (Using Postman & ContentType:Application/JSON)...

{
    "altName": "",
    "levels": [],
    "name": "My Organisation",
    "parentId": "",
    "shortName": "",
    "type": ""
}

d. Data in the MongoDB Collection looks good after POST is executed...

> db.orgs.find();
{ "_id" : ObjectId("56a9462902c3192d88d64bc3"), "type" : "", "name" : "My Organisation", "altName" : "", "shortName" : "", "parentId" : "" }
{ "_id" : ObjectId("56a9464b02c3192d8845d128"), "type" : "", "name" : "Ecosys Clover", "altName" : "", "shortName" : "", "parentId" : "" }

e. Everything works like a charm till here and the SysOut prints the Org's newly created id...

ds.save(org);
System.out.println("org name = " + org.getName() + ", id = " + org.getId()); // Prints the new Org ID perfectly fine!!!

f. But, when the same Org is returned as a response of the POST call, it doesnt contain the new ID!!!

{
  "altName": "",
  "id": {},
  "levels": [],
  "name": "My Organisation",
  "parentId": "",
  "shortName": "",
  "type": ""
}

Do let me know if I'm doing anything wrong here? Since the Org ID is being printed from the Org Object, it seems that the insertion in DB, update on the Org object Id (via Morphia) is working fine. May be the problem lies somewhere in the return type or I'm making some very fundamental mistake somewhere...

g. Investigation done

  1. Tried changing private ObjectId id to _id : No luck
  2. Tried changing private @Property("id") to "_id" : No luck
  3. Tried simple Query on objects already created with GET : same behaviour
  4. Update another field of Org within OrgResource.POST and this does get reflected in the POST Response!

Appreciate any help and thanks in advance...

SG

Upvotes: 0

Views: 743

Answers (3)

SSG
SSG

Reputation: 314

All,

It is not really an answer on how to solve the problem but rather an workaround.

  1. I'm using String id instead of ObjectId id
  2. In the Object constructor, I create a new ObjectId and assign it to the field.
  3. While Updating the object, I re-assign the String id to make sure that the _id remains same and the object is updated rather than a new one being created.

For a structural solution, go with evanchooly's suggestion if you have the expertise though...

Regards,

SSG

Upvotes: 1

Daniel Pereira
Daniel Pereira

Reputation: 2785

You are in the right track. Remove the @Propertyannotation from the idfield, so it will be like this:

@Id
private ObjectId id;

Then you only need to get the return from the save method to retrieve the key. The code bellow ilustrates that:

Key<Org> key = ds.save(org);
org.setId(key.getId());
return org;

Now it should work properly.

Upvotes: 0

evanchooly
evanchooly

Reputation: 6243

It's been a while since I've messed with jersey but I expect you'll need to write de/serializer for ObjectId.

Upvotes: 0

Related Questions