Montag, 21. Juli 2008

GORM Inheritance & Relationships

Trying out GRAILS today, I came across an odd bug – or is it a feature? Before I get into details a class diagram of the problem at hand

I have the super class Shape, which should reference a list of ShapeAttributes. I therefore expect all sub classes  of Shape (i.e. Square and Triangle) to also have a reference to a list of ShapeAttributes. On top of that I also want to have a bi-directional relationship, so I can list all shapes (regardless of concrete implementation) from a single ShapeAttribute instance.

Here are my domain classes:

class Shape {       
static hasMany = [attributes:ShapeAttribute]
}

class Square extends Shape {

}

class Triangle extends Shape{

}

class ShapeAttribute{

String name
String value
static hasMany = [shapes: Shape]
static belongsTo = Shape

}

To test all of this I wrote the following integration test:

void testSimpleInheritance() {
def triangle = new Triangle()
def square = new Square()
def shape = new Shape()

def lengthAtt = new ShapeAttribute(name: "length", value: "value")
def shapeAtt = new ShapeAttribute(name: "type", value: "not specific")
def triangleAtt = new ShapeAttribute(name: "type", value: "triangle")
def squareAtt = new ShapeAttribute(name: "type", value: "square")
                                                                            
shape.addToAttributes shapeAtt
shapeAtt.addToShapes(shape)
triangle.addToAttributes lengthAtt
triangle.addToAttributes triangleAtt
square.addToAttributes lengthAtt
square.addToAttributes triangleAtt 
    
shape.save()
triangle.save()
square.save()          
           
assert shape.attributes.size() == 1
assert triangle.attributes.size() == 2
assert square.attributes.size() == 2

assert shapeAtt.shapes.size() == 1
assert lengthAtt.shapes.size() == 2
assert triangleAtt.shapes.size() == 1
assert squareAtt.shapes.size() == 1
}   

But the compilation of all this fails due to:

     [copy] Copying 1 file to /Users/stefansiprell/.grails/1.0.3/projects/scratchpad
org.codehaus.groovy.grails.exceptions.GrailsDomainException: No owner defined between domain classes [class Triangle] and [class ShapeAttribute] in a many-to-many relationship. Example: def belongsTo = ShapeAttribute

It seems to me, that GRAILS knows that Triangle should have a list of Attributes, but it does not know that Triangle should be the managing (i.e. belongsTo) part. What am I doing wrong? Or where is GRAILS failing?

3 Kommentare:

Stefan Siprell hat gesagt…

Compare with:
http://markmail.org/message/gwtotphlxdeehets

cake hat gesagt…

You should check if it also fails if Shape is abstract...

Stefan Siprell hat gesagt…

Thanks cake, I tried that but it did not help any :-(