Guyb
Guyb

Reputation: 137

Spring JSP view with 2 Forms - each form to diffrent Controller

I have JSP view and inside 2 Forms, I have 2 Controllers (1 - UserController, 2 - Home Controller)

UserController - Manage all login and regestration to the site Home Controller - Manage all the User actions

Why is that? * The home is called from UserController and the actions inside needed to sent to HomeController

Update

home.jsp -> The form that need to sign to "HomeController" * it include 2 forms (1-"scanRequest" > UserController, 2-"scanForm" > HomeController)

<form:form method="POST" action="${contextPath}/scanRequest" modelAttribute="scanForm" class="form-signin">
    <h2 class="form-signin-heading">Create new scan: </h2>
    <table>
        <tr>
            <td>
                <spring:bind path="seller_name">
                    <div class="form-group ${status.error ? 'has-error' : ''}">
                        <form:input type="text" path="seller_name" class="form-control" placeholder="Seller Name" autofocus="true"></form:input>
                        <form:errors path="seller_name"></form:errors>
                    </div>
                </spring:bind>
            </td>
            <td>
                <input type="hidden" name="scanForm" value="${UserRequestDTO}" />
                <button class="btn btn-lg btn-primary btn-block" type="submit">Scan</button>
            </td>
        </tr>
    </table>
</form:form>

<form:form method="POST" action="${contextPath}/scanTest" modelAttribute="scanTestForm" class="form-signin">
    <h3>${msg}</h3>
    <input type="hidden" name="scanTestForm" value="${UserRequestDTO}" />
    <button class="btn btn-lg btn-primary btn-block" type="submit">Test</button>
</form:form>

HomeController:

@Controller
public class HomeController {

    @ModelAttribute("scanTestForm")
    public UserRequestDTO getScanForm(){
      return new UserRequestDTO();
    }

    @RequestMapping(value = "/scanTest", method = RequestMethod.POST)
    public String scanRequest(@ModelAttribute("scanTestForm")UserRequestDTO userRequestDTO, BindingResult bindingResult, Model model) {
        String strMsg = "-----------scanTest---------- \r\n";

        if (bindingResult.hasErrors()) {

            return "home";
        }


        model.addAttribute("msg", strMsg);

        return "home";
    }
}

UserController

  @ModelAttribute("scanForm")
    public UserRequestDTO getScanForm(){
      return new UserRequestDTO();
    }


    @RequestMapping(value = "/scanRequest", method = RequestMethod.POST)
    public String scanRequest(@ModelAttribute("scanForm")UserRequestDTO userRequestDTO, BindingResult bindingResult, Model model) {
        logger.info("scanRequest():");

        String strMsg = "---------------------- \r\n" + userRequestDTO.getSeller_name() + "\r\n";

        // Checking if there is any errors with the seller
        if (bindingResult.hasErrors()) {

            return "home";
        }

        model.addAttribute("msg", strMsg);

        return "home";
    }

** I just what it to work and after that I can continue my code.. **Update: Error - when I cliced on "Test" button **

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

יול 26, 2016 2:34:44 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [searcher] in context with path [/Searcher] threw exception [An exception occurred processing JSP page /WEB-INF/views/home.jsp at line 47

44:             <table>
45:                 <tr>
46:                     <td>
47:                         <spring:bind path="seller_name">
48:                             <div class="form-group ${status.error ? 'has-error' : ''}">
49:                                 <form:input type="text" path="seller_name" class="form-control" placeholder="Seller Name" autofocus="true"></form:input>
50:                                 <form:errors path="seller_name"></form:errors>


Stacktrace:] with root cause
javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'scanForm' available as request attribute
    at org.springframework.web.servlet.tags.BindTag.doStartTagInternal(BindTag.java:120)
    at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAw

Upvotes: 0

Views: 976

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148870

After more details it is easier to understand what has happened - even if there are still dark sides like how have you first displayed home.jsp. But here we are:

  • you managed to display home.jsp (how ?)
  • you click on Test button
  • browser sends a post request to /scanTest processed by HomeController.scanRequest
  • the controller finds in Model an attribute scanTestForm built from the POSTed parameters, adds a msg attribute and forwards that to view home (I assume it is home.jsp)
  • tomcat starts home.jsp to build the response with scanTestForm and msg as request attributes - but no scanForm because the controller has not added it into the model...
  • <form:form ... modelAttribute="scanForm" ...> looks for a scanForm attribute in the request, finds none and raises an error

How to fix:

  • quick and dirty: just add model.addAttribute("scanForm", userRequestDTO); in the controller. It will be found by the JSP and should be enough to go past this error
  • more correct: instead of just forwarding to the view after the post, to a redirect to the controller that you first used to display home.jsp. This is the post-redirect-get pattern. You can even pass model attributes directly to the other controller by using redirectAttributes

But anyway, I cannot understand why you use 2 different model attribute names in the same page if they should use same value at response building time. Because the modelAttribute name is only use at that time, when the JSP build the response, and not when the browser sends back the POST request.

Upvotes: 1

Related Questions