see my comments below...

| chris wilson || web dev ||| [EMAIL PROTECTED] || | www.wondergeek.com |
|

> -----Original Message-----
> From: Martin Cooper [mailto:[EMAIL PROTECTED]]
> Sent: Wednesday, January 10, 2001 11:44 PM
> To: [EMAIL PROTECTED]
> Subject: Re: Can I use a Map.Entry as a bean?
>
>
> I've done some extensive digging around on this (because I wanted to use
> inner classes with the Digester as well), and found out what's going on.
> It's not an inner class thing per se, because I do have inner classes
> working with the Digester now.
>
> First, getValue() is public in both Map.Entry and TreeMap.Entry, so this
> wasn't affecting things. I assume getKey() is the same, but I haven't
> checked.
>
> What does matter is that Map.Entry is a public inner class, but
> TreeMap.Entry has only package access. Struts uses bean.getClass() to get
> the class, and looks up the getter method on that. Not surprisingly,
> getClass() returns TreeMap.Entry, so that when the getter is found, it is
> actually the TreeMap.Entry getter, which is not accessible from
> outside the
> package.

wow!  thanks for digging so deep.  it's nice to know what's actually going
on.

> What this tells us (I think) is that the PropertyUtils introspection code
> won't work on a bean whose concrete class is not public, even if it is
> derived from, and almost exclusively manipulated as, a public interface.
>
> One interesting point that I discovered on my trails through the code is
> that the "type" attribute on the logic:iterate tag does not appear to be
> used at all. It certainly isn't taken into account when
> bean:write is doing
> its thing. This actually makes sense when you think about it - the
> logic:iterate tag just puts a bean into the requested scope, and
> it's up to
> the retriever (in this case, bean:write) to decide what type it is.

why is the type attribute even in the iterate tag then?  just curious...

> OK, so much for the problem. What can we do about it? Well, in theory, we
> could add a "type" attribute to bean:write, and then have that passed
> through to where the introspection happens. The problems I see
> with this are
> that bean:write is undoubtedly not the only tag that would have to be
> modified to handle this, and that a pile of code would have to change so
> that the type can wend its way down to the appropriate introspection code.
>
> The only other alternative I can think of is a bit hairy. That would be to
> have the introspection code first figure out whether a method is
> accessible
> (by looking at the modifiers of the method and its class). If the
> method is
> not accessible, then the code would work its way down through the base
> classes and implemented interfaces to look for an accessible version, and
> use the corresponding class to call the method. Like I said, a bit hairy.
>
> On the other hand, we could just do nothing. I would assume that
> this is not
> something a lot of people will hit, and that Chris is just one of those
> unlucky folks. :-}

true... however, why is there even the ability to work with maps in this way
with the iterate tag then?  1) simply so i can use scriptlets to get at the
values of the entries?  if i'm going to use scriptlets, i might as well just
use scriptlets to iterate as well.  2) or in the hope that someone will
implement a map that doesn't use a protected map.entry class?  the only
reason i can see to fix it, is so that the working of the struts iterate tag
is consistent.  if i can't get at the stuff with tags, it's confusing to
iterate it with tags (in the case of maps).

i've since worked around this by basically stuffing my own 'entry-like'
class in a set which works great, except that it doesn't work like a map
when querying, only with iterating.  maps are handy for building select
lists and such and then getting the indexed value in a servlet somewhere
instead of having to iterate through an entire set.

i actually agree that it's probably not a big enough deal to fix or contend
with, i'm just a consistency freak :)

thanks for the help and info!

struts rocks,
chris

