简体   繁体   中英

HttpServletRequest losing parameters from HTML form

I'm making a locally-hosted webapp with Java, JSP, and Spring MVC. My local server is Apache/Tomcat and my IDE is NetBeans. The assignment is to make a CRUD superhero database. All my GET methods have been working fine, but it started falling apart when I started implementing POST methods.

Front end:

<form class="form" role="form" method="POST" action="addHeroToDB">
  <div class="form-group row">
    <label for="name" class="col-3 col-form-label">
      Name:
    </label>
    <div class="col-6">
      <input type="text" class="form-control" name="name" required></input>
    </div>
  </div>
  <div class="form-group row">
    <label for="description" class="col-3 col-form-label">
      Description:
    </label>
    <div class="col-6">
      <textarea class="form-control" name="description" required></textarea>
    </div>
  </div>
  <div class="form-group row">
    <label for="powers" class="col-3 col-form-label">
      Known Superpowers:
      <p><span style="font-size:.75em">Select multiple options by holding Control or Command.</span></p>
    </label>
    <div class="col-6">
      <select multiple class="form-control" name="powers">
        <c:forEach var="power" items="${powers}">
          <option value="${power.powerID}">
            <c:out value="${power.name}" />
          </option>
        </c:forEach>
        <option>Other/None</option>
      </select>
    </div>
  </div>
  <div class="form-group row">
    <label for="orgs" class="col-3 col-form-label">
      Organizations:
      <p><span style="font-size:.75em">Select multiple options by holding Control or Command.</span></p>
    </label>
    <div class="col-6">
      <select multiple class="form-control" name="orgs">
        <c:forEach var="org" items="${orgs}">
          <option value="${org.orgID}">
            <c:out value="${org.name}" />
          </option>
        </c:forEach>
        <option>Other/None</option>
      </select>
    </div>
  </div>
  <p>(Don't see a specific superpower or organization listed? Add it to our <a href="showSuperpowerDatabase">superpower database</a> or <a href="showOrganizationDatabase">organization database</a>!)</p>
  <div class="form-group row">
    <input type="submit" id="saveHero" class="btn btn-primary col" style="margin:5px" value="Save" />
    <a href="showHeroDatabase" role="button" id="cancel" class="btn btn-primary col" style="margin:5px">
      Cancel
    </a>
    <div class="col-md-9"></div>
  </div>
</form>

Back end:

@RequestMapping(value = "/addHeroToDB", method=RequestMethod.POST)
  public String addHero(HttpServletRequest request) {
    Hero hero = new Hero();
    hero.setName(request.getParameter("name"));
    hero.setDescription(request.getParameter("description"));
        
    List<Superpower> powers = new ArrayList<>();
    for (String idString : request.getParameterValues("powers")) {
      int powerID = Integer.parseInt(idString);
      Superpower power = dao.getSuperpowerByID(powerID);
      powers.add(power);
    }
    hero.setPowers(powers);
        
    List<Organization> orgs = new ArrayList<>();
    for (String idString : request.getParameterValues("orgs")) {
      int orgID = Integer.parseInt(idString);
      Organization org = dao.getOrganizationByID(orgID);
      orgs.add(org);
    }
    hero.setOrgs(orgs);
        
    dao.addHero(hero);
    return "redirect:showHeroDatabase";
  }

Every time I test filling out and submitting the form, the app crashes from a NullPointerException because the request doesn't have any parameters on it. When I ran the debugger, it showed the CoyoteRequest variable as the place where the parameters come from, and all of the parameter maps were size 0.

What puzzles me most is that the tutorial project from the course doesn't have this problem. Submitting the forms doesn't cause any exceptions, and the debugger showed the parameters going through on the request.

Front end:

<form role="form" method="POST" action="createContact">
  <div class="form-group row">
    <label for="add-first-name" class="col-md-4 col-form-label">First Name:</label>
    <div class="col-md-8">
      <input type="text" class="form-control" name="firstName" placeholder="First Name"/>
    </div>
  </div>
  <div class="form-group row">
    <label for="add-last-name" class="col-md-4 col-form-label">Last Name:</label>
    <div class="col-md-8">
      <input type="text" class="form-control" name="lastName" placeholder="Last Name"/>
    </div>
  </div>
  <div class="form-group row">
    <label for="add-company" class="col-md-4 col-form-label">Company:</label>
    <div class="col-md-8">
      <input type="text" class="form-control" name="company" placeholder="Company"/>
    </div>
  </div>
  <div class="form-group row">
    <label for="add-email" class="col-md-4 col-form-label">Email:</label>
    <div class="col-md-8">
      <input type="email" class="form-control" name="email" placeholder="Email"/>
    </div>
  </div>
  <div class="form-group row">
    <label for="add-phone" class="col-md-4 col-form-label">Phone:</label>
    <div class="col-md-8">
      <input type="tel" class="form-control" name="phone" placeholder="Phone"/>
    </div>
  </div>
  <div class="form-group row">
    <div class="offset-md-4 col-md-8">
      <input type="submit" class="btn btn-primary" value="Create Contact"/>
    </div>
  </div>
</form>

Back end:

@RequestMapping(value = "/createContact", method=RequestMethod.POST)
  public String createContact(HttpServletRequest request) {
    Contact contact = new Contact();
    contact.setFirstName(request.getParameter("firstName"));
    contact.setLastName(request.getParameter("lastName"));
    contact.setCompany(request.getParameter("company"));
    contact.setPhone(request.getParameter("phone"));
    contact.setEmail(request.getParameter("email"));
    dao.addContact(contact);
        
    return "redirect:displayContactsPage";
  }

I've looked all around the code, the pom/web.xml/other meta files, the application context, etc. and I can't find any reason why the contact form works perfectly but the superhero one doesn't. What have I missed? Can anyone help me out?

EDIT: Here's my web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
         id="WebApp_ID" version="2.5">
  <display-name>Archetype Created Spring MVC Web Application</display-name>
<!--Commented out to enable homepage functionality!
  <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      <welcome-file>index.htm</welcome-file>
      <welcome-file>index.jsp</welcome-file>
      <welcome-file>default.html</welcome-file>
      <welcome-file>default.htm</welcome-file>
      <welcome-file>default.jsp</welcome-file>
  </welcome-file-list> -->
  <servlet>
    <servlet-name>spring-dispatcher</servlet-name>            
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.eot</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.svg</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.ttf</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.woff</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.woff2</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.gif</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring-dispatcher-servlet.xml
        classpath:spring-persistence.xml
    </param-value>
  </context-param>
  <listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>
</web-app>

UPDATE: Further experiments have shown that this is only a problem with forms and POST endpoints. Request parameters added directly to the URL have been going through fine. Because the tutorial project did not have this problem, I'd still like to find a real solution rather than use a clunky workaround (like changing the submit button to a URL).

I found the issue, and it wasn't in the request itself.

I didn't have a way to handle the request.getParameterValues() arrays being null. For some reason, that stopped any values from coming through on the request body. Once I added an if statement to handle a null-value array, the code worked.

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