commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject Re: [Digester] Method call order.
Date Fri, 03 Jun 2005 06:28:04 GMT

Hi Simon,

      I might have missed your point, but how does this explain the
different call order for those with "paramtypes" declared versus those
without "paramtypes"? I'm guessing here that if paramtypes are not
declared, it gets triggered immediately (WITHOUT being pushed into the
stack) ..but when paramtypes are declared it gets pushed into the stack
thus LIFO ???


                      Simon Kitching                                                     
                      <skitching@apach         To:      Jakarta Commons Users List <>
            >                   cc:                                    
                                               Subject: Re: [Digester] Method call order.
                      03/06/2005 02:07                                                   
                      Please respond                                                     
                      to "Jakarta                                                        
                      Commons Users                                                      

On Fri, 2005-06-03 at 13:17 +0800, wrote:
> The XML I'm trying to parse:
> <Common>
>       <attributes1 attr="common_attributes1"/>
>       <attributes2 attr2="common_attributes2"/>
>       <Type1>
>             <attributes attr="subclass1_attributes"/>
>       </Type1>
>       <Type2>
>             <attributes attr="subclass2_attributes"/>
>       </Type2>
> </Common>
> In this scenario, I'm trying to generate an appropriate object depending
> whether the tag <Type1> or <Type2> appears but both must have common
> attributes "common_attributes1" & "common_attributes2" set into them.
> this is my first time using Digester, I'm unaware of a way to write a
> factory at <Common> to peek deeper to get the appropriate Type class to
> load.

You can't write a factory to do that. The object must be created when
the start tag is encountered, in order for it to be available to store
attribute info on when that is found. But digester is based on SAX, so
has *no* ability to "look ahead" in the stream of data.

Some variant of your CommonLoader is the way to go I expect - though as
you have found out it isn't easy...

> So I introduced a "CommonLoader" intermediate class and wrote the
> rules as follows...
> <digester-rules>
>       <pattern value="Common">
>             <object-create-rule classname="CommonLoader"/>
>             <call-method-rule methodname="setCommonAttributes1"
> paramcount="1" paramtypes="java.lang.Boolean"/>
>             <call-param-rule pattern="attributes1" attrname="attr1"
> paramnumber="0"/>
>             <call-method-rule methodname="setCommonAttributes2"
> paramcount="1" />
>             <call-param-rule pattern="attributes2" attrname="attr2"
> paramnumber="0"/>
>             <pattern value="Type1">
>                   <object-create-rule classname="Type1"/>
>                   <set-next-rule methodname="setType1"/>
>                   <call-method-rule methodname="setType1Attribute"
> paramcount="1" paramtypes="java.lang.Boolean"/>
>                   <call-param-rule pattern="attributes" attrname="attr"
> paramnumber="0"/>
>             </pattern>
>             <pattern value="Type2">
>                   <object-create-rule classname="Type2"/>
>                   <set-next-rule methodname="setType2"/>
>                   <call-method-rule methodname="setType1Attribute"
> paramcount="1" paramtypes="java.lang.Boolean"/>
>                   <call-param-rule pattern="attributes" attrname="attr"
> paramnumber="0"/>
>             </pattern>
>       </pattern>
> </digester-rules>
> CommonLoader will have the method setType1() and setType2() and these
> methods accepts the object created (either Type1 or Type2) and then sets
> the common attributes obtained from within the <Common> tag to these Type
> objects. I require that the method setType1() and setType2() be called
> to ensure all the common attributes are loaded into CommonLoader before
> proceeds to set them into the appropriate Type object. However the order
> execution I got is as follows:
> 1.    setCommonAttributes2.
> 2.    setType1.
> 3.    setCommonAttributes1.
> Because setType1 as seen above is called before setCommonAttributes1,
> common_attribute1 never gets set into the object Type1.
> I've got a few workarounds in mind that would work, but before I proceed,
> need to understand as to why setCommonAttributes2() gets called based on
> the proper order while setCommonAttributes1() gets called last? Why is
> order not as follows?
> 1.    setType1
> 2.    setCommonAttributes2
> 3.    setCommonAttributes1
> However if I were to remove "paramtypes=java.lang.Boolean" and pass it in
> as a String then the order will be as follows:
> 1.    setCommonAttributes1
> 2.    setCommonAttributes2
> 3.    setType1
> I hope my explanation is clear and the experts out there is able to help.

Adding multiple CallMethodRule rules with the same pattern is a bad
idea. It's a design flaw in Digester, and can result in some very
unexpected behaviour. The fundamental cause is that there is just one
"parameter stack" in digester, and CallParamRule objects always operate
on the "parameter-info" structure on the top of the stack.

In your case it's not necessary to have CallMethodRule rules with the
same pattern. I suggest adding the CallMethodRule rules with the same
pattern that triggers their sole parameter:

<pattern value="Common">
  <object-create-rule ...>

  <pattern value="attributes1">
    <call-method-rule name="setCommonAttributes1" paramcount="1" .../>
    <call-param-rule attrname="attr" paramnumber="0"/>

  <pattern value="attributes2">
    <call-method-rule name="setCommonAttributes2" paramcount="1" .../>
    <call-param-rule attrname="attr" paramnumber="0"/>

  <pattern value="Type1">



To unsubscribe, e-mail:
For additional commands, e-mail:

Unencrypted electronic mail is not secure and may not be authentic.
If you have any doubts as to the contents please telephone to confirm.

This electronic transmission including any attachments is intended only
for those to whom it is addressed. It may contain copyright material or
information that is confidential, privileged or exempt from disclosure by law.
Any claim to privilege is not waived or lost by reason of mistaken transmission
of this information. If you are not the intended recipient you must not
distribute or copy this transmission and should please notify the sender.
Your costs for doing this will be reimbursed by the sender.

We do not accept liability in connection with computer virus, data corruption,
delay, interruption, unauthorised access or unauthorised amendment.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message