简体   繁体   中英

Can't resolve custom validation messages in Hibernate + Spring

I am developing Spring MVC + Hibernate Validator integration example by taking reference from https://spring.io/guides/gs/validating-form-input/ . I added some messages to be gets resolved from messages.properties file, but none of the messages getting resolved and facing below issue. Please guide why application not recognizing the messages.properties file. I was expecting to get actual message from .properties file, but why this is coming [{length.validation.country}] ?

org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'person' on field 'country': rejected value [U]; 
codes [Length.person.country,Length.country,Length.java.lang.String,Length]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes 
[person.country,country]; arguments []; default message [country],50,2]; default message [{length.validation.country}]

Person.java

@Entity
@Table(name="PERSON")
public class Person {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @SafeHtml(whitelistType=WhiteListType.NONE, message="{html.validation.firstname}")
    @Length(max=Constant.MAX_FIRSTNAME,min=Constant.MIN_FIRSTNAME,message="{length.validation.firstname}")
    @Column(name="FIRST_NAME")
    private String firstname;

    @SafeHtml(whitelistType=WhiteListType.NONE, message="{html.validation.lastname}")
    @Length(max=Constant.MAX_LASTNAME,min=Constant.MIN_LASTTNAME,message="{length.validation.lastname}")
    @Column(name="LAST_NAME")
    private String lastname;

    @SafeHtml(whitelistType=WhiteListType.NONE, message="{html.validation.country}")
    @Length(max=Constant.MAX_COUNTRY,min=Constant.MIN_COUNTRY,message="{length.validation.country}")
    @Column(name="COUNTRY")
    private String country;

    @SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE, message = "{html.validation.emailId}")
    @Length(max=Constant.MAX_EMAILID,min=Constant.MIN_EMAILID, message = "{length.validation.emailId}")
    @Pattern(regexp = "^(.+)@(.+)$")
    @Column(name="EMAIL_ID")
    private String emailId;
        // setters and getters
}

PersonController.java

@Controller
public class PersonController {

    private PersonService personService;

    public PersonController(){}

    public PersonController(PersonService personService){
        this.personService = personService;
    }

    @Autowired(required=true)
    @Qualifier(value="personService")
    public void setPersonService(PersonService ps){
        this.personService = ps;
    }

    @RequestMapping(value = "/persons", method = RequestMethod.GET)
    public String listPersons(Model model) {
        model.addAttribute("person", new Person());
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }

    //For add and update person both
    @RequestMapping(value= "/person/add", method = RequestMethod.POST)
    public String addPerson(@Valid @ModelAttribute("person") Person p, BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            System.out.println(bindingResult);
            return "redirect:/persons";
        }

        if(p.getId() == 0){
            //new person, add it
            this.personService.addPerson(p);
        }else{
            //existing person, call update
            this.personService.updatePerson(p);
        }

        return "redirect:/persons";

    }

    @RequestMapping("/remove/{id}")
    public String removePerson(@PathVariable("id") int id){
        this.personService.removePerson(id);
        return "redirect:/persons";
    }

    @RequestMapping("/edit/{id}")
    public String editPerson(@PathVariable("id") int id, Model model){
        model.addAttribute("person", this.personService.getPersonById(id));
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }
}

messages.properties

