I'm implementing a JSP which expects a few parameters which have to be validated before running the jsp.
Suggestion: Validate the parameters inside the JSP using
Taglibraries
Suggestion: Pre-parse the Parameters in a Filter
What do you think?
Edit
Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent.
example:
https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...
None of both are good approaches. Controller/business logic doesn't belong in a JSP (tag). A filter is almost good, but it's not specific enough. This job should be done by a servlet. You're submitting the form to a servlet to postprocess it, right? It sounds like that you're not already doing that, the answer would otherwise have been pretty straightforward.
In our servlets tag wiki page you can find a hello world example of a good approach of using a JSP with a Servlet to postprocess a form submit. Here's an extract of relevance:
<input id="name" name="name" value="${fn:escapeXml(param.name)}">
<span class="error">${messages.name}</span>
with
String name = request.getParameter("name");
if (name == null || name.trim().isEmpty()) {
messages.put("name", "Please enter name");
}
// ...
request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
Further, there exist MVC frameworks which removes all the boilerplate (duplicated/repeated) servlet code for this kind of use cases, such as JSF, Spring MVC, Wicket, Stripes, Struts2, etc. With for example JSF it look just something like this:
<h:inputText id="name" value="#{bean.name}" required="true" requiredMessage="Please enter name" />
<h:message for="name" />
That's all. The JSF's FacesServlet controller servlet will validate if it's been filled in and display a (configureable) message at the given location, without any need for custom Java code. You could even move it to the model, JSF has transparent support for JSR303 bean validation as well. E.g.
<h:inputText id="name" value="#{bean.name}" />
<h:message for="name" />
with
#NotNull(message="Please enter name")
private String name;
Update as per your edit:
Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent. example: https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...
Just use a servlet the same way. The only difference is that you've to implement the job in doGet() instead of doPost() and if necessary return HTTP 400 on an error :) Once again, check our servlets tag wiki page to understand their purpose better. Or to go a step further, use a webservice framework instead, such as JAX-WS or JAX-RS which do this job transparently like a MVC framework does for HTML pages.
Use an MVC Framework (Spring MVC, Stripes, Struts 2 etc.) and validate the parameters in the controller class. Every MVC framework supports parameter validation, and you get a clean separation of concerns.
Example: Spring MVC automatically registers JSR-303-style parameter Validation (if you have a JSR-303 provider, e.g. Hibernate-Validator, on the classpath) when using mvc:annotation-driven
Related
I am doing validation inside validate() method.
public void validate(){
if(continent.equals("-1")){
HttpServletRequest request=ServletActionContext.getRequest();
HttpSession session=request.getSession();
String s=(String)session.getAttribute("operation");
if(s.equals("edit"))
edit();
else if(s.equals("add"))
add();
addFieldError( "Continent", "Continent must be selected");
}
}
And in jsp(view) added form attribute validate=true
<s:form action="add" name="aaa" cssClass="yy" method="post" validate="true">
<s:textfield name="Code" label="Code" readonly="false" cssClass="defaultTextBox"/>
<s:textfield name="Name" label="Name" cssClass="defaultTextBox"/>
<s:select name="Continent" label="Continent" headerKey="-1" headerValue="Select" list="continentlist" cssClass="defaultTextBox"/>
<s:textfield name="IndepYear" label="Independance Year" cssClass="defaultTextBox" />
<s:submit value="Save" cssClass="login login-submit" theme="simple"/>
</s:form>
But only server side validation is working. My question is -->is it not possible to add client side validation using validate() method?
In Struts 2, Client Side Validation has different meanings, and totally depends on the type of theme you are using.
With XHTML (default) and CSS XHTML, you can use the
Pure JavaScript Client Side Validation
that is totally client side, Javascript based and doesn't communicate with the server.
With the AJAX theme instead, you can run the
AJAX Client Side Validation
that will contact the server, running the whole validation Stack, and (to answer your question) running your validate() methods too.
I personally prefer to use the SIMPLE theme, completely handling the HTML, the CSS and the JavaScript on my own.
Since the server-side validation is mandatory, the client-side validation is to be considered just a surplus, positive for making the page more user-friendly, and to reduce the network traffic in high users environment (you block unsuccessfull - but legit - requests before they go through the wire :)
Consider using HTML5 types with fallback on jQuery, especially if you are targeting the mobile.
actually you shouldn't mix up server side and client side code.
validate method can be invoked only in server side... So there is no way to use this method on client side.
You need to write your own JS side validation as the same as server side validation.
It is possible to perform AJAX validation using your server side code using struts2-jquery plugin , as shown in the Showcase under:
Form Forms with Validation
Form Forms with Custome Validation
The example that might interest you more is Form Submit without AJAX.
I have a basic CRUD view-scoped bean. Within the setter methods I am performing some data-specific validation, which build a detailed error message for each setter if an error occurs in any of them.
This works fine, but I would like to empty this error message on each request and I have no idea how I would do that.
preRenderView won't cut it, because this error message needs to be rendered as well. Something like a postRenderView would be ideal.
You shouldn't perform validation in setter methods and you shouldn't store validation messages in the backing bean. Your whole problem is just caused by bad design and not utilizing JSF provided validation facilities.
Just utilize JSF provided validation facilities instead of working completely around it and all your problems as described so far will disappear. You can use several of the JSF builtin validators such as required="true", validator="javax.faces.XxxValidator, <f:validateXxx> tags, etc on input components. You can create a custom validator by implementing Validator interface and giving it an unique validator ID which you use in validator="myValidator" or <f:validator validatorId="myValidator">.
When using JSF standard validation, any validation error will be thrown as a ValidatorException with a FacesMessage in the request scope which would be shown in a <h:message> associated with the component. This way the messages will "automagically" disappear in the subsequent requests.
Here's a very basic kickoff example:
<h:form>
<h:inputText id="foo" required="true" requiredMessage="Enter this!" />
<h:message for="foo" />
<h:commandButton value="Submit" />
</h:form>
See also:
Is there how to validate into rich:calendar if the date selected is before a specific date?
How to create JSF form with AJAX data validation
How to show multi error message in jsf while validation is in EJB?
How validate two password fields by ajax?
etc...
I'm looking for a very simple form processing API for Java. Assuming the form input fields correspond to bean properties, and all beans have javax.Validation annotations, ideally the API would:
Display a bean as an html form
Populate the bean, including nested objects where applicable, using the request parameters
Validate the input using Validation annotation
If there is an error, display errors at top of form, and highlight error fields.
Additionally:
It would be nice if i didn't have to buy into a whole application framework, since I am working with a legacy app.
Allow configuration for more complicated use cases, but by default just use convention.
Bonus:
generates javascript client side validation too.
Note: If this requires several different libraries, that is fine too.
Update:
Since I never found what I was looking for, and migrating to Spring was not an option, I went ahead and rolled my own solution. It is, affectionately, called java in jails (loosely modeled on rails form processing). It gives you dead simple (and pretty) form creation, client and server side validation, and request parameter to object mapping. No configuration required.
Example Bean:
public class AccountForm {
#NotBlank(groups = RequiredChecks.class)
#Size(min = 2, max = 25)
private String name;
//...
}
Example Form:
<%# taglib uri="http://org.jails.org/form/taglib" prefix="s" %>
<s:form name="accountForm" action="/jails-demo/jails" label="Your Account Details" style="side">
<s:text name="name" label="Name" size="25" />
<s:text name="accountName" label="Account Name" size="15" />
...
</s:form>
Example Validation and Mapping:
SimpleValidator validator = new SimpleValidator();
if ("submit".equals(request.getParameter("submit"))) {
Map<String, List<String>> errors = validator.validate(AccountForm.class, request.getParameterMap());
if (errors != null) {
AccountForm account = validator.getMapper().toObject(AccountForm.class, request.getParameterMap());
//do something with valid account
} else {
SimpleForm.validateAs(AccountForm.class).inRequest(request).setErrors(errors);
//handle error
}
} else {
SimpleForm.validateAs(AccountForm.class).inRequest(request);
//forward to formPage
}
This is what the form looks like, with client side validation using jQuery (provided by Position Absolute):
I don't think you will find something that has most of this functionality and is not a framework.
I can recommend Spring MVC - you can plug it in easily in the legacy app. It supports all of the above.
Doing-it-yourself won't be that hard either:
use BeanUtils.populate(bean, request.getParameterMap()) to fill your object with the request parameters
use javax.validation.* manually - here is how. For each error add request attributes which you can later display as errors.
Note that either way you will have to write the html code manually.
I'm starting building web apps in Spring 3 (and in J2EE) in general.
Looking at the petclinic example I've seen that the programmer creates many JSP pieces, like header, includes, footer and then stitches them together using static inclusion. Anyway what I'd like is that I may have a base page, like Base.jsp and be able to include things like this:
<body>
<jsp:include page="${subpage}"></jsp:include>
</body>
the reason is that I'd like a main page, then being able to put in the ModelAndView returned by the controller which parts of the pages display in each situation (with the data attached to it). This works, but it gives no errors in case ${subpage} is not found, the jsp name is wrong or missing. I'd like more error checking...
Is this the best and recommended way to do this? And if this seems a good idea for what I've in mind, what's the correct way of doing it?
You might want to use Apache Tiles 2 integration for managing your JSP files. Spring has good integration support Apache Tiles. It also shows if there's an error in your page. I've put an example of it at http://krams915.blogspot.com/2010/12/spring-mvc-3-tiles-2-integration.html
It appears you have additional quotes in your subpage. Get rid of them. For example:
<c:set var="subpage" value="/jsp/index.jsp" />
If you have to set it in a controller or servlet - just use request.setAttribute("subpage", "/jsp/index.jsp")
For error checking you can use:
<c:catch var="myException">
<c:import url="${subpage}" />
</c:catch>
and later you can check it with:
<c:if test="${myException != null}">
...
</c:if>
Take a look at Sitemesh (http://www.opensymphony.com/sitemesh). It is a servlet filter-based page layout system that is easy to use. I have done a number of projects using it with Spring MVC and it worked very well.
Is there a cleaner way to do this in a JSP/Struts1 setup ?
... some HTML here ...
EDIT: In admin mode I would like to have access to additional parameters from a form element,
e.g. from the form element:
input type="text" value="Test user" name="Owner"
EDIT 2: Actually, my problem is very similar to the question that was asked in : Conditionally Render In JSP By User
But I don't really get the "pseudo-code" from the likely answer
Is SessionConfig exposed as a bean in your JSP (as part of request / session / Struts Form)?
If it's not, you can expose it. And if it's a static class containing global settings (which, by the looks of it, is a possibility), you can create a small wrapper and put it in the servlet context which you'd then be able to access from Struts tags as scope="application".
Once that's done you can check your condition via Struts tags:
<logic:equal name="sessionConfig" property="adminMode" value="true">
... your HTML here
</logic:equal>
Or, if you're using EL / JSTL, same can be done via <core:if>.
Without more information, it's hard to answer this, but I'd think instead of separate views: one for admin mode, one for normal mode. Extracting the parts of your pages into tiles will help you do this without a lot of pain; see: http://tiles.apache.org/