Found the issue.
AssignmentTransaction has a one-to-many relationship named
"studentResponses". It also had a private variable:
private List studentResponses. In certain situations (described
momentarily), it appears that the field accessor class is "seeing" the
private variable instead of the relationship. When I changed the name of
the private variable, the problem disappeared. I was also able to
duplicate the issue in an entirely unrelated (and much simpler) data
map. This seems like a bug to me; seems like FieldAccessor shouldn't be
able to grab/use my private variables. :) If you want, I can open up a
jira issue and attach a really simple map and bit of code that will
illustrate the issue.
In any event, here is the situation where the invalid access occurs:
X has a to-many relationship to Y. Z also has a to-many relationship to Y.
Y has a to-many relationship named k, and also has a private List k;
declaration.
xinstance, zinstance , and yinstance are instances of X, Z and Y,
respectively, and xinstance and zinstance share a yinstance.
X loads its list of Y via xinstance.getY(). xinstance does some
processing that results in
k's initialization in the shared yinstance. zinstance now does
zinstance.getY() and attempts to perform some operation on the list
(size(), get(0), iterator(), etc... something that forces cayenne to
fault the toManyList). While processing the shared yinstance, cayenne
will choke with a ClassCastException because it will see the private
variable k (now initialized, eg, to an ArrayList) rather than the
relationship with the same name.
Apologies if the explanation is a bit opaque... again... I'll work up a
trivial data map + code example that triggers the error.
Robert
Robert Zeigler wrote:
> Didn't get back to this last night, sorry. Ok, I sat down and wrote a
> quick test to call the same code, external of tapestry.
> The code outside of tapestry didn't result in a class cast exception.
> Instead, it resulted in an ExpressionException (unable to evaluate
> assignment.name). Turns out that the assignment object doesn't have a
> "name" property (it's "title"). The thing that seems odd here is that
> the code throws no exceptions with M5 (I suspect this has to do with
> removing BeanUtils as a dependency?).
>
> Anyway... the lack of a ClassCastException says that something weird
> must be happening in tapestry or my code somewhere. I'll keep looking.
> I don't define collection setters in the DO; neither my code nor
> tapestry should be initializing the relationship, but I'll keep digging
> to see what I can find.
>
> Robert
>
>
> Andrus Adamchik wrote:
>
>>> In poking around, I saw a place where if something was
>>> transient, an ArrayList was returned... but I can't find it again at the
>>> moment; I'll look later tonight when I have a bit of time and see if I
>>> can find it again.
>>>
>> Let us know if you find those - this shouldn't happen in DataObjects.
>> The code below looks clean, so the cause is somewhere else. Is it
>> possible that Tapestry or the user code initializes the relationship
>> list on its own? Do you define collection setters in your DO's
>> (Cayenne does not by default)?
>>
>> Andrus
>>
>>
>>
>> On Jun 27, 2006, at 2:54 AM, Robert Zeigler wrote:
>>
>>
>>> Hi all,
>>>
>>> Way back when 1.2B1 was released, I reported a weird fault resolving
>>> exception. I didn't have time then to look into it further. I just tried
>>> out cayenne 1.2RC2 and am still seeing the same weird behavior (maybe
>>> I'm doing something weird. ;). I do have time now to look into it
>>> further, but am getting stuck before I can get started by a separate
>>> issue.
>>>
>>> My code:
>>> public List getTransactionsForCourse(Course course) {
>>> List ret = this.getAssignmentTransactions();
>>> ret =
>>> ExpressionFactory.matchExp("assignment.course.name",course.getName()).filterObjects(ret);
>>>
>>> List orderings = new ArrayList();
>>> orderings.add(new Ordering("assignment.name",true));
>>> orderings.add(new Ordering("scoreAsFloat",false));
>>> Ordering.orderList(ret,orderings);
>>> return ret;
>>> }
>>>
>>> assignmentTransactions is a one to many relationship.
>>>
>>> Calling said code is resulting in the following exception:
>>>
>>> *
>>> org.objectstyle.cayenne.property.AbstractCollectionProperty.ensureCollectionValueHolderSet(AbstractCollectionProperty.java:159)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.property.AbstractCollectionProperty.injectValueHolder(AbstractCollectionProperty.java:142)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.property.BaseClassDescriptor.injectValueHolders(BaseClassDescriptor.java:218)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataContext.localObject(DataContext.java:1924)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.ObjectResolver.objectFromDataRow(ObjectResolver.java:237)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.ObjectResolver.objectsFromDataRows(ObjectResolver.java:155)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.ObjectResolver.synchronizedObjectsFromDataRows(ObjectResolver.java:134)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:373)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:151)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataDomain.onQuery(DataDomain.java:766)
>>>
>>> *
>>> org.objectstyle.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:253)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataContextQueryAction.execute(DataContextQueryAction.java:90)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataContext.onQuery(DataContext.java:1422)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.DataContext.performQuery(DataContext.java:1411)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.ToManyList.resolvedObjectList(ToManyList.java:343)
>>>
>>>
>>> *
>>> org.objectstyle.cayenne.access.ToManyList.size(ToManyList.java:296)
>>> *
>>> org.objectstyle.cayenne.exp.Expression.filterObjects(Expression.java:458)
>>>
>>>
>>> * org.eledge.domain.User.getTransactionsForCourse(User.java:92)
>>> * org.eledge.domain.User.getGradebookGradedResponses(User.java:197)
>>> *
>>> org.eledge.domain.User.getGradedGradebookGradedResponses(User.java:192)
>>>
>>> *
>>> org.eledge.domain.User.getHasGradedGradebookGradedResponses(User.java:188)
>>>
>>>
>>> * sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>> *
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>
>>>
>>> *
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>
>>>
>>> * java.lang.reflect.Method.invoke(Method.java:585)
>>> * ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:491)
>>> * ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:785)
>>> * ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:61)
>>> * ognl.OgnlRuntime.callMethod(OgnlRuntime.java:819)
>>> * ognl.ASTMethod.getValueBody(ASTMethod.java:75)
>>> * ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170)
>>> * ognl.SimpleNode.getValue(SimpleNode.java:210)
>>> * ognl.ASTChain.getValueBody(ASTChain.java:109)
>>> * ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170)
>>> * ognl.SimpleNode.getValue(SimpleNode.java:210)
>>> * ognl.Ognl.getValue(Ognl.java:333)
>>> * ognl.Ognl.getValue(Ognl.java:310)
>>> *
>>> org.apache.tapestry.binding.ExpressionBinding.resolveProperty(ExpressionBinding.java:201)
>>>
>>>
>>> *
>>> org.apache.tapestry.binding.ExpressionBinding.getObject(ExpressionBinding.java:194)
>>>
>>>
>>> *
>>> org.apache.tapestry.binding.AbstractBinding.getBoolean(AbstractBinding.java:77)
>>>
>>>
>>> *
>>> org.apache.tapestry.param.BooleanParameterConnector.setParameter(BooleanParameterConnector.java:51)
>>>
>>>
>>> *
>>> org.apache.tapestry.param.ParameterManager.setParameters(ParameterManager.java:105)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.prepareForRender(AbstractComponent.java:898)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:853)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> *
>>> org.apache.tapestry.components.RenderBody.renderComponent(RenderBody.java:45)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> *
>>> org.apache.tapestry.components.RenderBody.renderComponent(RenderBody.java:45)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> * org.apache.tapestry.html.Body.renderComponent(Body.java:269)
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> *
>>> org.apache.tapestry.components.RenderBody.renderComponent(RenderBody.java:45)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> * org.apache.tapestry.html.Shell.renderComponent(Shell.java:124)
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.BaseComponent.renderComponent(BaseComponent.java:118)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.BaseComponent.renderComponent(BaseComponent.java:118)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.renderBody(AbstractComponent.java:624)
>>>
>>>
>>> * org.mb.tapestry.base.IfBean.renderComponent(IfBean.java:83)
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.BaseComponent.renderComponent(BaseComponent.java:118)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> *
>>> org.apache.tapestry.BaseComponent.renderComponent(BaseComponent.java:118)
>>>
>>>
>>> *
>>> org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:857)
>>>
>>> * org.apache.tapestry.AbstractPage.renderPage(AbstractPage.java:300)
>>> *
>>> org.apache.tapestry.engine.RequestCycle.renderPage(RequestCycle.java:368)
>>>
>>>
>>> *
>>> org.apache.tapestry.engine.AbstractEngine.renderResponse(AbstractEngine.java:749)
>>>
>>>
>>> *
>>> org.apache.tapestry.engine.PageService.service(PageService.java:77)
>>> *
>>> org.apache.tapestry.engine.AbstractEngine.service(AbstractEngine.java:889)
>>>
>>>
>>> * org.eledge.EledgeEngine.service(EledgeEngine.java:60)
>>> *
>>> org.apache.tapestry.ApplicationServlet.doService(ApplicationServlet.java:198)
>>>
>>>
>>> *
>>> org.apache.tapestry.ApplicationServlet.doGet(ApplicationServlet.java:159)
>>>
>>>
>>> * javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
>>> * javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
>>> *
>>> org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:428)
>>>
>>> *
>>> org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:830)
>>>
>>>
>>> *
>>> org.eledge.OldEledgePagesFilter.doFilter(OldEledgePagesFilter.java:64)
>>>
>>> *
>>> org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
>>>
>>>
>>> *
>>> org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(WebApplicationHandler.java:471)
>>>
>>>
>>> *
>>> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:568)
>>>
>>> * org.mortbay.http.HttpContext.handle(HttpContext.java:1530)
>>> *
>>> org.mortbay.jetty.servlet.WebApplicationContext.handle(WebApplicationContext.java:633)
>>>
>>>
>>> * org.mortbay.http.HttpContext.handle(HttpContext.java:1482)
>>> * org.mortbay.http.HttpServer.service(HttpServer.java:909)
>>> * org.mortbay.http.HttpConnection.service(HttpConnection.java:816)
>>> *
>>> org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:982)
>>> * org.mortbay.http.HttpConnection.handle(HttpConnection.java:833)
>>> *
>>> org.mortbay.http.SocketListener.handleConnection(SocketListener.java:244)
>>>
>>>
>>> * org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
>>> * org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
>>>
>>>
>>> This is a tapestry (3.0.3) webapp, running with the JettyLauncher. I've
>>> done a clean recompile, but no good. I dug into the code, and it looks
>>> like ensureCollectionValueHolderSet is trying to cast an ArrayList as a
>>> ValueHolder. In poking around, I saw a place where if something was
>>> transient, an ArrayList was returned... but I can't find it again at the
>>> moment; I'll look later tonight when I have a bit of time and see if I
>>> can find it again. Anyway... thoughts? Cayenne bug? Something I've
>>> screwed up?
>>>
>>> Robert
>>>
>>>
>
>
This archive was generated by hypermail 2.0.0 : Wed Jun 28 2006 - 09:08:16 EDT