Spring3 MVC: Validation not working - java

The gender validation is not working. Even if no values are entered in the gender text field, the form is getting validated successfully without throwing any error.
Below is the Employee class:
#Size(min=2,max=10)
private String gender;
// Setters and Getters
Below is the Controller method:
#RequestMapping(value="done", method = RequestMethod.POST)
public String validateForm(#Valid Employee employee, BindingResult result, ModelMap m){
if(result.hasErrors()){
System.out.println("Validation Failed!!!");
return "main";
}else{
System.out.println("Validation Succeeded!!!");
return "done";
}
}
Below is the context file:
<context:annotation-config />
<context:component-scan
base-package="com.XXX" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
Below is the jsp file:
<tr>
<td>
Gender:
</td>
<td>
<form:input path="gender"/>
<form:errors path="gender" cssStyle="color: red;"/>
</td>
</tr>
I am not able to find out whats missing but its something silly. Please help.

1) All of the javax constraints include an implicit "or null" in their pass conditions. If you want to catch blanks you need to either add #NotNull, or reconfigure the web binder to bind blank inputs to empty string instead of null.
2) <context:annotation-config /> does not turn on Spring 3 dispatcher servlet auto-config magic. You need to define your own validator bean if you do that. To enable everything to automagically work you need to use <mvc:annotation-driven />.

Related

Required CommonsMultipartFile parameter 'file' is not present in spring boot

I am trying to add feature of uploading excel to my spring boot application.
jsp:
<form action="/uploadpoifile/truepoi" method="post" enctype="multipart/form-data">
<input type="file" name="excelfile" />
<input type="submit" value="Upload" />
</form>
bean:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxInMemorySize" value="409600"/>
<property name="maxUploadSize" value="200000000"/>
</bean>
controller:
#Controller
#RequestMapping("/uploadpoifile")
public class QcUploadPoiFileController {
#ResponseBody
#RequestMapping(value = "/{poiType}", method = RequestMethod.POST)
void update(#RequestParam(value = "excelfile") CommonsMultipartFile file, #PathVariable(value = "poiType") String poiType){...}
}
After I selected excel I click upload and see error message:
Required CommonsMultipartFile parameter 'excelfile' is not present
What do I wrong?

how to create a properties file for error messages thrown ny #Valid annotation in spring

I have this class, where the field "nome" can't be empty
public class Utente {
......
#NotEmpty
#Size(min=2, max=30)
private String nome;
.......
}
After the user fills and sends the form I call this method
#RequestMapping("/formSent")
public String formSentMethod(Model model, #Valid Utente utente, BindingResult result){
.....
}
I print the error in the Eclipse's console with this plain code, put inside the formSentMethod method.
#RequestMapping("/formSent")
public String formSentMethod(Model model, #Valid Utente utente, BindingResult result){
.....
for(ObjectError errore : result.getAllErrors()){
System.out.println(errore.getDefaultMessage());
}
.....
}
So far, I get the default error message "may not be empty", when the user doesn't fill the field "nome".
I tried to customize that message by using a properties file called messages.properties, that I put under WEB-INF/classes, as you can see in this pic
Inside messages.properties I wrote
NotEmpty.utente.nome = Il nome è obbligatorio
In my XXX-servlet.xml I "call" the properties file this way
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
<property name="basename" value="messages" />
</bean>
<mvc:annotation-driven />
Since it didn't work I even tried editing the basename value this way
<property name="basename" value="WEB-INF/Classes/messages" />
but it didn't work as well.
I keep on getting the default error message and not my customized message "Il nome è obbligatorio". Probably what I wrote in my properties file is not correct. What am I doing wrong?
message.properties doesn't reference the class and field, but form name and the field. For example in this html:
<form:form method="POST" commandName="utente" action="customer/signup">
<form:errors path="*" cssClass="errorblock" element="div" />
<table>
<tr>
<td>Customer Name :</td>
<td><form:input path="nome" /></td>
<td><form:errors path="nome" cssClass="error" /></td>
</tr>
<tr>
<td>Customer Age :</td>
<td><form:input path="age" /></td>
<td><form:errors path="age" cssClass="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" /></td>
</tr>
</table>
</form:form>
NotNull.utente.nome will be correct, because the form utente contains field nome. The important thing is, it's not based on the class but the path in html.
To access the internationalization from controller, you need MessageSource bean, and use the bean to get the internationalization.
Here is example taken from here to access internationalization message in controller:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="ValidationMessages"/>
</bean>
Inject your MessageSource instance inside your Controller
#Autowired
private MessageSource messageSource;
And to get your message, do as follows
for (Object object : bindingResult.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
/**
* Use null as second parameter if you do not use i18n (internationalization)
*/
String message = messageSource.getMessage(fieldError, null);
}
}
I believe that message's should be placed inside classes but one level up, according to your configuration.
You could also make a absolute path like:
/WEB-INF/classes/messages
or one level up
/WEB-INF/messages
Also, remember that with this configuration, you're not setting default encoding, which may lead to some problems, I suggest set property defaultEncoding to UTF-8

Spring MVC with Spring Webflow

