Morphia module - MultipleID complaint

340 views
Skip to first unread message

prib

unread,
Apr 14, 2011, 12:41:14 PM4/14/11
to play-framework
Hello all,

First of all congratulations to Play framework and all its community.
We've been using Play for a couple of months on a project and it's
been really great overall.

We are now migrating our model from MySQL to MongoDB, and we have
chosen to go with Morphia for its convenience and similarity to JPA.
However, we are having a problem I will try to exemplify.

We have class Content as follows:

@Entity("content")
public abstract class Content extends Model {

@Required
public String description;

@Required
public Date date;

public Content(String description, Date date) {
this.description = description;
this.date = date;
}

}

And we have another class ContentChild which is a "child" of Content
adding some more fields. This class is to be stored in the same
collection as Content.

@Entity("content")
public class ContentChild extends Content {

@Required
public int type;

@Required
public String item;

public ContentChild(String description, Date date, int type,
String item) {
super(description, date);
this.type = type;
this.item = item;
}

}

Now each time I run the app, I get a lot of errors like the following:

com.google.code.morphia.mapping.validation.ConstraintViolationException:
Number of violations: 2
MultipleId complained about models.ContentChild. : More than one @Id
Field found (_id, _id).DuplicatedAttributeNames complained about
models.ContentChild._id : Mapping to MongoDB field name '_id' is
duplicated; you cannot map different java fields to the same MongoDB
field.
at
com.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:
65)
at
com.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:
153)
at
com.google.code.morphia.mapping.MappedClass.validate(MappedClass.java:
259)
at com.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:
152)
at com.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:
140)
at com.google.code.morphia.Morphia.map(Morphia.java:55)
at play.modules.morphia.MorphiaPlugin.configureDs_(MorphiaPlugin.java:
174)
at
play.modules.morphia.MorphiaPlugin.onApplicationStart(MorphiaPlugin.java:
154)
at play.Play.start(Play.java:427)
at play.Play.detectChanges(Play.java:543)
at play.Invoker$Invocation.init(Invoker.java:100)
at Invocation.HTTP Request(Play!)

and in the end:

RuntimeException:
too many errories mapping Morphia Entity classes



I noticed that there's a similar error with Morphia Grails module
(link through Google Cache):

http://webcache.googleusercontent.com/search?q=cache:n-2Vrxt6clEJ:jira.codehaus.org/browse/GRAILSPLUGINS-2895%3Fpage%3Dcom.atlassian.jira.plugin.system.issuetabpanels%253Achangehistory-tabpanel+mongodb+%22MultipleId+complained+about%22&cd=2&hl=en&ct=clnk&source=www.google.com


But Morphia alone is supposed to work well in this scenario, as
referenced in their Wiki (look at the animals example):

http://code.google.com/p/morphia/wiki/EntityAnnotation


Any clues on how to solve this problem?

Thanks!

paulo

green

unread,
Apr 14, 2011, 7:05:36 PM4/14/11
to play-fr...@googlegroups.com
Hi Paulo,

Thanks for reporting this error. I will take a look into it.

Could you please submit this issue to https://github.com/greenlaw110/play-morphia/issues?

Regards,
Green


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.


green

unread,
Apr 14, 2011, 7:08:50 PM4/14/11
to play-fr...@googlegroups.com
BTW, since Content is an abstract class, I think you could remove the @Entity annotation from it. This could resolve the MultipleId problem in your project.

prib

unread,
Apr 14, 2011, 7:29:46 PM4/14/11
to play-framework
Hi Green!

Just came here to post my solution to find that you posted exactly the
same. Didn't thought it was so easy. :D
The @Entity annotation on the abstract class is really just a
redundancy. Dropped it, and everything works.

Thanks for your help and for your work on the Morphia module. It's
great to have MongoDB integrated with Play!

Cheers,
paulo
> >>http://webcache.googleusercontent.com/search?q=cache:n-2Vrxt6clEJ:jir...

green

unread,
Apr 14, 2011, 7:44:48 PM4/14/11
to play-fr...@googlegroups.com, prib
Hi Paulo,

Also thanks for your findings as there might be cases that the parent or ancestor class are not abstract, morphia module need to handle that anyway.