> --
> Martin Cooper
> Tumbleweed Communications
>
> ----- Original Message -----
> From: "Craig R. McClanahan" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Tuesday, January 09, 2001 12:32 PM
> Subject: Re: Can I use a Map.Entry as a bean?
>
>
> > Chris Wilson wrote:
> >
> > > here's a simple example  of what i'm talking about.  would one of your
> > > wizards please try this servlet and jsp page to see what i'm talking
> about?
> > > thanks very much!
> > >
> >
> > I did some playing with this as well.  It seems to be a Java
> API issue --
> > Map.Entry is an inner class, so apparently Java reflection APIs are not
> allowed
> > to call it's methods dynamically (the way that the Struts tags
> need to in
> order
> > to be generalized :-(.
> >
> > As you noted, using mapEntry.getKey() and mapEntry.getValue() directly
> seems to
> > work, so we could cheat if need be -- but I would hate to start special
> casing
> > the code in <bean:write> (and all the other tags that can access
> properties) for
> > wierd situations like this ...
> >
> > Craig
> >
> >
> > >
> > > i tried this on tomcat 3.2.1, jdk 1.3, win 2000
> > >
> > > ###### Begin TestServlet.java ######
> > >
> > > import javax.servlet.http.HttpServlet;
> > > import javax.servlet.http.HttpServletRequest;
> > > import javax.servlet.http.HttpServletResponse;
> > > import javax.servlet.ServletException;
> > > import java.util.HashMap;
> > > import java.io.IOException;
> > >
> > > public class TestServlet extends HttpServlet {
> > >    public void doGet(HttpServletRequest req, HttpServletResponse res)
> > >    throws ServletException, IOException {
> > >       HashMap map = new HashMap();
> > >       map.put("test", "hope this works");
> > >       map.put("foo", "bar");
> > >       req.setAttribute("map", map);
> > >
> getServletContext().getRequestDispatcher("/display.jsp").forward(
> > >          req, res);
> > >    }
> > > }
> > >
> > > ###### End TestServlet.java ######
> > >
> > > ###### Start display.jsp ######
> > >
> > > <%@ taglib uri="struts-logic.tld" prefix="logic" %>
> > > <%@ taglib uri="struts-bean.tld" prefix="bean" %>
> > > <html>
> > > <head>
> > >         <title>display.jsp</title>
> > > </head>
> > >
> > > <body>
> > > <logic:iterate name="map" id="entry" scope="request"
> > > type="java.util.Map.Entry">
> > > <!-- i get an IllegalAccessException when running the following two
> > > lines -->
> > > <!-- delete the following two lines to elimate the
> > > IllegalAccessException -->
> > > <bean:write name="entry" property="key" scope="page" /> ->
> > > <bean:write name="entry" property="value" scope="page" /><br>
> > > <!-- why dosen't this work? -->
> > > <!-- end delete -->
> > >
> > > <!-- these two lines work!  they don't throw an exception -->
> > > <!-- they are functionally equivelent to the above two lines
> right? -->
> > > <%= ((java.util.Map.Entry)pageContext.getAttribute("entry")).getKey()
> %> ->
> > > <%=
> ((java.util.Map.Entry)pageContext.getAttribute("entry")).getValue()
> > > %><br>
> > > </logic:iterate>
> > > </body>
> > > </html>
> > >
> > > ###### End display.jsp ######
> > >
> > > | chris wilson || web dev ||| [EMAIL PROTECTED] || |
> www.wondergeek.com |
> > > |
> > >
> > > > -----Original Message-----
> > > > From: Chris Wilson [mailto:[EMAIL PROTECTED]]
> > > > Sent: Thursday, January 04, 2001 10:46 AM
> > > > To: [EMAIL PROTECTED]
> > > > Subject: RE: Can I use a Map.Entry as a bean?
> > > >
> > > >
> > > > yes,
> > > >
> > > > i've included both taglib defs...  in fact, the tags are working
> great.
> > > > it's only the write tag that's having a problem, and only when i
> > > > try to get
> > > > a property on a Map.Entry
> > > >
> > > > <bean:write name="subjectEntry" property="value" scope="page" /> //
> this
> > > > fails with an IllegalAccessException...
> > > >
> > > > ((java.util.Map.Entry)pageContext.getAttribute("subjectEntry)).get
> > > > Value() //
> > > > this works!
> > > >
> > > > if i use my own bean in the write tag, everything is dandy.
>  it's just
> the
> > > > dang Map.Entry!
> > > >
> > > > | chris wilson || web dev ||| [EMAIL PROTECTED] || |
> > > > www.wondergeek.com |
> > > > |
> > > >
> > > > > -----Original Message-----
> > > > > From: Ted Husted [mailto:[EMAIL PROTECTED]]
> > > > > Sent: Thursday, January 04, 2001 10:11 AM
> > > > > To: Struts List
> > > > > Subject: Re: Can I use a Map.Entry as a bean?
> > > > >
> > > > >
> > > > > So, you've included the Struts bean tag library along with logic,
> yes?
> > > > >
> > > > > <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
> > > > > <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
> > > > >
> > > > > You can get some weird and misleading error messages if you omit a
> > > > > taglibs you're using.
> > > > >
> > > > > The inner class shouldn't cause a problem, since the
> iterate tag is
> > > > > designed for that (an attribute or property of an attribute).
> > > > >
> > > > > For more troubleshooting, did you try setting the inner class as a
> > > > > standalone page attribute, to see if that works too?
> > > > >
> > > > > *********** REPLY SEPARATOR  ***********
> > > > >
> > > > > On 1/4/2001 at 9:17 AM Chris Wilson wrote:
> > > > >
> > > > > hello,
> > > > >
> > > > > sorry to post this similar message again, but i'm really
> stumped...
> > > > >
> > > > > i've run into a problem however trying to use the iterate
> tag with a
> > > > > TreeMap
> > > > > and the write tag...  here's a snippet of my code:
> > > > >
> > > > > <logic:iterate name="subjects" id="subjectEntry" scope="request"
> > > > > type="java.util.Map.Entry">
> > > > > // subjects is a TreeMap in the request object... no problem there
> > > > > // it's my understanding that when the iterate tag is used with a
> map,
> > > > > the
> > > > > // iterator is on the Set of Map.Entries returned by
> Map.entitySet(),
> > > > > // therefore the object exposed as subjectEntry should be a
> > > > > java.util.Map.Entry
> > > > >
> > > > > <bean:write name="subjectEntry" property="value" scope="page" />
> > > > > // this is where i get an IllegalAccessException attempting to
> access
> > > > > the
> > > > > //property value of subjectEntry, even though there is a
> getValue()
> > > > > method
> > > > > in the
> > > > > //api...
> > > > >
> > > > > </logic:iterate>
> > > > >
> > > > > just for fun, i replaced the write tag above with the following
> > > > > scriptlet
> > > > > which i believe is logically equivalent:
> > > > > <%=
> > > > >
> ((java.util.Map.Entry)pageContext.getAttribute("subjectEntry)).getValue(
> > > > > )
> > > > > %>
> > > > >
> > > > > and that works!  of course, i could simply use this
> scriptlet and my
> > > > > problem
> > > > > would be solved, but i'd like to use only taglibs if
> possible and it
> > > > > seems
> > > > > to me that the <bean:write> tag should do the same thing...
> > > > >
> > > > > will <bean:write> only work on "bean-like" objects that
> are public?
> in
> > > > > this
> > > > > case the object implementing the Map.Entry interface is an inner
> class
> > > > > in
> > > > > TreeMap.  is that causing the problem?
> > > > >
> > > > > what am i missing?  thanks for any help!
> > > > >
> > > > > cheerio,
> > > > > chris
> > > > >
> > > > > | chris wilson || web dev ||| [EMAIL PROTECTED] || |
> > > > > www.wondergeek.com |
> > > > > |
> > > > >
> > > > >
> > > > >
> > > > >
> > > >
> > > >
> >
>
>
>

Reply via email to