html.validation.firstName=Invalid First Name
length.validation.firstName=First Name should be 2 to 50 lenght in characters
html.validation.lastName=Invalid Last Name
length.validation.lastName=Last Name should be 2 to 50 lenght in characters
html.validation.country=Invalid Country Name
length.validation.country=Country Name should be 2 to 50 lenght in characters
html.validation.emailId=Invalid Email ID
length.validation.emailId=Email ID length should not be more than 11 characters

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
    <context:component-scan base-package="com.journaldev.spring.controller" />

    <!-- Load database.properties file -->
    <context:property-placeholder location="classpath:database.properties" />

    <!-- Enable JPA Repositories -->
    <jpa:repositories base-package="com.journaldev.spring.repository" />

    <!-- Enable Transaction Manager -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Necessary to get the entity manager injected into the factory bean -->
    <beans:bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />


    <!-- ====== MYSQL DataSource ====== -->
    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <beans:property name="driverClassName" value="${mysql.jdbc.driverClassName}" />
        <beans:property name="url" value="${mysql.jdbc.url}" />
        <beans:property name="username" value="${mysql.jdbc.userName}" />
        <beans:property name="password" value="${mysql.jdbc.password}" />
    </beans:bean>

    <!-- ====== Hibernate JPA Vendor Adaptor ======= -->
    <beans:bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <beans:property name="showSql" value="true"/>
        <beans:property name="generateDdl" value="true"/>
        <beans:property name="database" value="MYSQL"/>
    </beans:bean>


    <!-- Beans -->
    <beans:bean id="personService" class="com.journaldev.spring.service.PersonServiceImpl" />
    <beans:bean id="visitService" class="com.journaldev.spring.service.VisitServiceImpl" />


    <beans:bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <beans:property name="packagesToScan" value="com.journaldev.spring.*" />
        <beans:property name="jpaProperties">
            <beans:props>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>  <!-- validate | update | create | create-drop -->
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</beans:prop>
                <!-- <beans:prop key="hibernate.cache.use_query_cache">true</beans:prop> --> 
            </beans:props>
        </beans:property>
    </beans:bean>

    <beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <beans:property name="entityManagerFactory" ref="entityManagerFactory" />
    </beans:bean>

    <beans:bean id="validationMessageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:messages" />
        <beans:property name="defaultEncoding" value="UTF-8" />
    </beans:bean>

    <beans:bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <beans:property name="validationMessageSource">
           <beans:ref bean="validationMessageSource"/>
        </beans:property>
    </beans:bean>
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
</beans:beans>

