My application is using Spring MVC.
On the way from the Controller to the view we are taking adventage of this framwork by creating a bean of the model that is used to display the relevant properties through the JSP.
On the way back however, meaning after submitting a form back to the controller, it is using a raw HTTPRequest instead of a structured formBean.
I think that this is a disadvantege so I am looking for way to insert this to our MVC model.
I saw in this link some way that Spring MVC handles it.
by adding to the JSP binding such as:
<spring:bind path="command"> <font color="red"> <b><c:out value="${status.errorMessage}"/></b>
</font>
</spring:bind>
and to the controller:
protected ModelAndView onSubmit(Object command) throws ServletException
{ Widget widget = (Widget) command;
...
}
But this solution is not good for our implementation - I don't want to add anything to the JSP and in addition . some of the parameters that are added to the httprequest are done in javascript code.
Therefore I am looking for a solution that can create formBean out of the form parameters while the mapping is not defined on the JSP but elsewhere (in some dedicated xml obviously).
Any ideas?
The simplest way to use a form (command) bean in Spring is to write a controller that extends SimpleFormController.
A quick Google shows a number of basic tutorials - for example:
http://www.vaannila.com/spring/spring-simple-form-controller-1.html
Related
I am trying to validate 2 model attributes on one action using spring validation framework. The purpose is to validate the lookUpbean (search criterion) on click of Search button and then to validate the resultant bean also i.e memberShipbean once we get it from the services so that we can show warnings to the user if some fields are empty in the resultant bean.
<form:form method="POST" modelAttribute="lookupPageBean" id="lookupForm" name="lookupForm"
action="lookupMembership.htm">
<td class="error">
<form:errors path="membershipNumber" />
<form:input class="medium-textbox" id="membershipNumber" path="membershipNumber" />
<button type="submit" class="Active-button-small">
<fmt:message key="button.go" />
</button>`
#RequestMapping(method = RequestMethod.POST, value = URLMappingConstant.MEMBERSHIP_LOOKUP)
public String viewMembership(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response,
#ModelAttribute(UIConstant.LOOKUP_PAGE_BEAN) LookupPageBean lookupPageBean, BindingResult result,
#ModelAttribute(UIConstant.MEMBERSHIP_BEAN) MembershipPageBean membershipPageBean, BindingResult error) throws WebMTracksException
{
membershipValidator.validate(lookupPageBean, result);
membershipValidator.validate(membershipPageBean, error);
}
Now what is happening is first validation is working fine however during second validation
the error messages are not shown on the resultant jsp ,
however the errors are reported till this controller layer in the “error” binding results.
Also in the validation layer
ValidationUtils.rejectIfEmpty(errors, UIConstant.BUSINESSNAME,ValidationMSGConstants.BUSINESS_NAME)
This method always returns validation errors even if the field is not empty.
First question is can we have multiple model attributes in one action. I read it somewhere on internet but could not find any implementation of the same. Please help me to resolve this issue. Also let me know if you can think of any other working solution for this problem but I would like to use only the spring framework for the both the validations as that helps to maintain the existing design of the application.
I do not think you have bind multiple Model Attributes to the same form, which I believe is what you are asking. I am not even sure what that request would look like, from an HTTP stand point, as I don't believe Spring would have a way to detangle all the bean's properties, especially if the names overlap. What you may want to consider doing is wrapping your LookupPageBean and MembershipPageBean into one "form bean".
As for the error messages, you may want to take a look at the spring:bind tag. It may do what you are needed to get the binding errors from the second Model Attribute.
I am in the process of changing a project which used a simple java HTTPServer on port 8080 to that which uses the Spring MVC servlet framework.
There are lots of links in the application like so:
Manage rules<br/>
Which worked fine using requests such as:
http://localhost:8080/send
However, these now don't work unless I put the servlet name in front like so:
"Manage rules<br/>"
Just wondering is there any way around this, or is it a matter of just changing all the href links to add the servlet name in front of them?
Note that I dont have to add the servlet name in my #RequestMapping calls at the start of methods, its only links that are the problem. E.g. this works fine without adding the servlet name in front
#RequestMapping(value = "/send", method = RequestMethod.GET)
If you use JSPs in your view layer, use a tag library that has a link tag (or write one yourself). Basically, the link tag has to create the url by doing
HttpServletResponse.encodeURL(originalUrl)
The <c:url> tag in JSTL does that, but it only generates the URL, not the link tag, but it can get you there like this:
<c:url value="your/relative/url" var="somevar" />
Link Text
I made this way more confusing than it needed to be. Here is the simplified version.
1 - I have a drop down and a submit button on every page in the upper right hand corner. The drop down is a list of languages. The user can change the language and press the submit button to go to the language controller and update the current language.
public class LanguageController {
#ModelAttribute("languageList")
public LanguageList populateLanguageList() {
return LanguageDAO.all();
}
#RequestMapping("/setLanguage.mvc")
public ModelAndView setLanguage(
#ModelAttribute("languageForm") LanguageForm languageForm,
HttpServletRequest request,
HttpServletResponse response
){
//do stuff
}
}
<form:form modelAttribute="languageForm">
<form:select path="acctGrpId" >
<form:options items="${languageList}"/>
</form:select>
<input type="submit"/>
</form:form>
How would I make that available on every page? Given that the page might be a page where you are editing/creating a user so the "Controller" of that page is actually a UserController, or RoleController, or DepartmentController, not the LanguageController. I need this particular jsp to hit a specific controller regardless of what the page is doing.
You just specify different action attribute in different forms. There's no problem in having multiple forms on one page.
In your case it would be:
<form action="Context/adduser.mvc">
</form>
and
<form action="Context/addBookmark.mvc">
</form>
etc
I would love to help you on this, but I am unsure of your requirements.
Are you talking about BookMarkController having various methods and add/upload calling the methods?
or you want BookMarkController to have more than one form?
Could you please elaborate more on this?
I believe, you want all the jsp pages to post data to a controller which can save the form when a link is clicked. This is quite simple, you can add a savePage method in all the controllers and map the uri accordingly and from the savePage method you can reedirect the request to the specific controller which you have written to save the pages.
Hope this helps.
Your JSP is the view, which is separate from your controller. That's the beauty of MVC, the separation of the Model, View, and Controller. You shouldn't necessarily think of the view as being tied to a controller, or a page as having a "current" controller. Yes, we often make that association pretty strong because the controller handles populating the model attributes to render the view and processing the form post as a result of an action in the view, but really any controller can return any view as long as it populates the model correctly, and any view can submit to any controller. A view can even submit to different controllers at different times depending on the url that is followed.
So, in your case, as soulcheck says, you simply change the URL that the form submits to. Because the controllers are mapped by the #RequestMapping, changing the form's action will change the controller class and/or method that is called when the form is submitted as long as Spring MVC can find a suitable RequestMapping.
Is this what you are looking for?
What are the best practices around setting global model attributes in Spring MVC?
implement a HandlerInterceptor, and expose the data to every request
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
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.