Cheers,
Green

prib

unread,
Apr 15, 2011, 4:29:09 AM4/15/11
to play-framework
Hi again Green,

There's one problem I missed related to removing the @Entity
annotation from the abstract class. If you then create a class like
this (with Content being the parent abstract class like in the
previous example):

@Entity("item")
public class Item extends Model {

@Reference
Content content;

...

}

You then get the following exception, because the @Id is only created
on @Entity annotated classes:

com.google.code.morphia.mapping.validation.ConstraintViolationException:
Number of violations: 1
ReferenceToUnidentifiable complained about models.Item.content :
models.Item.content is annotated as a @Reference but the
models.Content class is missing the @Id annotation
at
com.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:
65)
at
com.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:
153)
at
com.google.code.morphia.mapping.MappedClass.validate(MappedClass.java:
259)
at com.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:
152)
at com.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:
140)
at com.google.code.morphia.Morphia.map(Morphia.java:55)
at play.modules.morphia.MorphiaPlugin.configureDs_(MorphiaPlugin.java:
174)
at
play.modules.morphia.MorphiaPlugin.onApplicationStart(MorphiaPlugin.java:
154)
at play.Play.start(Play.java:427)
at play.Play.detectChanges(Play.java:543)
at play.Invoker$Invocation.init(Invoker.java:100)
at Invocation.HTTP Request(Play!)

There really is a need then for some kind of extra annotation to
handle this type of scenarios.
What do you think?

Cheers,
paulo

green

unread,
Apr 15, 2011, 5:30:46 AM4/15/11
to play-fr...@googlegroups.com
Hi Paulo,

In this case you need to manually define id field in Content class:

public abstract class Content extends Model {
   @Id 
   public String _id;
}

Note please don't annotate Content class with @Entity

Could you please try it and let me know the result?

Thanks,
Green

prib

unread,
Apr 15, 2011, 6:16:51 AM4/15/11
to play-framework
Hi Green,

Thanks for your reply.
Just tried it and gives the MultipleID complaint again. Probably
because I'm explicitly defining the @Id in the Content class (which
isn't annotated with @Entity), and it's automatically created in the
ContentChild class (which is annotated with @Entity).

If you have any other ideas, just shoot. I'm trying to understand a
bit more of Play! inner workings as well as modules and plugins
(didn't have to do it before :)), so I'll be working on this for now.

Cheers,
Paulo

On Apr 15, 10:30 am, green <greenlaw...@gmail.com> wrote:
> Hi Paulo,
>

green

unread,
Apr 17, 2011, 1:05:16 AM4/17/11
to play-fr...@googlegroups.com
Hi Paulo,

I have just tested adding id field to a base class and extend that class with real model. This could be done without problem. I have added new unit test cases to 1.2.1 branch, which could be found at https://github.com/greenlaw110/play-morphia/tree/1.2.1/samples-and-tests/unit-tests.

The tricky part is at the base class where you add the @id field, you have to implement several methods in addition to add an @Id field:

public static class Base extends Model {
@Id
public ObjectId _id;
@Override public Object getId() {return _id;}
@Override protected void setId_(Object id) {_id = (ObjectId)processId_(id);}
protected static Object processId_(Object id) {return (id instanceof ObjectId) ? id : new ObjectId(id.toString());}
}

This is documented in the module document: http://www.playframework.org/modules/morphia-1.2.1beta1/home. Search for "How to create Entity with user defined @Id field?".

Hope this helps.

Regards,
Green

prib

unread,
Apr 18, 2011, 4:28:19 AM4/18/11
to play-framework
That's great Green! It works!

Thank you for your precious help.

Cheers,
Paulo

On Apr 17, 6:05 am, green <greenlaw...@gmail.com> wrote:
> Hi Paulo,
>
> I have just tested adding id field to a base class and extend that class
> with real model. This could be done without problem. I have added new unit
> test cases to 1.2.1 branch, which could be found athttps://github.com/greenlaw110/play-morphia/tree/1.2.1/samples-and-te...
> .
> > > > > > > >> --...
>
> read more »
Reply all
Reply to author
Forward
0 new messages