I am coding a web-app in Java-EE and find myself with a very unexpected result when I am trying to display errors on user-input.
The app is built on the JSP/Servlet/Form/Bean model. Basically, the JSP stores data in the request, and transfers it to the servlet. Then the servlet transfers the request raw to the form, which then reads the data, performs the necessary checks and returns the bean to the servlet.
Most of the fields must have specific values, some others must simply be non-null.
I have written error detection code to secure inputs however I find myself with a very strange result:
- when the field is non-null but the value is incorrect (say, an hour located outside the 00:00-23:59 range), it does return the proper error, along with the error message, stored in a HashMap, and I can access it in my JSP.
- However, when the field is null, it returns the message, probably stores it in the HashMap as well (I know this because the
${!empty errors.dataErrors}test returns true and the error field is displayed in my JSP) but there’s no way to access the values of the errors
I have searched through my code but still can’t find where the error comes from. Here are snippets of it if someone knows where the problem comes from
doPost method from the servlet:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
NewBookingForm form = new NewBookingForm();
Booking booking = form.registerBooking(request);
String VUE;
request.setAttribute("booking", booking);
request.setAttribute("errors", form);
this.getServletContext().getRequestDispatcher(VIEW).forward(request, response);
}
the map is a field in the NewBookingForm class, declared and initialized outside the registerBooking method like this private Map<String,String> dataErrors = new HashMap<String,String>(); and it has a private setter (for access within the class) and a public getter (for access in the Servlet and in the JSP)
inside the form class, I use this function to get the field values:
private static String getFieldValue(HttpServletRequest request, String fieldName)
{
String value = request.getParameter(fieldName);
if (value == null || value.trim().length() == 0){return null;}
else{return value;}
}
After getting the values with a series of calls like String fieldDepartureStation = getFieldValue(request, FIELD_DEPARTURE_STATION); at the beginning of my method, I then check them using try/catch blocks like this
try
{validation.departureStation(fieldDepartureStation);}
catch(Exception e)
{setDataErrors(FIELD_DEPARTURE_STATION, e.getMessage());}
The validations method within the validation class are a bit different if the data must have specific value-ranges or must simply be non-null.
In the former case, they are something like this:
public void departureTime(String time) throws Exception
{
if (!validationRETime(time)) { throw new Exception("Please input a time with the hh:mm pattern"); }
}
....
private boolean validationRETime(String strTime)
{
String regExp = "^([01][0-9]|2[0-3])[:][0-5][0-9]$"; // hh:mm
if (strTime.matches(regExp))
{
return true;
}
else
{
return false;
}
}
whereas in the latter case they are simply
public void departureStation(String station) throws Exception
{
if (station.equals(null)) { throw new Exception("Please input a departure station"); }
}
Finally, in my JSP, I use the following code to display errors:
<c:if test="${!empty errors.dataErrors}">
<p>Errors</p>
<c:forEach items="${errors.dataErrors}" var="message">
<p><c:out value="${message.value}" /></p>
</c:forEach>
</c:if>
And it does display the Error paragraph when I purposedly enter incorrect values, but the <c:forEach> is only looping and displaying the error messages when the wrong field is non-null but with an incorrect value. Thus with a field that only needs to be non-null, I never get the message (but I do get the error)
These are all the things I could think of that could possibly go wrong, but I have yet to discover where they did and if someone could help me, I’d be very glad.
The problem is in your
departureStationmethod: –Your test for
nullvalue is itself triggering aNPE. So, as soon asstation.equals(null)is executed forstation = null, aNPEexception is thrown, which is then propagated to the caller. So, yourifblock will not even be executed. And hence you are not throwing theExceptionas you might be thinking.Now, also note that, the
NPEthat is thrown does not contain anymessage. So,e.getMessage()will returnnullon it.Now, let’s move back to the caller: –
Here you are doing the biggest Crime in the world of
Exception Handling, by using a catch block forException. SinceExceptionis the super class of all the exceptions, it will handle all the exceptions in the same way. So, it consumes theNPE, and passes it tosetDataErrors().So, you will of course get the errors, but, the value
e.getMessage()will benull. And that is why you are not seeing any message. You can even test it byloggingthe value ofe.getMessage()in thecatch blockabove.Solution ??
Just change your
nullcheck with this one: –And everything will be ok. I think, you will have to do this change in all of your methods. Always perform the
null checkusing==operator.