Person.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ page session="false" %>
<html>
<head>
    <title>Person Details Page</title>
    <style type="text/css">
        .tg  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}
        .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}
        .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}
        .tg .tg-4eph{background-color:#f9f9f9}
    </style>
</head>
<body>
<h1>
    Add a Person
</h1>

<c:url var="addAction" value="/person/add" ></c:url>

<form:form action="${addAction}" commandName="person">
<table>
    <c:if test="${!empty person.firstname}">
    <tr>
        <td>
            <form:label path="id">
                <spring:message text="ID"/>
            </form:label>
        </td>
        <td>
            <form:input path="id" readonly="true" size="8"  disabled="true" />
            <form:hidden path="id" />
        </td> 
    </tr>
    </c:if>
    <tr>
        <td>
            <form:label path="firstname">
                <spring:message text="First Name"/>
            </form:label>
        </td>
        <td>
            <form:input path="firstname" />
        </td> 
    </tr>

    <tr>
        <td>
            <form:label path="lastname">
                <spring:message text="Last Name"/>
            </form:label>
        </td>
        <td>
            <form:input path="lastname" />
        </td> 
    </tr>

    <tr>
        <td>
            <form:label path="emailId">
                <spring:message text="EmailId"/>
            </form:label>
        </td>
        <td>
            <form:input path="emailId" />
        </td> 
    </tr>

    <tr>
        <td>
            <form:label path="country">
                <spring:message text="Country"/>
            </form:label>
        </td>
        <td>
            <form:input path="country" />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <c:if test="${!empty person.firstname}">
                <input type="submit"
                    value="<spring:message text="Edit Person"/>" />
            </c:if>
            <c:if test="${empty person.firstname}">
                <input type="submit"
                    value="<spring:message text="Add Person"/>" />
            </c:if>
        </td>
    </tr>
</table>    
</form:form>
<br>
<h3>Persons List</h3>
<c:if test="${!empty listPersons}">
    <table class="tg">
    <tr>
        <th width="80"><b>PersonID</b></th>
        <th width="120"><b>FirstName</b></th>
        <th width="120"><b>LastName</b></th>
        <th width="120"><b>EmailID</b></th>
        <th width="120"><b>Country</b></th>
        <th width="60"><b>Edit</b></th>
        <th width="60"><b>Delete</b></th>
    </tr>
    <c:forEach items="${listPersons}" var="person">
        <tr>
            <td>${person.id}</td>
            <td>${person.firstname}</td>
            <td>${person.lastname}</td>
            <td>${person.emailId}</td>
            <td>${person.country}</td>
            <td><a href="<c:url value='/edit/${person.id}' />" >Edit</a></td>
            <td><a href="<c:url value='/remove/${person.id}' />" >Delete</a></td>
        </tr>
    </c:forEach>
    </table>
</c:if>
</body>
</html>

Image: 在此输入图像描述 pom.xml

<properties>
        <java.version>1.7</java.version>
        <org.springframework-version>4.1.9.RELEASE</org.springframework-version>
        <org.aspectj-version>1.7.4</org.aspectj-version>
        <org.slf4j-version>1.7.5</org.slf4j-version>
        <hibernate.version>5.1.0.Final</hibernate.version>
        <validation-api.version>1.1.0.Final</validation-api.version>
        <hibernate-validator.version>5.1.1.Final</hibernate-validator.version>
        <jsoup-version>1.8.1</jsoup-version>
        <spring-data-jpa-version>1.9.2.RELEASE</spring-data-jpa-version>
    </properties>

    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>${spring-data-jpa-version}</version>
        </dependency>


        <!-- Hibernate Entity Manager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>


        <!-- Validations -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>${validation-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
        </dependency>

        <!-- Apache Commons DBCP -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- Spring ORM -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <!-- Querydsl dependencies -->
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-core</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.mysema.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>3.3.2</version>
        </dependency>

        <!-- LOG4J -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
            <scope>runtime</scope>
        </dependency>


        <!-- Needed for Hibernate Validation -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>${jsoup-version}</version>
        </dependency>

        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>jsr305</artifactId>
            <version>3.0.0</version>
        </dependency>

        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <!-- JSP API -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Junit Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
    </dependencies>

    <!-- Project Build -->
    <build>
        <finalName>spring-mvc-jpa-hibernate</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>


            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.1</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <!-- Specifies the directory in which the query types are generated -->
                            <outputDirectory>target/generated-sources</outputDirectory>
                            <!-- States that the APT code generator should look for JPA annotations -->
                            <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Define your MessageSource bean id as 'messageSource' and reference it from you validator as 'messageSource' as well.

<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <beans:property name="basenames">
       <beans:list>
            <beans:value>classpath:messages</beans:value>
            <beans:value>classpath:ValidationMessages</beans:value>
        </beans:list>        
    </beans:bean>
    <beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>

Also for Hibernate Validation you will need ValidationMessages.properties and make sure the correct key names were used. Keep in mind that external message properties need to override the defaults of the validation framework to provide custom messages. see below

ValidationMessages.properties 

# FirstName
html.validation.firstName=Invalid First Name
#length.validation.firstName=First Name should be 2 to 50 lenght in characters
Length.person.firstname=First Name should be 2 to 50 lenght in characters

# LastName
html.validation.lastName=Invalid Last Name
#length.validation.lastName=Last Name should be 2 to 50 lenght in characters
Length.person.lastname=Last Name should be 2 to 50 lenght in characters

# Country
html.validation.country=Invalid Country Name
#length.validation.country=Country Name should be 2 to 50 lenght in characters
Length.person.country=Country Name should be 2 to 50 lenght in characters

#EmailId
html.validation.emailId=Invalid Email ID
#length.validation.emailId=Email ID length should not be more than 11 characters
Length.person.emailId=Email ID length should not be more than 11 characters 
Pattern.person.emailId=Invalid Email Format

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM