GN: Did anyone who did the Servlets class have a problem with the CastMap getTrimmed String()? My servlet is just blowing down if I don't specify a value for the form checkbox field I am testing. Works fine for yes but just stops if I leave the associated checkbox blank. if the "dvd" string does not equals("yes"), the servlet exits with an unknown error. Deep down I'd bet that unknown error is really a NullPointerException. Your original code
parms.getTrimmedString( "dvd" ).equals( "yes" )
doesn't gracefully allow for the possibility of nulls -- and null is exactly what parms.getTrimmedString( "dvd" ) resolves to if the associated checkbox is blank. So when .equals() is called on null, a NPE gets thrown. Your second version of the code *does* handly nulls gracefully (albeit somewhat verbosely). I'll show you a less verbose way to do the same thing (but you must first suffer through one of my famous explanation-through-demonstration posts). Then I'll challange you do to some detective work and find a third way of doing the same thing (if you want).
Why do you have to care about nulls when working with these checkboxes? First you have to understand how the parameters from the web page form are packaged up by LogServlet for you to use in your servlet code. These parameters and values from posting the form are put in a Map (actually a CastMap). The parameter names are map keys and the parameter values are name values. There's a bit of trickiness with checkboxes though. You've already seen, for example, that if the checkbox with the name "dvd" and value "yes" is checked, the map will contain an entry with "dvd" as the key and "yes" as the value. But if that checkbox is *not* checked, the map will contain *no entry at all* for "dvd". If you try to retrieve and use a value from a nonexisting entry, you get a null back. Your code must be able to handle those nulls gracefully, otherwise you'll have code throwing NullPointerExceptions and crashing.
Here's some code that illustrates my point.
A web page in html (call it showParameters.html):
<code>
<html>
<head>
<title>Show Parameters Servlet</title>
</head>
<body>
<h1>Show Parameters Servlet</h1>
<form method = 'POST' action = '/servlet/ShowParametersServlet'>
<p>
Thread participants:
<br><input type = 'checkbox' name = 'Greg' value = 'yes'>Greg
<br><input type = 'checkbox' name = 'Pauline' value = 'yes'>Pauline
<br><input type = 'checkbox' name = 'Barry' value = 'yes'>Barry
<br><input type = 'checkbox' name = 'Carol' value = 'yes'>Carol
<br><input type = 'checkbox' name = 'Mike' value = 'yes'>Mike
<br><input type = 'checkbox' name = 'Jason' value = 'yes'>Jason
</p>
<p><input type=submit value='showWhatsBeingPassed'></p>
</form>
</body>
</html>
</code>
And the servlet this web page calls:
<code>
import java.io.PrintWriter ;
import java.util.Iterator ;
import java.util.Map ;
import com.javaranch.common.* ;
public class ShowParametersServlet extends LogServlet
{
public void doPost( PrintWriter out , CastMap parameters )
{
out.println( "Er, check the console because I didn't feel like dealing with html." );
for ( Iterator iterator = parameters.entrySet().iterator() ; iterator.hasNext() ; )
{
Map.Entry entry = (Map.Entry)iterator.next() ;
System.out.println( "( " + entry.getKey() + " , " + entry.getValue() + " )" ); // (A)
}
System.out.println( parameters.getString( "The Moose" ) ); // (B)
}
}
</code>
Access showParameters.html served from Orion or suchlike. Check some of the checkboxes and leave others blank. Then click the "showWhatsBeingPassed" button. In the console output generated by code at (A),
you should be able to see exactly what I'm saying about checkboxes. There are entries for the checked ones, but no entries for the unchecked ones. So if you had left checkbox Pauline blank and called getString( "Pauline" ) or getTrimmedString( "Pauline" ), you'd have a null on your hands because there's no "Pauline" entry in that parameters map. Just like there's no entry for "The Moose" at line (B). (If showParameters.html is the only page posting to ShowParametersServlet, there would never be a "The Moose" entry because there's no "The Moose" html input control on the form.)
(If you're wondering why System.out.println() can just print "null" for nulls, but method calls on null cause your program to blow up, that's because there's some special magic behind System.out.println() to do just that. Otherwise debugging would be a major pain.)
So if getString( "dvd" ) (or getTrimmedString( "dvd" )) has the possibility of returning null, how do you safely call equals() on it? There's the way you proposed, but why not just try flipping things around:
"yes".equals( parms.getString( "dvd" ) )
(Yes, you can do method calls on string literals!)
(Note also that this whole thing resolves to a boolean -- which could come in *very* handy.
Depending of course on what you doing with it.)
Can't remember whether this calling-equals-on-"yes" trick gets an OK from the nitpickers though, but it's worth a try.
The other way of handling this I'm not going to tell you because it's sitting right there in the javaranch.common.com package just waiting for you to find it. Happy hunting!
[ November 15, 2003: Message edited by: Michael Matola ]