New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document the use of ParameterMappingInterceptor for typical Portlet MVC setup [SPR-3162] #7848
Comments
Juergen Hoeller commented Note that the "showForm" call happens in SimpleFormController's "renderFormSubmission" method, not in "processFormSubmission", due to the separate action/render phases in a Portlet environment. This does work in our test cases, so it doesn't seem that there's a general problem in SimpleFormController's workflow. Can you please double-check the behavior that you get, and post the relevant parts of your configuration? Juergen |
Jonathan van Alteren commented Hi Juergen, First of all, thanks for your fast response to my issue. You are correct, I did not notice the 'showForm' call in the 'renderFormSubmission' method. However, it turns out that the 'renderFormSubmission' method on my form controller is never called after submission of the form. Instead, the render phase (after the form submission action) is handled by my basic default controller that just forwards to the 'home' view. After debugging, it seems that the flow is:
At step 7, the parameter 'action' with value 'registerUser' is not passed to the render request. This results in the default controller being invoked, instead of returning to the form view with errors. The javadoc description of the 'passRenderParameters' method is: 'Pass the specified list of action request parameters to the render phase by putting them into the action response object. This may not be called when... ' Can I conclude that the implementation of this method in the AbstractFormController is incorrect? For completeness, I will attach my 'selfcare-portlet.xml' and 'applicationContext.xml' configurations. Kind regards, |
Jonathan van Alteren commented DispatcherPortlet configuration |
Jonathan van Alteren commented Application context configuration |
Jonathan van Alteren commented PS Please remove attachment #3 (selfcare-portlet.xml 06:13 AM) |
Jonathan van Alteren commented Any progress on this issue? Jonathan |
Chris Elgar commented "Pass the specified list of action request parameters to the render phase by putting them into the action response object." You need to specify the list of parameters to pass to the next phase by setting the renderParameters property. See the setRenderParameters method in AbstractFormController, and also the exposed configuration properties section of the class level javadoc for details. Hopefully, by specifying "action" as one of the parameters to be passed this will resolve your issue. |
Jonathan van Alteren commented Thank you Chris, this does resolve the immediate problem. In my opinion however, this should not be necessary. Without specifying the 'action' parameter, the form functionality does not work. Both the Spring Portlet MVC reference and the wiki do not mention the 'renderParameters' property. Also, the Spring Portlet sample provided by the wiki does not use the 'renderParameters' property. Shouldn't the 'action' parameter always be passed to the render phase, regardless of the 'renderParameters' property? |
Chris Elgar commented I am fairly new to the framework and at first I agreed with your comment. But when I thought about it, the only reason that the action parameter needs to be mapped is you have multiple controllers backing your portlet. So this is actually a handler mapping issue instead of a controller issue. The class org.springframework.web.portlet.handler.ParameterMappingInterceptor is probably the intended method of solving this issue when using multiple controllers in this fashion (or alternatively the solution I suggested above if redirects are required - the javadoc for the ParameterMappingInterceptor explains this). See http://static.springframework.org/spring/docs/2.0.x/reference/portlet.html#portlet-handlermapping for the explanation on use of different handler mappings. Section 16.5.6 explains the use of the ParameterMappingInterceptor to ensure that the same controller handles the action and render phases. Hope this helps. Chris. |
Chris Elgar commented BTW - the sample application available from http://opensource.atlassian.com/confluence/spring/display/JSR168/Home has a books example that uses this approach. The relevant section of the config to declare and use the ParameterMappingInterceptor is: <bean id="parameterMappingInterceptor" class="org.springframework.web.portlet.handler.ParameterMappingInterceptor"/>
|
Jonathan van Alteren commented Thank you Chris! That did the job. As you might have guessed, I'm also new to the framework and I missed the importance of that section in the reference manual. For every portlet that uses more than 1 controller, this part of the configuration is absolutely vital to get the framework working (IMHO). To help other (new) users of the Portlet MVC framework, I'd like to suggest to add another configuration example to (or after) section 16.5.6 that demonstrates the combined use of the portlet mode and portlet mode parameter handler mappings, together with the parameter mapping interceptor:
I guess this issue can be closed. Thanks for your help! |
Jonathan van Alteren commented By the way... I agree with you on it being a handler mapping issue instead of a controller issue ;-) |
Jani Kaarela commented I think this "feature" is badly enough documented to be called a bug. The section 16.5.2 "ParameterHandlerMapping" should clearly point out the need for ParameterMappingInterceptor. Or, in order to be more intuitive: 1) the whole notion of one portlet -> multiple handlers should be discouraged and the specific steps needed to enable it well documented, or 2) calling passRenderParameters() should by default be called automatically, regardless of the outcome of the earlier processing stages. Personally, I found it puzzling that processFormSubmission() doesn't call passRenderParameters() in the typical case (ie. no errors, not a form change request). Without digging into the issue, it seemed unintuitive that in some cases it's called and in some not. The behaviour is not obvious and should thus be reconsidered or at least much, much more clearly documented. |
Juergen Hoeller commented I'm considering this issue as invalid in the meantime, since the entire form controller hierarchy has been deprecated as of 3.0 and has been removed for 4.0. That said, we do plan to revisit our Portlet support in 4.1, so there's an opportunity for new, up-to-date issues to be considered rather immediately. Juergen |
Jonathan van Alteren opened SPR-3162 and commented
I'm evaluating Portlet MVC for use in WebSphere Portal 5.1 JSR-168 portlets.
I have created a simple form controller that processes a very simple command class. I have configured it to use a validator and I have set the 'formView' and 'successView' properties. Furthermore, I have configured an internal resource view resolver in a separate applicationContext.xml file.
I am able to navigate the portlet to get to the form, so I guess the formView works for that part. If I enter faulty data in my form I can see in the logs that validation errors occur. However, I am returned to the 'home' view (which is where I started from) instead of going back the formView. I need to be able to show the errors to the user and allow him to resubmit the form (as you would expect).
Am I doing something wrong here? I looked at the code in SimpleFormController (in the ...web.portlet.mvc package) and unlike the non-portlet variety, it does not call showForm(..) (see below).
I can't find anything about this in the docs. Please help!
----------- excerpt from org.springframework.web.portlet.mvc.SimpleFormController.java:
...
protected void processFormSubmission(
ActionRequest request, ActionResponse response, Object command, BindException errors)
throws Exception {
...
Affects: 2.0.2
Attachments:
1 votes, 4 watchers
The text was updated successfully, but these errors were encountered: