Issue
I am trying to display error messages to the user when he registers on website. I am using spring, spring validation, spring security and mysql database. I am new to spring, and I can't figure this out.
Here is my html file:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<title>Create an account</title>
<link href="${contextPath}/resources/css/bootstrap.min.css" rel="stylesheet">
<link href="${contextPath}/resources/css/common.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<form:form method="POST" modelAttribute="userForm" class="form-signin">
<h2 class="form-signin-heading">Create your account</h2>
<spring:bind path="username">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="username" class="form-control" placeholder="Username"
autofocus="true"></form:input>
<form:errors path="username"></form:errors>
</div>
</spring:bind>
<spring:bind path="password">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="password" path="password" class="form-control" placeholder="Password"></form:input>
<form:errors path="password"></form:errors>
</div>
</spring:bind>
<spring:bind path="passwordConfirm">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="password" path="passwordConfirm" class="form-control"
placeholder="Confirm your password"></form:input>
<form:errors path="passwordConfirm"></form:errors>
</div>
</spring:bind>
<button class="btn btn-lg btn-primary btn-block" type="submit">Submit</button>
</form:form>
</div>
<!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>
</body>
</html>
My dispatcher-servlet looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.web.shop"/>
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
p:basename="WEB-INF/messages" />
</beans>
My UserValidation file:
@Component
public class UserValidator implements Validator {
@Autowired
private UserService userService;
@Override
public boolean supports(Class<?> aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
User user = (User) o;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "NotEmpty");
if (user.getUsername().length() < 6 || user.getUsername().length() > 32) {
errors.rejectValue("username", "Size.userForm.username");
}
if (userService.findByUsername(user.getUsername()) != null) {
errors.rejectValue("username", "Duplicate.userForm.username");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "NotEmpty");
if (user.getPassword().length() < 8 || user.getPassword().length() > 32) {
errors.rejectValue("password", "Size.userForm.password");
}
if (!user.getPasswordConfirm().equals(user.getPassword())) {
errors.rejectValue("passwordConfirm", "Diff.userForm.passwordConfirm");
}
}
}
My file with the messages is in WEB-INF in messages folder, it is called validation.properties and look like this:
NotEmpty=This field is required.
Size.userForm.username=Please use between 6 and 32 characters.
Duplicate.userForm.username=Someone already has that username.
Size.userForm.password=Try one with at least 8 characters.
Diff.userForm.passwordConfirm=These passwords don't match.
I don't understand why cant it find the messages. This is the error that I am getting:
There was an unexpected error (type=Internal Server Error, status=500).
org.springframework.context.NoSuchMessageException: No message found under code 'Size.userForm.username' for locale 'en_US'.
Thank you for your help.
Solution
Follow the resource file naming convention like your file name should be
"messages_en_us.properties"
<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>classpath*:messages</value>
</property>
Since all your properties files are in classpath of java you need to define the path with prefix classpath*: otherwise it will look into the web directory of your application
Answered By - Sangam Belose