Two Laptop Bag*
The moose likes Servlets and the fly likes Why does getParameterMap() return an *immutable* Map? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Servlets
Bookmark "Why does getParameterMap() return an *immutable* Map?" Watch "Why does getParameterMap() return an *immutable* Map?" New topic
Author

Why does getParameterMap() return an *immutable* Map?

Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
I really wanted some way of forcing parameters into the request from within a filter. I notice that ServletRequest.getParameterMap() returns an immutable object. Is the only way for me to provide a mutable object to override this method?
David O'Meara
Rancher

Joined: Mar 06, 2001
Posts: 13459

No, you need to place your data in attributes instead.
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
I've done this. It works but it does make my idea seem less effective. I was trying to parse the URI and build request parameters from the path as part of a little framework/learning experience.

I guess I'll just have to provide a wrapper which looks at what was in the request and what's been stored in attributes somewhere.

Thanks for the response
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

The parameter properties are readonly in the API for HttpServletRequest.

Originally posted by Chris Corbyn:

I guess I'll just have to provide a wrapper which looks at what was in the request and what's been stored in attributes somewhere.


That's how I would do it.
[ August 19, 2007: Message edited by: Ben Souther ]

Java API J2EE API Servlet Spec JSP Spec How to ask a question... Simple Servlet Examples jsonf
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Something just dawned on me (could be dangerous ). If I was to (*yawn*) sit down and write a class which implements HttpServletRequest:



Then within a filter if I pass my own implementation of HttpServletRequest to doFilter(), by the time my servlet's service() method gets invoked it will be using my own request object right? I mean, writing all those proxy methods sucks but it does mean I can get the result I was aiming for Unless I'm missing something?
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Originally posted by Chris Corbyn:
Unless I'm missing something?


This is called the "Wrapper Pattern" (Also Known As: the Adaptor Pattern) and is a common technique for doing what you want.
In fact the Servlet API already provides wrapper classes for you to extend so you don't have to implement all of the methods yourself.


http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequestWrapper.html
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletResponseWrapper.html
[ August 20, 2007: Message edited by: Ben Souther ]
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Perfect
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Quick question. When implementing this can I make the assumption that because getParameterMap() is part of the interface, any implementation taken will use that method to get the map it uses to store values? Basically I'm wondering if because I'll be overriding getParameterMap(), do I also need to override getParameter(), getParameterNames() and getParameterValues()? I'd still be returning a Map based on the original one but I guess you can't guarantee that every implementation will actually use the getter to access the map
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12806
    
    5
In order to avoid the immutable Map I substitute this:



Using getParameterMap and then creating your own would involve the extra object creation of the request map.

Bill
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Thanks for that So would that also mean that even without overriding getParameter() for example, the results will still come from your mutable map?
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Originally posted by Chris Corbyn:
Thanks for that So would that also mean that even without overriding getParameter() for example, the results will still come from your mutable map?


Since he's passing his method the request object, I assume Bill doesn't use this method in a wrapper class. I'm also assuming that he only plans to call this once per request.


In a wrapper class, I would create an instance variable of type HashMap, copy all of the contents from the superClasses parameter map to mine, in the constructor, and override getParameterMap so that it reads my parameterMap.

If the underlying implementation always references the map with getParameterMap instead of referencing it as an instance variable with the 'this' keyword for getParameter, getParameterNames, and getParameterValues then you should not have to implement those methods.

If you're not sure, you could test for the container you plan to support, read the source code for the container you plan to support, or override those methods yourself to be sure.
[ August 20, 2007: Message edited by: Ben Souther ]
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
The underlying implementation doesn't call my method so I'm having to override a few of the other ..Parameter..() methods.

I already sussed that I'd need to either lazy-load a map, or populate one at instantiation. So far I have this:



I really have no idea how to get the keySet() from my HashMap and turn it into an Enumeration. Well, I do have a clue if my suspicions are correct and I have to write the class for Enumeration myself. The Java API (5.0) says the only known implementing class for Enumeration is StringTokenizer.

