Announcement Announcement Module
Collapse
No announcement yet.
Post data not received Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Post data not received

    Hi,

    I am submitting a HTML form:
    Code:
    <form method="post" action="signIn2.htm">
      <input name="email" type="text" maxlength="255" id="emailId"/>
      <input name="pass" type="password" maxlength="50" id="passId"/>
      <input type="submit" value="Signin"/>">
    </form>
    When I look in the handleRequest method in the SigninController, I don't get anything in the request parameterMap.
    Are my expectations wrong? How do I go about sending post data to a controller without using the command object?!

    What I want to do is have a login form in the menu part of a web page. Now, the body part of the web page could contain another form or just present data (no form). Because of this, I can't form a command object for the login form in the menu.

    I actually have a signin view (body part) and an appropriate SimpleFormController. Eventually I want the login form data from the menu to be sent to this controller and validated by it's Validator, but I can't see the post data when debugging in the controller.

    I tried creating a command object with the same name ('signin') from the HomeController (home page):
    Code:
    UserCredentials userCredentials = new UserCredentials();
    userCredentials.setEmail("");
    userCredentials.setPassword("");
    myModel.put("signin", userCredentials);
    return new ModelAndView("home", "model", myModel);
    but when I use this:
    Code:
    <form:form method="post" action="signIn.htm" modelAttribute="model.signin"> <%--commandName="model.signin" modelAttribute="${model.signin}" --%>
    even though I can see the model.signin object in the jsp, I get this error:
    org.springframework.beans.NotReadablePropertyExcep tion: Invalid property 'signin' of bean class [java.util.HashMap]: Bean property 'signin' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    Can anyone tell me some way I could make this work?

    Kind Regards,
    Despot

  • #2
    use the commandName attribute in your form:form tag instead of modelAttribute and action.

    Follow this simple tutorial.

    Comment


    • #3
      It is not a trivial case

      Thank you Enrico for replying!

      The tutorial that you sent me is for trivial cases. I have already done this without the annotations. Using annotations is only a preference. We agree on this, right?

      I see that I wasn't clear before. I need to implement a functionality like in this web site. Do you see the Login form in the menu part? Now, if you browse through the web site, you will see that the body part is always different. For more clarity I am providing the tiles-defs.xml:
      Code:
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE tiles-definitions PUBLIC
             "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
             "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
      
      <tiles-definitions>
      
      	<!-- GENERAL DEFINITIONS BEGIN -->
      	<!-- Abstract definition -->
      	<definition name="abstractTemplate" template="/WEB-INF/tiles/basicTemplate.jsp">
      		<put-attribute name="headTile" value="/WEB-INF/tiles/headTile.jsp" />
      		<put-attribute name="headerTile" value="/WEB-INF/tiles/headerTile.jsp" />
      		<put-attribute name="menuTile" value="/WEB-INF/tiles/menuTile.jsp"/>
      		<put-attribute name="loginTile" value="/WEB-INF/tiles/loginTile.jsp"/>
              <put-attribute name="footerTile" value="/WEB-INF/tiles/footerTile.jsp" />
      		<put-attribute name="scriptTile" value="/WEB-INF/jsp/empty.jsp" />
      	</definition>
      	<!-- GENERAL DEFINITIONS END -->
      	
      	<!-- MOST COMMON TEMPLATE DEFINITIONS BEGIN -->
      	<!-- Definition extension - This template will be used for most of the pages. -->
      	<definition name="basicTemplate" extends="abstractTemplate">
      		<put-attribute name="contentTile" value="/WEB-INF/tiles/contentTileAbstract.jsp"/>
          </definition>
          <!-- MOST COMMON TEMPLATE DEFINITIONS END -->
          
          <!-- COMMON DEFINITIONS BEGIN -->
          <definition name="home" extends="basicTemplate">
              <put-attribute name="contentTile" value="/WEB-INF/jsp/home.jsp"/>
          </definition>
      
      </tiles-definitions>
      and the basicTemplate.jsp:
      Code:
      <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
         "http://www.w3.org/TR/html4/loose.dtd">
      
      <html>
      <head>
      <tiles:insertAttribute name="headTile" />
      </head>
      <body>
      <table border="1" cellpadding="2" cellspacing="2" align="center">
      	<tr>
      		<td colspan="2" align="center"><tiles:insertAttribute name="headerTile" /></td>
      	</tr>
      	<tr>
      		<td valign="top">
      			<tiles:insertAttribute name="menuTile" />
      			<br>
      			<tiles:insertAttribute name="loginTile" />
      		</td>
      		<td>
      			<tiles:insertAttribute name="contentTile" />
      		</td>
      	</tr>
      	<tr>
      		<td colspan="2" align="center"><tiles:insertAttribute name="footerTile" /></td>
      	</tr>
      </table>
      </body>
      <tiles:insertAttribute name="scriptTile" />
      </html>
      One type of body would be one that doesn't have any form. For example the body part home.jsp:
      Code:
      <%@ include file="/WEB-INF/jsp/includeHeader.jsp"%>
      
      <c:set var="contextPath" value="${pageContext.request.contextPath}"/>
      <c:set var="imagesPath" value="${contextPath}/images"/>
      
      <table>
      	<c:forEach var="product" items="${model.products}" varStatus="itemsRow">
      		<c:if test="${(itemsRow.index + 1) mod 3 == 1 && (itemsRow.index + 1) != 1}">
      		</tr>
      		</c:if>
      		<c:if test="${(itemsRow.index + 1) mod 3 == 1}">
      		<tr>
      		</c:if>
      			<td>
      				<table>
      					<tr>
      						<td>
      							<a href="<c:url value="detail.htm?product=${product.id}"/>">
      								<img class="product-thumb" src="${imagesPath}/${product.imageUrl}" alt="${product.description}" />
      							</a>
      						</td>
      					</tr>
      				<tr>
              				<td>
              					<div style="text-align:left">
              						<a href="<c:url value="detail.htm?product=${product.id}"/>">
      									<c:out value="${product.priceInDollars}"></c:out>
      								</a> 
              					</div>
              				</td>
      					</tr>
      				</table>
      			</td>
      	</c:forEach>
      	</tr>
      </table>
      <br>
      The HomeController.java:
      Code:
      package home;
      
      public class HomeController implements Controller {
      
         public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                      //...bunch of other stuff...
      		Map<String, Object> myModel = new HashMap<String, Object>();
                      //...bunch of other stuff...
      		myModel.put("products", products);
      		return new ModelAndView("home", "model", myModel);
         }
      }
      Another type of body would be one that has a form. For example the body part registerView.jsp:
      Code:
      <form:form method="post" commandName="orderBackingObject">
      <table>
      <tbody>
      <tr>
       <td>
         <label id="labelLastNameId"><fmt:message key="orderBackingObject.user.addressLastName" />:</label>
       </td>
       <td>
         <span>*</span>
       </td>
       <td>
         <form:input path="user.shippingAddress.addressLastName"  id="shippingAddress_lastNameId" maxlength="50"/>
         <span id="spanLastNameId">*</span>
       </td>
      </tr>
      </tbody>
      </table>
      </form:form>
      RegisterFormController.java:
      Code:
      public class RegisterFormController extends SimpleFormController {
      
      	protected Object formBackingObject(HttpServletRequest request)
      	throws ServletException {
                      //...other stuff...
      		OrderBackingObject orderBackingObject = new OrderBackingObject(user, null, 1, false, null, new Date(), -1, null, registrationService.getCountries(), "");
                      return orderBackingObject;
      	}
      
      	public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws ServletException {
                      //..take the orderBackingObject and do something with it!...
      		return new ModelAndView(getSuccessView());
      	}
      
      }
      Now imagine that you have many pages with the first type of body and with the second type. This suggests that creating a Backing Object (or command object) for every page for the login menu part is not possible. I would have to make the controllers of all pages with the first type of body extend some of the implementations of CommandController (example: SimpleFormController), just so I can provide a command object for the menu login form. And on the other side, I would have to make the controllers of all pages with the second type of body return a command object that will hold a property that I will use as the object for the menu login form. I think that this is too much refactoring for just one form. That is why I thought that I should send the post data from the menu login form without using a command object. Actually my idea was to send the post data to the controller that manages the login page (the page with body that holds a login form).
      The body of the login page (signInFormView.jsp):
      Code:
      <%@ include file="/WEB-INF/jsp/includeHeader.jsp"%>
      <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
      <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
      
      <h1><fmt:message key="signin.heading" /></h1>
      <form:form method="post" commandName="signin">
      	<table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
      		cellpadding="5">
      		<tr>
      			<td>
      				<spring:bind path="signin.*">
      					<c:if test="${not empty status.errorMessages}">
                      		<c:forEach items="${status.errorMessages}" var="error">
                             		<c:out value="${error}"/><br/>
                             </c:forEach>
                     		</c:if>
                     	</spring:bind>
      			</td>
      		</tr>
      		<tr>
      			<td align="right" width="20%"><fmt:message key="signin.emailAddress" />:</td>
      			<td width="20%"><form:input path="email" /></td>
      			<td width="60%"><form:errors path="email" cssClass="error" />
      			</td>
      		</tr>
      		<tr>
      			<td align="right" width="20%"><fmt:message key="signin.password" />:</td>
      			<td width="20%"><form:password path="password" /></td>
      			<td width="60%"><form:errors path="password" cssClass="error" />
      			</td>
      		</tr>
      	</table>
      	<br>
      	<input type="submit" align="middle" value="Execute">
      </form:form>
      The SignInFormController.java:
      Code:
      public class SignInFormController extends SimpleFormController {
      
      	protected Object formBackingObject(HttpServletRequest request)
      	throws ServletException {
      		//WHEN SETTING UP A BREAKPOINT HERE I CANNOT SEE THE POST DATA FROM THE MENU LOGIN FORM! WHY?!?!?!
      		UserCredentials userCredentials = new UserCredentials();
      		userCredentials.setEmail("");
      		userCredentials.setPassword("");
      		return userCredentials;
      	}
      
      	public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
      		UserCredentials userCredentials = ((UserCredentials) command);
      		//...do something with the command object here...
      		return new ModelAndView(getSuccessView());
      	}
      
      }
      First I would have to find a way to notify the controller that instead of going to formBackingObject, he should validate the data sent and call the onSubmit method if everything is ok. Either way when I set a breakpoint in the formBackingObject method of this controller, I see no post data, no data in the parameterMap. So that is why I asked "How do I go about sending post data to a controller without using the command object?!".

      Or if anyone has a better idea of how I could incorporate the menu login part, than please speak freely!

      Kind Regards,
      Despot

      Comment


      • #4
        One more tiny problem left! (Solved the communication)

        Hi again,

        first of all, I want to clarify why I wasn't getting any parameters (post data) when debugging. Apparently, when debugging with Eclipse the parameterMap is empty until you do a
        Code:
        request.getParameterMap();
        .

        The way that I solved the problem with the commandName is by inserting an object with the email and password properties, into the request through an interceptor. So whenever I need this login form in the menu, I have to create this object and expose it in the request:
        Code:
        public void postHandle(HttpServletRequest request,
        	HttpServletResponse response, Object handler,
        	ModelAndView modelAndView) throws Exception {
        	//...other stuff...
        	Map<String, Object> attributes = new HashMap<String, Object>();
        	attributes.put("signin", userCredentials);
        	WebUtils.exposeRequestAttributes(request, attributes);
        }
        When I send the post data from the login menu form to the controller SignInFormController (that manages the url from the action attribute in the form), the behavior is the following:
        - first enters the formBackingObject and creates a new "signin" command object although one already exists;
        - than enters the validator and if all is fine, enteres the onSubmit method.
        So I achieved what I want.

        I am only left with one more variation of the original question regarding the post data! When I am sending post data through http but requesting a secure resource from the server (the server returns the appropriate resource through https), I don't see the post data in the controller. On the other hand if I send the same post data through https, and request the same secure resource (on https), I see the post data in the same controller. So can anyone please explain me why is this the case? And how can I make the server show me that data if I wan't to process it?

        The concrete case is that the menu login form is sometimes on an unsecure page (http). When I send the post data to the SignInFormController (which in turn has its url secured with https), I cannot see it. So when the user types his email and/or password (when the login menu form is placed in an unsecured page), when the login page is loaded the field for the email is left blank.

        Kind Regards,
        Despot

        Comment

        Working...
        X