I'm using tapestry + hibernate.

        I have a class called employee that has a field in it called
"manager".

        I have a tapestry control I home brewed which allows users to pick
an arbitrary set of columns to display from a list of arbitrary objects. You
just feed it a collection and a list of field names and out comes a
generated grid. This is where I'm using my own reflection code.

        I also have a much more traditional tapestry edit form which I use
to edit employees. Upon this form I have an IPropertySelection that looks
like:

            <td><span jwcid="@PropertySelection"
model="ognl:getLookupModel('core.User', 'id', 'fullName')"
value="ognl:object.assignedTo"/><td>                      


        My code then goes out and builds the property selection model by
querying the core.User repository, using the id field as the value, the
fullName field as the label, and the object itself as the object.

        However ...

        The form displays an employee record. So ognl enhances the employee
record upon that form e.g. if I'm displaying "Bob Thompson's" employee
record, then that employee record will get enhanced. Hibernate, however, is
so aggressive about first level caching that when it gets a list of 100
users to fill the propertyselectionmodel, it gets 99 normal users and Bob
Thompson's "enhanced" user.

        If I look at the list in my eclipse debugger, sure enough, 99 normal
users, and 1 [EMAIL PROTECTED]

        My property selection model code correctly plucks values out of
normal core.users under all circumstances.
        
        My property selection model code, however, can't pluck a value out
of a *final* property of a core.User after ognl has had its way with it. If
I make the property in question non final, no problem. So I have my system
working again, but in the previous system as soon as I "displayed" an
employee and he went into L1 cache enhanced, he dropped off the combo box
until I restarted tomcat because his ID wouldn't be resolvable anymore.

        FWIW here's the code that's building the property selection model.

public static SelectModel getLookupModel(String objectName,
                        String valueField, String labelField, String[]
order) {
                SelectModel m = new SelectModel();
                Criteria c =
HibHelper.getSession().createCriteria(objectName);
                c.setCacheable(false);
                if (order != null) {
                        for (int x = 0; x < order.length; x++) {
                                String col = (String) order[x];
                                c.addOrder(Order.asc(col));
                        }
                }
                List l = c.list();
                Wrapper w = null;
                for (int x = 0; x < l.size(); x++) {
                        DynaObject o = (DynaObject) l.get(x);
                        if (w == null)
                                w = new Wrapper(o);
                        else
                                w.setWrapped(o);
                        String value = w.getField(valueField);
                        if (value == null) {
                                // some emergency code to work around ognl 
                                if (o instanceof DynaObject &&
valueField.equals("id")) {
                                        String dingo =
w.getField("firstName");
                                        // first name is non final works
fine
                                        Wrapper temp = new Wrapper(o);

                                        value = temp.getField("id");
                                        // id won't work because
DynaObject.getId() is final
                                }
                        }
                        String label = w.getField(labelField);
                        SelectOption s = new SelectOption();
                        s.setLabel(label);
                        s.setValue(value);
                        s.setObject(o);
                        m.fList.add(s);
                }
                return m;
        }


-----Original Message-----
From: Erik Hatcher [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, April 27, 2005 3:21 AM
To: Tapestry users
Subject: Re: OGNL Voodoo

Could you put this scenario concretely in Tapestry terms?   Are you 
speaking of a page or component here?  As far as I know, OGNL doesn't 
enhance objects, but Tapestry does enhance components and pages that 
need to have getters/setters filled in.

OGNL does its fair share of reflection voodoo, though, so it would seem 
unnecessary for you to use your bag of tricks in conjunction with OGNL 
expressions.

I'm interested in seeing a concrete Tapestry-specific example of where 
you are encountering the issue.

        Erik


On Apr 27, 2005, at 12:42 AM, Patrick Casey wrote:

>
>
>             I ran into a situation recently that I managed to resolve 
> via
> some programming voodoo. As a rule, I'm uncomfortable when voodoo 
> solutions
> because I'm not sure I'll be able to resolve the situation if it crops 
> up
> again. So I was hoping someone here with a bit more experience with 
> OGNL
> could help me out.
>
>
>
>             I have a class, Mamal which has a final method getId().
>
>             I have a subclass, Cat which has a (not final) method 
> getName()
>
>
>
>             For reasons too obscure to explain, I'm using my own 
> reflection
> virtualizer to access these fields (what follows oversimplifies, but 
> you get
> the idea. There's actually a lot of cache code and whatnot in place to 
> speed
> up method location).
>
>
>
>             Method[] me = Cat.class.getMethods();
>
>             For (int x =0; x< me.length; x++) {
>
>                         Method thisMethod = me[x];
>
>                         if (therightone)
>
>                                     thisMethod.invoke(targetObject, 
> null);
>
>             }
>
>
>
>             Works like a champ and it uses some reflection code I've 
> had in
> my bag of tricks for years.
>
>
>
>             The problem arises when ognl decides it wants to "enhance" 
> a
> class which it appears to do by generating a synthetic wrapper class 
> and
> proxying all the method calls (this based on two minutes of looking at 
> the
> debugger not reading the doc so I might be wrong).
>
>
>
>             Before ognl "enhances" a cat,
>
>
>
>             Wrapper.get("name", cat)  yields "fluffy"
>
>             Wrapper.get("id", cat) yields 50
>
>
>
>
>
>             Once ognl "enhances" a cat,
>
>
>
>             Wrapper.get("name", cat)  yields "fluffy"
>
>             Wrapper.get("id", cat) yields null
>
>
>
>             Here's the voodoo: if I take mammal.getId() and change it 
> from
> public final to just plain public,
>
>
>
>             Once ognl "enhances" a cat (with a non final getId()),
>
>
>
>             Wrapper.get("name", cat)  yields "fluffy"
>
>             Wrapper.get("id", cat) yields 50 <--- works now??!?
>
>
>
>             Does anyone have any insight into what's going on here? Why
> should finality of the method matter?
>
>
>
>             --- Pat
>
>
>
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to