aspose file tools*
The moose likes JSP and the fly likes JSTL possibly not recognizing my class because it implents the Map interface Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » JSP
Bookmark "JSTL possibly not recognizing my class because it implents the Map interface" Watch "JSTL possibly not recognizing my class because it implents the Map interface" New topic
Author

JSTL possibly not recognizing my class because it implents the Map interface

Arjumand Bonhomme
Greenhorn

Joined: Feb 28, 2007
Posts: 6
I hope someone can shed some light on this. I'm very new to jsp/servlets/jstl/struts, java web development in general.

In one of my Struts Action classes, I was placing a java.util.Map into the request scope.

In the JSP doing the rendering for the action, I wanted to use the keySet of the map. Because .keySet() isn't actually a getter, I decided to make an inner wrapper class with the method .getKeySet(). I also wanted to be able use this same wrapper object as a normal Map. So I implemented the Map interface, delegated all the Map methods to my internal map, and created my .getKeySet() method which simply returned the keySet from the internal Map.

Pseudo-code (this was an inner class of the Action):


I had JSTL code in the JSP that looked like this:


It didn't work. I didn't error either, but it produced no output at all.
So I started debugging. Here's what I started with:


The first two lines in the last bit of code printed out:
com.my.package.some.CustomServlet$MapWrapper@3dc3943f
3

Which made sense. It got the classname in the toString, and the count was correct.
Strangely, the 3rd and 4th lines printed out nothing at and 0, respectively.

I thought this was odd and continued to attempt to debug for several hours. Eventually I commented out the Map interface on my MapWrapper class, and suddenly all of the debug lines started working!

So it appeared that JSTL couldn't access my custom methods if my wrapper class was implementing the Map interface.

I have since "solved" my problem and have basically worked around it, but I am really curious to understand why this behaved the way it did. Seems like this would really help further my understanding of JSTL because this would seem to be an odd problem. I didn't find anything on this site or Google.



Anyone have any insight?

Thanks!
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14688
    
  16

I don't know which version of JSTL you're using, but you seem to be years behind ;) Map is perfectly recognized in the forEach tag. The "var" attribute will be of type Map.Entry, so then you can use customer.key, customer.value

Looping through the keys :


[My Blog]
All roads lead to JavaRanch
Arjumand Bonhomme
Greenhorn

Joined: Feb 28, 2007
Posts: 6
Slight correction, when I said the debugging statements started working after removing the Map interface from my wrapper class, I meant the 3rd and 4th statements. The 2nd statement, "fn:length(...)" obviously stopped working because the JSTL no longer interpreted the wrapper class itself as a collection.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61413
    
  67

Originally posted by Arjumand Bonhomme:
I decided to make an inner wrapper class with the method .getKeySet()
Why do you not just iterate over the Map and extract the keys from the Map.Entry instances as Satou demonstrated? Why over-engineer the process?
[ February 28, 2007: Message edited by: Bear Bibeault ]

[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Arjumand Bonhomme
Greenhorn

Joined: Feb 28, 2007
Posts: 6
Thanks for you observations, by the end of my debugging session, I realized how I "could"/"should" do it with the Map.Entry class.

However, this still doesn't explain the behavior I saw. I can do everything that I need to with the Map.Entry style, but what I'm seeking is greater understanding. Knowing how to make something work is great, but knowing why something works (or doesn't in this case) is much much more useful and fulfilling.

I don't simply want to get my project done, I want to understand as much as possible about all the technologies I'm using. So basically this isn't a help me get my project working thread, it's more of a help me have a better understanding thread

Hope one of you can help relay the "why" behind all this.

Thanks!

Cheers!
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61413
    
  67

Originally posted by Arjumand Bonhomme:
but knowing why something works (or doesn't in this case) is much much more useful and fulfilling.


I'm 100% with you on that!

Problem is, the volunteers who answer questions here, myself included, don't always have the time to dig in as much as we'd like to.

That said, I've done something similar -- implement a Map to use with the JSTL -- many times without issue.
Arjumand Bonhomme
Greenhorn

Joined: Feb 28, 2007
Posts: 6
@Bear

Thanks! good to meet people who share the same sentiment.


That said, I've done something similar -- implement a Map to use with the JSTL -- many times without issue.


Have you ever added additional (ie non-Map) getters/setters to an object implementing Map and used those additional properties via JSTL?


I also understand what you mean about limited time. If this thread doesn't yield the answer, then I will simply have to put this on my list of things to come back and re-visit when my project is done (even though we know they are seldom ever "done").

Thanks again!
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14688
    
  16

I don't clearly understand where the problem is

The spec says :
6.1.2
If the items attribute is of type java.util.Map,
then the current item will be of type java.util.Map.Entry,

So if your request attribute is an instance of Map,
the "var" attribute will be a Map.Entry, not a MapWrapper.
No matter what you do, JSTL sees it as a Map instance, so it returns a list of Map.Entry, preventing you from calling your beloved custom methods.
The only way to do it is, as you said, to remove the implementation of a Map.

Hope one of you can help relay the "why" behind all this.

I hope it did
[ February 28, 2007: Message edited by: Satou kurinosuke ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JSTL possibly not recognizing my class because it implents the Map interface