EDIT | Bah, sod it I'll just use an anonymous class for the Enumeration...
[ August 20, 2007: Message edited by: Chris Corbyn ]
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Implementation to allow parameters to be injected. I won't be advertising that this wrapper has been used when it finally reaches my servlet it will just be type hinted as HttpServletRequest. It allows me to do what I need inside my filter though


[ August 20, 2007: Message edited by: Chris Corbyn ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12806
    
    5
Thanks for that So would that also mean that even without overriding getParameter() for example, the results will still come from your mutable map?


No - the architecture I like to use is a minimum servlet that extracts the parameters to the map, adds some user specific stuff to the map and then pass the map to a class that does the real work. Typically to a method called "doTheNextThing()"

The class that does the work does not know a thing about the servlet environment, it only knows the input map and an output stream - this means it can be tested outside the servlet environment. So much easier to debug and test that way.

Bill
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Yeah I'm a TDD'er in PHP, but I haven't delved into that in Java just yet. I do sometimes feel like I'm developing blindfolded.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61437
    
  67

Probably because you haven't read the Specs.


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Alok Kushwah
Ranch Hand

Joined: Jul 10, 2007
Posts: 31
Semantics of getParameter family methods are to expose interface to access HTTP request parameters sent by HTTP client to HTTP server. Parameters can be sent by either get HTTP method (Query string) or post HTTP method. These parameters are sent by client to communicate client's state/data with server. It doesn't make any sense if more parameters would be added by server program or edit/change the the current value of request parameter sent by client.

HttpServeletRequest represents the HTTP request sent by the end client. This HTTP request cannot be changed. If you are adding or changing any parameter you are attempting to change HTTP request sent by end client which is just like a client is asking for orange juice and overwrite it with Vodka and serve Vodka.

If I am getting it right. You want to use a resource(Servlet/JSP/Component) in server which can serve Vodka, however that resource is reading data from request parameter and your client is sending parameters and their values, which cannot be understood by this resource. Thats why you want to change/add the request parameters to make them consumable by that resource.

To solve this problem use the sendRedirect() method. Create your own URL with whatever parameters you want and redirect the request to new resource with new parameters. It will work only for get HTTP method. so it has the limitation of get HTTP method.

Actually here we want to collaborate two sever resources. However we are using HTTP clients way of communication with server. As I told you request parameters are meant for HTTP request parameters, sent by client.

The best way to collaborate is to use attributes (request/session/application), which can me managed by server program. You can add/delete/update any attribute whenever you want.


Other solution to the problem is, write a filter which reads all your request parameters and set them in request (HttpServletRequest) as attributes. Other resources in program should work with these attribute and never try to read request parameter directly. Server resources has the read and write accessibility to these attributes. Now one resource can change the client request of Orange Juice to Vodka by replacing the value of specific attribute in request. Subsequent resource will get the updated value and work accordingly.


Alok Singh Kushwah
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

"hello There",
Please check your private messages.
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Hi guys,

Just FYI, I'm not strictly adding things that the client hasn't sent. I'm doing URL rewriting (for clean URLs). Basically a URL like this:

http://mysite.com/myModule/myAction/foo/bar

Is translated to this:

http://mysite.com/?module=myModule&action=myAction&foo=bar

Mappings handled via a configuration file (I'm sure I've been over this in another thread )

(No, I'm not really planning on releasing the "framework" unless it grows into something good... I'm just a learner driver here )



EDIT | Fixed a whole bunch of typos in the <!-- comment -->
[ August 21, 2007: Message edited by: Chris Corbyn ]
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Originally posted by Chris Corbyn:
Yeah I'm a TDD'er in PHP, but I haven't delved into that in Java just yet. I do sometimes feel like I'm developing blindfolded.


TDD'r ?
Chris Corbyn
Ranch Hand

Joined: Jan 14, 2007
Posts: 114
Test-Driven Developer. Unit tester. Whatever you wanna call it I like agile development, I'm not really sure why I didn't jump in with both feet when I started out in Java. That's a lie actually, it's because I'm still figuring out the language so I'm just playing really
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Why does getParameterMap() return an *immutable* Map?