Search code examples
htmlspring-mvcmodel-view-controllercontrollerspring-web

Form not posting values, 'browser edit and resend' is working


I am using Spring mvc web to submit a form. Form is rendering fine however when I am submitting this form, I am getting http status code 400, however if I use 'edit and resend' function of firefox, it is hitting corresponding controller method (which doesn't happen when I submit this form from html). But again there is another issue, within that controller method when I inspect my modelAttribute object, I find everything in this object as null. Which is not the case as I am submitting values within this form.

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
    <%@ include file="include.jsp"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>${message}</title>
    </head>
    <body>
        General:
<br>
<form:form modelAttribute="initialMatchConfiguration" action="../match/configure" method="post" >
    Date and time:
    <form:input path="dateAndTimeOfMatch" type="text" />
    <br> Match Type:
    <form:select path="matchType">
        <option value="friendly">friendly</option>
        <option value="international">international</option>
        <option value="domestic">domestic</option>
        <option value="local">local tournament</option>
    </form:select>
    <br> Match Rules Configuration:
    <form:select path="matchConfigurationId">
        <option value="0">Random</option>
        <option value="1">T20</option>
        <option value="2">One Day</option>
        <option value="3">Test</option>
    </form:select>
    <button type="button">Create a new rule configuration</button>
    <br> Tournament:
    <form:input type="text" path="tournament" />
    <form:hidden path="tournamentId"/>
    <button type="button">Create a new Tournament</button>
    <br> Played at Stadium:
    <form:input type="text" path="stadium" />
    <form:hidden path="stadiumId"/>
    <button type="button">Create a new stadium</button>
    <br> <input type="submit" value="Save" />
</form:form>
    </body>
    </html>

Following method is to render form:

    @RequestMapping(value = "/match/create", method = RequestMethod.GET)
public String  createMatch(Model model){
    model.addAttribute("initialMatchConfiguration", new InitialMatchConfiguration());
    return "config-match-initial";
}

Following method is to submit the form:

@RequestMapping(value = "/match/configure", method = RequestMethod.POST)
public String  configureMatch(@ModelAttribute("initialMatchConfiguration") InitialMatchConfiguration initialMatchConfig, Model model){
    System.out.println(initialMatchConfig);
    return "config-match-team";
} 

InitialMatchConfiguration class

public class InitialMatchConfiguration {
private Date dateAndTimeOfMatch;
private String matchType;
private Long matchConfigurationId;
private Long tournamentId;
private Long stadiumId;
private String tournament;
private String stadium;
public Date getDateAndTimeOfMatch() {
    return dateAndTimeOfMatch;
}
public void setDateAndTimeOfMatch(Date dateAndTimeOfMatch) {
    this.dateAndTimeOfMatch = dateAndTimeOfMatch;
}
public String getMatchType() {
    return matchType;
}
public void setMatchType(String matchType) {
    this.matchType = matchType;
}
public Long getMatchConfigurationId() {
    return matchConfigurationId;
}
public void setMatchConfigurationId(Long matchConfigurationId) {
    this.matchConfigurationId = matchConfigurationId;
}
public Long getTournamentId() {
    return tournamentId;
}
public void setTournamentId(Long tournamentId) {
    this.tournamentId = tournamentId;
}
public Long getStadiumId() {
    return stadiumId;
}
public void setStadiumId(Long stadiumId) {
    this.stadiumId = stadiumId;
}
public String getTournament() {
    return tournament;
}
public void setTournament(String tournament) {
    this.tournament = tournament;
}
public String getStadium() {
    return stadium;
}
public void setStadium(String stadium) {
    this.stadium = stadium;
}

}

Request when fired from firefox edit and resend tool:

Request Header:

POST http://localhost:8090/scoreboard.web/score/match/configure

Host: localhost:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101    Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8090/scoreboard.web/score/match/create
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

Request Body:

Content-Type: application/x-www-form-urlencoded
Content-Length: 107

dateAndTimeOfMatch=&matchType=friendly&matchConfigurationId=0&tournament=&tournamentId=&stadium=&stadiumId=

Solution

  • ROOT CAUSE: change the type of dateAndTimeOfMatch from text to date

    and in FORM class:

        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
        private Date dateAndTimeOfMatch;
    

    Form :

     <form:form modelAttribute="initialMatchConfiguration" action="../match/configure" method="post" >
    Date and time:
    <form:input path="dateAndTimeOfMatch" type="date" />
    <br> Match Type:
    <form:select path="matchType">
        <option value="friendly">friendly</option>
        <option value="international">international</option>
        <option value="domestic">domestic</option>
        <option value="local">local tournament</option>
    </form:select>
    <br> Match Rules Configuration:
    <form:select path="matchConfigurationId">
        <option value="0">Random</option>
        <option value="1">T20</option>
        <option value="2">One Day</option>
        <option value="3">Test</option>
    </form:select>
    <button type="button">Create a new rule configuration</button>
    <br> Tournament:
    <form:input type="text" path="tournament" />
    <form:hidden path="tournamentId"/>
    <button type="button">Create a new Tournament</button>
    <br> Played at Stadium:
    <form:input type="text" path="stadium" />
    <form:hidden path="stadiumId"/>
    <button type="button">Create a new stadium</button>
    <br> <input type="submit" value="Save" />
    

    InitialMatchConfiguration.java:

     public class InitialMatchConfiguration {
    
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private Date dateAndTimeOfMatch;
    private String matchType;
    private Long matchConfigurationId;  
    private Long tournamentId;
    private Long stadiumId;
    private String tournament;
    private String stadium;
    
     //getters and setters
    
    }
    

    Controller:

    @RequestMapping(value = "/match/configure", method = RequestMethod.POST)
        public String  configureMatch(@ModelAttribute("initialMatchConfiguration") InitialMatchConfiguration initialMatchConfig, Model model){
            System.out.println(initialMatchConfig.toString());
    
            return "config-match-team";
        } 
    

    Response:

    ** InitialMatchConfiguration [dateAndTimeOfMatch=Tue Jan 10 05:30:00 IST 2017, matchType=international, matchConfigurationId=2, tournamentId=null, stadiumId=null, tournament=sa, stadium=]**