commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Barney Barumba (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (DIGESTER-180) Digester calls invalid method when using proxy ObjectCreate rule
Date Wed, 24 Dec 2014 11:42:17 GMT

    [ https://issues.apache.org/jira/browse/DIGESTER-180?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14257205#comment-14257205
] 

Barney Barumba edited comment on DIGESTER-180 at 12/24/14 11:42 AM:
--------------------------------------------------------------------

I think the problem is in the {{ObjectCreateRule.intercept}} method:

{code}
public Object intercept( Object obj, Method method, Object[] args, MethodProxy proxy )
    throws Throwable
{
    boolean hasDelegate = delegate != null;
    if ( !hasDelegate )
    {
        invocations.add( new RecordedInvocation( method, args ) );
    }
    if ( hasDelegate )
    {
        return proxy.invoke( delegate, args );
    }
    return proxy.invokeSuper( obj, args );
}
{code}

This records *all* intercepted method calls on the object being constructed, whereas it should
probably only record the method calls invoked directly from the digester, and not those called
internally within the object.

So when building the proxy object, the digester calls {{addWidget}} which in turn calls {{addWidgetInternal}},
but both of these method invocations are intercepted and recorded. So later in {{ObjectCreateRule.establishDelegate}}
when all invocations are played back, both of these calls are repeated, when only the first
should be.

Not sure of the best way to fix this, but hope it helps.


was (Author: baarney):
Just found something else which may be relevant... as above, if {{addWidgetIternal}} is {{public}}
I see it get called twice, and if it is {{private}} then it is only called once and everything
is ok. However, if I make it {{protected}} I see the following exception:

{code}
04:00:55 ERROR org.apache.commons.digester3.Digester: End event threw exception
java.lang.IllegalAccessException: Class org.apache.commons.digester3.ObjectCreateRule$DeferredConstructionCallback
can not access a member of class Box with modifiers "protected"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:109)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253)
	at java.lang.reflect.Method.invoke(Method.java:599)
	at org.apache.commons.digester3.ObjectCreateRule$DeferredConstructionCallback.establishDelegate(ObjectCreateRule.java:83)
	at org.apache.commons.digester3.ObjectCreateRule$ProxyManager.finalize(ObjectCreateRule.java:184)
	at org.apache.commons.digester3.ObjectCreateRule.end(ObjectCreateRule.java:388)
	at org.apache.commons.digester3.Digester.endElement(Digester.java:1128)
{code}

> Digester calls invalid method when using proxy ObjectCreate rule
> ----------------------------------------------------------------
>
>                 Key: DIGESTER-180
>                 URL: https://issues.apache.org/jira/browse/DIGESTER-180
>             Project: Commons Digester
>          Issue Type: Bug
>    Affects Versions: 3.2
>         Environment: Linux x_86_64, JDK 1.7.0_65
>            Reporter: Barney Barumba
>         Attachments: Box.java
>
>
> Hi, I've encountered some strange behaviour when using the new proxy object create: the
digester appears to call a method that is never mentioned in the digester rules! I've simplified
it as much as I can to the following (full, runnable code attached):
> A simple box of widgets:
> {code}
>   private final String id;
>   private final Set<String> widgetIds = new HashSet<>();
>   
>   public Box(String id) {
>     System.out.println("Box: id=" + id);
>     this.id = id;
>   }
>   
>   public void addWidget(String widgetId) {
>     System.out.println("addWidget: id=" + id + ", wid=" + widgetId);
>     addWidgetInternal(widgetId);
>   }
>   
>   public void addWidgetInternal(String widgetId) {
>     System.out.println("addWidgetInternal: id=" + id + ", wid=" + widgetId);
>     if (widgetIds.contains(widgetId)) {
>       System.err.println("*** box already contains widget " + widgetId);
>     } else {
>       widgetIds.add(widgetId);
>     }
>   }
> {code}
> The source XML is fairly straightforward:
> {code}
> <box id='b01'>
>   <widget wid='w01'>Widget 1</widget>
> </box>
> {code}
> as are the rules:
> {code}
>   forPattern("box")
>       .createObject().ofType(Box.class).usingConstructor(String.class)
>       .usingDefaultConstructorArguments("")
>       .then().callParam().fromAttribute("id").ofIndex(0);
>     
>   forPattern("box/widget")
>       .callMethod("addWidget")
>       .withParamCount(1)
>       .then().callParam().fromAttribute("wid").ofIndex(0);
> {code}
> The key point here is that the rules only ever invoke {{addWidget}}, and this calls {{addWidgetInternal}}.
However, when I run this, {{addWidgetInternal}} gets called twice, the second time directly
from the digester, and I get the following output:
> {code}
> Box: id=
> addWidget: id=, wid=w01
> addWidgetInternal: id=, wid=w01
> Box: id=b01
> addWidget: id=b01, wid=w01
> addWidgetInternal: id=b01, wid=w01
> addWidgetInternal: id=b01, wid=w01
> *** box already contains widget w01
> {code}
> I'm guessing that this is connected with the proxy code because I can change any number
of things to make it work:
> * Make {{addWidgetInternal}} private;
> * Call {{addWidgetInternal}} directly from the digester rules.
> * Use a custom object create rule instead (see attached code).



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message