Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting SearchContainer in portlet to use it in JSP using EL and JSTL

I am trying to use SearchContainer in my liferay application. Currently I've to use JSP Scriplets to set the results in <liferay-ui:search-container-results> tags. This is the snippet so far:

<liferay-ui:search-container emptyResultsMessage="there-are-no-courses" delta="5">
    <liferay-ui:search-container-results>
        <%
            List<Course> tempResults = ActionUtil.getCourses(renderRequest);

            results = ListUtil.subList(tempResults, 
                                   searchContainer.getStart(), 
                                   searchContainer.getEnd());

            total = tempResults.size();
            pageContext.setAttribute("results", results);
            pageContext.setAttribute("total", total);
        %>
    </liferay-ui:search-container-results>

    <liferay-ui:search-container-row ...></liferay-ui:search-container-row>

    <liferay-ui:search-iterator />

</liferay-ui:search-container>

Now, I would like to change those scriplets to EL. I found one post regarding the same issue, but that is using Spring MVC. And I've no idea where to write the below line as given in the answer to that question, in portlets:

SearchContainer<Book> searchContainer = new SearchContainer<Book>(renderRequest, renderResponse.createRenderURL(), null, "there are no books");

In can't write it in my portlet action, as the parameter in my action is ActionRequest and ActionResponse, which does not define the method createRenderURL(). How would I get the PortletURL?

Where should I write the above statement? Currently I'm writing in the same action from where I'm returning to this page. Am I doing it right? Here's the action that I'm firing from the same page, as the search-container is in:

public void addCourse(ActionRequest request, ActionResponse response) 
        throws Exception {

    ThemeDisplay themeDisplay = 
            (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    Course course = ActionUtil.courseFromRequest(request);

    List<String> errors = new ArrayList<String>();

    if (CourseRegValidator.validateCourse(course, errors)) {
        CourseLocalServiceUtil.addCourse(course, themeDisplay.getUserId());
        SessionMessages.add(request, "course-added-successfully");

        // I thought I might put it here.
        // But I don't know what to pass as `PortletURL` in constructor of SearchContainer
    } else {
        SessionErrors.add(request, "fields-required");
    }
}

I want that, everytime a Course is added, it is rendered in my search container, on the same page from where I'm firing the addCourse action.

And yes, my portlet extends MVCPortlet.


UPDATE:

Ok, I figured out a few part.

  • For the first time when portlet is loaded, I can override the doView method in my portlet, and then add the SearchContainer in renderRequest there, as I've access to it in doView.
  • But again, when I go on to editCourse() action, where I'am doing a response.setRenderParameter(), to send it to another jsp page. And in that JSP page, I'm firing an updateCourse() action.
  • Now, from updateCourse() action, I'm again using response.setRenderParameter() to send it to the original JSP page, where I'm using Search Container. But now, since it is not going through doView() method, I can't create the SearchContainer and add it to request.

So, is there any work-around here? How to make sure that the attribute I set in renderRequest in doView method is available in updateCourse method? I know that doesn't sound practical, as it is completely a new request, but is there any other way?

One work-around I can think of is to set the attribute in larger scope, like session or context instead of renderRequest. But, I won't need that attribute anywhere else. So, I don't think that would be appropriate.

Any inputs?


Update 2:

Just now, I used:

actionResponse.setPortletMode(PortletMode.VIEW);

in place of:

actionResponse.setRenderParameter("jspPage", jspPage);

And it worked, as it now goes through doView() method. Just wanted to ask, is this the appropriate way? What's the difference between two methods when we are setting render parameter to the same JSP page, where doView methods redirects?


My Current doView method looks like:

@Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) 
        throws IOException, PortletException {

    SearchContainer<Course> searchContainer = 
            new SearchContainer<Course>(renderRequest, renderResponse.createRenderURL(), null, "there-are-no-courses");

    searchContainer.setDelta(5);
    List<Course> tempResults = ActionUtil.getCourses(renderRequest);

    List<Course> results = ListUtil.subList(tempResults, 
                                    searchContainer.getStart(), 
                                    searchContainer.getEnd());

    searchContainer.setTotal(tempResults.size());
    searchContainer.setResults(results);

    renderRequest.setAttribute("searchContainer", searchContainer);
    super.doView(renderRequest, renderResponse);
}
like image 897
Rohit Jain Avatar asked Jul 29 '13 11:07

Rohit Jain


1 Answers

Converting comments to answer:

  1. Whenever you render a portlet it is rendered through the doView method and not directly through the action methods as part of the portlet life-cycle.
  2. the results and total set as renderRequest.setAttribute("searchResults", courses) and renderRequest.setAttribute("searchTotal", total) in doView will be available in the view.jsp as ${searchResults} and ${searchTotal}.
  3. Everytime you perform any action the doView will be called after that and the searchResults and searchTotal will be set again and will be shown.
  4. or you can just set the searchContainer in the doView method itself as explained in the answer which you had linked in your question.
like image 128
Prakash K Avatar answered Nov 15 '22 01:11

Prakash K