lazily-fetched properties that are interfaces are not proxied correctly
delocalizer opened this issue · 3 comments
The proxy returned by RdfGenerator#getProxyOrDbObject does not seem to have correct class hierarchy for properties that are interfaces.
== example ==
(see my comment in #106 about the workaround annotation of setters with @OneToMany)
Child.java:
package au.edu.qimr.grafli.generated; import com.clarkparsia.empire.SupportsRdfId; import com.clarkparsia.empire.annotation.*; import java.util.*; import javax.persistence.*; @javax.persistence.Entity // Fully-qualified to distinguish from PROV-O 'Entity' @RdfsClass("ex:Child") @Namespaces({"ex", "http://example.org/"}) public interface Child extends SupportsRdfId { @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.PERSIST) @RdfProperty("ex:isChildOf") public List getIsChildOf(); @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.PERSIST) public void setIsChildOf(final List parents); }
test data:
@prefix rdfs: . @prefix ex: . ex:Parent rdfs:subClassOf ex:Person . ex:Child rdfs:subClassOf ex:Person . ex:p1 a ex:Parent ; ex:isParentOf ex:c1 ; ex:isParentOf ex:c2 ; . ex:p2 a ex:Parent ; ex:isParentOf ex:c1 ; ex:isParentOf ex:c2 ; . ex:c1 a ex:Child ; ex:isChildOf ex:p1 ; ex:isChildOf ex:p2 ; . ex:c2 a ex:Child ; ex:isChildOf ex:p1 ; ex:isChildOf ex:p2 ; .
Parent.java:
package au.edu.qimr.grafli.generated; import com.clarkparsia.empire.SupportsRdfId; import com.clarkparsia.empire.annotation.*; import java.util.*; import javax.persistence.*; @javax.persistence.Entity // Fully-qualified to distinguish from PROV-O 'Entity' @RdfsClass("ex:Parent") @Namespaces({"ex", "http://example.org/"}) public interface Parent extends SupportsRdfId{ @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.PERSIST) @RdfProperty("ex:isParentOf") public List getIsParentOf(); @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.PERSIST) public void setIsParentOf(final List children); }
Test it:
/** * em is an Empire entity manager */ groovy:000> child1 = em.find(Child, "http://example.org/c1") ===> http://example.org/c1 groovy:000> parent1 = child1.isChildOf[0] ===> http://example.org/p1 groovy:000> parent1 instanceof Parent ===> false groovy:000> parent1.class ===> class com.clarkparsia.empire.SupportsRdfId_$$_javassist_0 groovy:000> parent1.class.interfaces ===> [interface com.clarkparsia.empire.SupportsRdfId, interface com.clarkparsia.empire.EmpireGenerated, interface javassist.util.proxy.ProxyObject]
My expectation is that the proxy should also have Parent
as an interface.
The issue is that in RdfGenerator#getProxyOrDbObject, the block that adds interfaces to the proxy:
aFactory.setInterfaces(ObjectArrays.concat(theClass.getInterfaces(), EmpireGenerated.class)); if (!theClass.isInterface()) { aFactory.setSuperclass(theClass); }
should be something like this so that the property class itself is an interface:
if (!theClass.isInterface()) { aFactory.setInterfaces(ObjectArrays.concat(theClass.getInterfaces(), EmpireGenerated.class)); aFactory.setSuperclass(theClass); } else { aFactory.setInterfaces(ObjectArrays.concat(theClass, ObjectArrays.concat(theClass.getInterfaces(), EmpireGenerated.class))); }
with that change, one gets:
groovy:000> child1 = em.find(Child, "http://example.org/c1") ===> http://example.org/c1 groovy:000> parent1 = child1.isChildOf[0] ===> http://example.org/p1 groovy:000> parent1 instanceof Parent ===> true groovy:000> parent1.class ===> class au.edu.qimr.grafli.generated.Parent_$$_javassist_0 groovy:000> parent1.class.interfaces ===> [interface au.edu.qimr.grafli.generated.Parent, interface com.clarkparsia.empire.SupportsRdfId, interface com.clarkparsia.empire.EmpireGenerated, interface javassist.util.proxy.ProxyObject]
It looks like you've pretty much got the test case covered between Child
, Parent
, and the data snippet. the groovy scripts are probably the reasonable body of the test case. beyond the obvious tests that i write, many are ad hoc re-creations of issues reported on the list and there's no real pattern to them.
one day i'd like to put a bit more test util in place to make it easier.