views:

2343

answers:

3

I hope I'll be able to explain this properly. I'm developing a portlet for Liferay by using Spring. It's a pinboard system. So I have a view (Jsp) which shows the detail of a certain pinboard entry, given its id. Furthermore there is a link which goes to an AddCommentController for adding a new comment to the pinboard entry the user is currently watching at. The AddCommentController extends Spring's SimpleFormController and has also a validator attached to it:

<bean id="addCommentController" class="com.lifepin.controllers.AddCommentController" parent="lifePinControllerTemplate">
    <property name="formView" value="addComment" />
    <property name="successView" value="viewEntryDetail" />
    <property name="validator" ref="commentValidator"/>
</bean>

The validator is really simple and looks as follows:

public class CommentValidator implements Validator {

    public boolean supports(Class clazz) {
        return clazz.equals(Comment.class);
    }

    public void validate(Object obj, Errors validationError) {
        ValidationUtils.rejectIfEmptyOrWhitespace(validationError, "content", "err.content.empty", "This value is required");
    }

}

Now the view where the user can enter his comment has two buttons, Save and cancel. Here are the two generators for the according urls.

<portlet:actionURL var="actionUrl">
    <portlet:param name="action" value="addComment"/>
    <portlet:param name="pinboardEntryId" value="${param.pinboardEntryId}"/>
</portlet:actionURL>

<portlet:renderURL var="cancelUrl">
    <portlet:param name="action" value="viewPinboardEntry"/>
    <portlet:param name="pinboardEntryId" value="${param.pinboardEntryId}"/>
</portlet:renderURL>

In the onSubmitAction of the AddCommentController I read out the parameter (see the 1st actionURL above) and pass it to the ActionResponse s.t. in the detail view of the pinboard entry I can again load the entry and display it.

public class AddCommentController extends SimpleFormController{
   ...
   @Override
   protected void onSubmitAction(ActionRequest request, ActionResponse response, Object command, BindException bindException)
            throws Exception {

      long pinboardEntryId = PortletRequestUtils.getLongParameter(request, ParameterNameConstants.PINBOARDENTRY_ID, -1);
      ...
   }
   ...
}

This all works fine, except when a validation error occurs. In that case I loose the "pinboardEntryId" parameter from the URL, and I don't have any way to read that parameter in the CommentValidator to pass it to the response again since I don't have any PortletRequest or response.

For now I solved this problem by storing the id on the session and by retrieving it from there. I wanted to ask however if some of you has an alternative solution without having to use the session. I'm quite sure there is one.

Thanks,
Juri

A: 

On validation errors showForm(..) gets called again. You could overwrite this method and manipulate Request and Response as you like.

Oliver Gierke
A: 

I first tried the showForm(..) approach suggested by Oliver Gierke (thanks for the feedback) but that didn't work out as expected. The showForm(..) wants to return a new ModelAndView which I don't want to care since that should be done by the onSubmitAction(...).

The right approach is to override the

@Override
protected void processFormSubmission(ActionRequest request, ActionResponse response, Object command, BindException errors){
  ...
}

There, all the needed information is available. I can check now the BindingException whether there have been validation errors by using errors.hasErrors(). If that's the case, I can read the needed parameters and forward them to the response to have them on the form again. Otherwise I just call the onSubmitAction(..), passing the needed parameters such as the request, reponse etc.. which I have available in the processFormSubmission.

Juri
+2  A: 

An even easier solution is to set the renderParameters property. The renderParameters property is an array of parameter names that SimpleFormController will always forward. For example:

    <bean id="addCommentController" class="...">
         ....
         <property name="renderParameters">
           <list>
             <value>pinboardEntryId</value>
           </list>
         </property>
    </bean>

This will cause the 'pinboardEntryId' parameter to be passed every time without any additional code.

Ed K
cool, I already finished the project, but thx for the hint.
Juri