Somebody wrote:
> > I am using HTML to communicate to a servlet, and I need to be able to
> > go back and forth between HTML and the servlet to progress through this
> > user interactive application. [...]
> > That's where I am stuck. In my doGet(HttpServletRequest,
> > HttpServletResponse) function within the servlet I try to see the
> > select list item using:
> >
> > String values[] = req.getParameterValues("configtable");
> >
> > I get the error:
> >
> > 500 Internal Server Error
> > LoginServlet:
> > java.lang.NullPointerException
Andy Bailey responded:
> Ok if you want the servlet to handle multiple forms you should use a
> session object to store a counter in it which 'reminds' your service
> method what it should do next. The problem is that you are trying
> to retrieve the value of the configtable parameter when it may be
> that none exists (hence the error).
> [...] Another solution is to send a hidden input field in each form,
> call it "stage" and grab the value thus...
> [...]
> I have another, more complicated, scheme which involves a Hashtable
> and a method which checks the command order because the http
> information I am processing must be done in a certain order, has to
> be hacker safe and involves database transactions.
In general, you have to check that parameters exist before you
use them. I find this generally annoying, but then again I'm spoiled
by the sloppy Perl world :-). Likewise, you have to check for cookies
before you use them. I currently have three convenience methods that
I use in my servlets, checkParameter, checkCookie, and getCookie. I've
included the listing for checkParameter below.
In general, if you have multistage servlets, you have to:
1) break the stages up so each one only gets invoked from the
appropriate form generated by the preceding stage servlet, or
2) maintain some continuity between requests, or
3) make each stage be smart enough to make sure the necessary values
are present, and react appropriately (the best reaction I can think of
is to send the user back to the appropriate stage).
There are only a few ways to maintain continuity (assuming you're
working with browsers and not a specialized client applet or
application). This sucks, but that's the state of the web. You can
either pass a value back and forth as a hidden parameter, pass a value
back and forth as a cookie (fortunately by now this is feasible) or
pass a value back and forth by having the servlet embed an ID code of
some sort in the URL it generates for the next request.
Depending on the amount of information you want pass, you can
either pass the information back and forth, or use the above methods
to pass an ID string of some sort, and keep the information in the
server and retrieve it via the ID string. This can be a bit of a pain
in the ass to build (since you have to keep track of bits of data,
expire them after a certain time, etc) but is generally more useful,
since you don't have to worry about data size or security issues.
I understand, though I haven't used it yet, that various servlet
engines provide generalized services for doing the latter
transparently. Under Netscape Enterprise Server's server-side
javascript, they call these "server-side cookies", I think. From the
application they look just like cookies, but the actual data isn't
passed back and forth between server and client. It's kept on the
server and the server uses a single cookie with an ID string to
uniquely identify the client and respond to the livewire application
or java servlet as if they were cookies.
An easy alternative is to just break up the form handling into
separate servlets, and have the page generated by each servlet point
to the next servlet. Effectively, all you're doing is moving the logic
of where the user is and hence which page to go to next out of the
servlet code and hardcoding it into the HTML page. Quick and easy,
but not necessarily good. This doesn't stop the user from directly
typing in the wrong servlet name, however, so you still have to check
the parameters and make sure they're all present. And it's a pain in
the ass to change.
Once you have continuity, you can just keep track of where the
user is and have your servlet handle the form submission
appropriately. This seems to be the standard way to handle it.
Again, you still have to check the parameters to make sure they're
present and contain some valid data.
An approach I've used in the past, which requires much smarter
servlets, is to have the servlet know all of the parameters and which
forms are used to enter them, and then by examining the request it can
determine what page the user needs to see next. Not easy, but far
more secure and flexible.
The two convenience "check" methods I mentioned above take a
request object and a string naming the parameter or cookie, and return
boolean true if the parameter or cookie is defined and is non-blank.
The reason I check for non-blank (after trimming the string to remove
excess whitespace) is because HTTP will quite happily pass a blank
string as a parameter value. I can't think of too many situations
where I would have the servlet react differently to a missing
parameter vs. a blank-value parameter.
The getCookie method takes a request and a string naming a
cookie, and loops through the cookie array and finds the requested
cookie. It returns null, just like getParameter returns null, if you
request a cookie that isn't there. Since you never call it without
calling checkCookie first, this shouldn't be a problem.
Last year I had somebody take me to task for having a method
return a null value as a way of responding to an error. Since the
method was encapsulating a hashtable, which returns null if you ask
for a value that isn't there, I thought that was an acceptable
response. Of course, said individual was unhappy because my null
value generated a runtime exception in his code, but what's the
accepted (i.e. "conventional") approach to this?
boolean checkParameter(HttpServletRequest request, String parameterName) {
// returns true if the parameter is present and non-blank
// Ideally I should add a version of this method that takes a
// regexp argument to compare the parameter value against.
String parameterValue = request.getParameter(parameterName) ;
if (parameterValue == null) {
log("Requested parameter " + parameterName + " is null.") ;
return(false) ;
}
else if (parameterValue.trim().equals("")) {
log("Requested parameter \"" + parameterName + "\" is blank.") ;
return(false) ;
}
else {
// This log statement is only used in testing.
// log("Requested parameter \""
// + parameterName
// + "\" is \""
// + parameterValue + "\"") ;
return(true) ;
}
}
A similar problem I was dwelling upon recently is loading in
configuration values (from the command line, environment variables, a
.rc file in the current directory, in the user's home directory, in
the application's installed directory) and gracefully performing some
error checking (type validity, optional/required values) and
responding. I'd like to make a generally useful class or set of
classes for this; parts of the solution to this could be applicable
to examining the parameters submitted from an HTTP request.
Steven J. Owens
[EMAIL PROTECTED]
[EMAIL PROTECTED]
___________________________________________________________________________
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff SERVLET-INTEREST".
Archives: http://archives.java.sun.com/archives/servlet-interest.html
Resources: http://java.sun.com/products/servlet/external-resources.html
LISTSERV Help: http://www.lsoft.com/manuals/user/user.html