I am trying to use Spring Webflow with my Spring MVC application.I had a look at the booking-mvc example and followed it,but most of the examples on the web are done with Tiles.I Hope that i am not completely wrong in my understanding and that Spring Webflow can be used with Spring MVC
I am trying to use Spring MVC controllers.But when i am doing a transition like submit/finish nothing seems to happen.
Here is my Flow xml:
<view-state id="enterBookingDetails">
<transition on="submit" to="reviewBooking" />
</view-state>
<view-state id="reviewBooking">
<transition on="confirm" to="bookingConfirmed" />
<transition on="revise" to="enterBookingDetails" />
<transition on="cancel" to="bookingCancelled" />
</view-state>
I Have enterBookingDetails and reviewBooking defined as controllers :
#RequestMapping(value = "/enterBookingDetails", method = RequestMethod.GET)
public ModelAndView getPage(final HttpServletRequest request) {
ModelAndView modelView = new ModelAndView();
modelView.setViewName("pa");
return modelView;
}
#RequestMapping(value = "/reviewBooking", method = RequestMethod.GET)
public ModelAndView getPage2(final HttpServletRequest request) {
ModelAndView modelView = new ModelAndView();
modelView.setViewName("pb");
return modelView;
}
My Jsp looks like this :
<form:form>
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="finished" />
<input type="submit" value="Submit" name="_eventId_finished" />
</form:form>
And finally my configuration :
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="mvcViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1" />
</bean>
<!-- Register all Web Flow definitions under /WEB-INF/flows/**/*-flow.xml -->
<webflow:flow-registry id="flowRegistry"
base-path="/WEB-INF/flows" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
<!-- Deploy a flow executor -->
<webflow:flow-executor id="flowExecutor" />
<!-- Configure flow builder services -->
<!-- Configure view service -->
<webflow:flow-builder-services id="flowBuilderServices"
view-factory-creator="mvcViewFactoryCreator" />
<!-- Web Flow components -->
<!-- Install flow handler (FlowHandlerAdapter) -->
<!-- It dispatches URL requests to flows -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<!-- Map Http request path to flows register in the registry -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
<property name="order" value="0" />
</bean>
<bean id="mvcViewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="mvcViewResolver"/>
</bean>
Spring Webflow is built on spring web mvc, so the two can be used together.
I have learned that the problem with this combination is that when there is something misconfigured, the only symptom is "nothing happens". I ultimately ended up looking at the debug logs for org.springframework.web and org.springframework.webflow, then tracing into the spring source code to diagnose configuration issues.
The spring paradigm is aiming towards "convention over configuration". The problem I have had with it is that the conventions are not always well defined in a manner that someone already familiar with them can easily grasp.
The final "gotcha" that I had to resolve is that the convention for spring webflow is to put the flow xml files in the same folder as the jsp's.
In your example, you appear to be planning to switch between spring-webflow and unadorned web mvc behind the same view. Provided everything is correctly configured, for a given uri, whatever is in the webflow registry will trump whatever is in the UrlHandlerMapping (your annotations). This can create confusion if you're not aware of it.

Spring locale messages don't work only within spring:form tag

Hello I have a form input button as follows :
<form:input path="creationUsr.lastName" type="text" name="creationUsr.lastName" id="creationUsr.lastName" class="login-text" placeholder="<spring:message code='tile.form.lastName'/>" value=""/>
Here is my spring context locale setting :
<mvc:interceptors>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
If I put this out of form tag :
<spring:message code='tile.form.lastName'/>
The value is as I should be.
I have a way around this but it's kind of ugly. I could revert to normal forms without using spring and regular <input type="text" name="lastname"> instead of <form:input .. and then serialize form to json and do a post with javascript.
I'm sure there must be a way to do this with spring mvc.
You can't use a JSP tag inside an attribute of another JSP tag. To do what you want, save the message in a page-scope attribute, and use the EL to pass the message to the input tag:
<spring:message code='tile.form.lastName' var="lastNameMessage"/>
<form:input path="creationUsr.lastName"
type="text"
name="creationUsr.lastName"
id="creationUsr.lastName"
class="login-text"
placeholder="${lastNameMessage}"
value=""/>

Using VelocityView or plain text in Controller response?

I'm trying to return content other than json in my Controller, but I can't seem to get it to work. Ideally, I'd like to return a rendered velocity template as plain text or html.
This is what I have in my controller:
#RequestMapping( value = "time", headers = "Accept=*/*", method = RequestMethod.GET )
public #ResponseBody
Date getCurrentTime( HttpServletRequest request, HttpServletResponse response ) {
response.setContentType( "text/plain" );
return new Date();
}
And this is in my springmvc-servlet.xml (I know this is not right...but I'm a bit lost here):
<context:component-scan base-package="com.paml.alerter.controller" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true" />
<property name="prefix" value="" />
<property name="suffix" value=".vm" />
</bean>
<!-- This bean sets up the Velocity environment for us based on a root path
for templates. Optionally, a properties file can be specified for more control
over the Velocity environment, but the defaults are pretty sane for file
based template loading. -->
<bean id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/velocity/" />
</bean>
Does anyone know how to set this up right?
TIA
If your method is annotated with #ResponseBody, then the Spring MVC view layer will be bypassed entirely.
If you're not interested in JSON output, then #ResponseBody is inappropriate - just remove it, and your Velocity views will be used.
If you need to switch between JSON and some other View layer, then you should consider removing #ResponseBody and using ContentNegotiatingViewResolver instead. See the Spring docs for how to set this up.

Categories

Resources