Search code examples
javajspliferayliferay-6

Why portlet is renderRequest.setAttribute return the last variable?


I explain my problem:

I am using Liferay 6.1 and I am trying to understand the functioning of Documents and Media control Panel.

  • In my portlet view I have a table which displays a list of documents one of these fields is the modification date. By default this date is the file modification date.

  • In the java code I need to check this date field (optional), if it is empty I keep the old code(display the modification date of the document) if it is not empty then I want to display its value instead (the value of the optional date).

  • I created a document type and I added a field in the document type called date(optional) to manually add the date.

  • One of the things I did not understand, when trying to add a field ddm-date type the date field should have a default value, it can't be empty am I wrong?

My first problem, How to set ddm-date type to empty?

  • In the creation of the field when I put None in the prefered value the CMS change it automatically to a default value and in the Form (when adding new file ) the select data of optional date doesn't contain an empty value as I see (by default it contains today's date).

  • So I used text field as type.

My main problem:

I displayed the optional date but it overwrites all creation dates. in the display I only get the optional date and the last one. I explain when I add a file from Documents and Media control Panel with the optional date field for example with the value '2012/08/01', all values in the table are replaced by this value.

I sent my variable from java code using renderRequest.setAttribute and I displayed it in my view with JSTL - Core <fmt: formatDate value = "$ {optionalDate}" pattern = "MMM yyyy" /> tag. also my portlet extends from MVCPortlet.

Why doView is render renderRequest.setAttribute return the last variable?

In my java code:

    for(DLFileEntry file : listFiles){
    try {
    Map<String, Fields> fieldsMap = file.getFieldsMap(file.getFileVersion().getFileVersionId());
         if(fieldsMap.values().size() <= 0)
            listContextFiles.remove(file);

    for (Fields fields : fieldsMap.values()) { 
    if(...){
      if(...){
      }
      else{ 
         if(fields.get("optionaldate") != null ) {
         DateFormat dateFormat1 = new SimpleDateFormat("yyyy/MM/dd");
         String _optionalDate = (String) fields.get("optionaldate").getValue();
         Date optionalDate = dateFormat1.parse(_optionalDate);
         file.setModifiedDate(optionalDate);
         renderRequest.setAttribute("optionalDate", optionalDate);
         System.out.println(file.getModifiedDate());
         listDate.add(dateFormat.format(file.getModifiedDate()));
         }
         else{
            renderRequest.setAttribute("optionalDate", file.getModifiedDate());                  
            if(!listDate.contains(dateFormat.format(file.getModifiedDate()))){
            listDate.add(dateFormat.format(file.getModifiedDate()));
            } 
         }
         //other conditions
     }
...

In my view.jsp:

<liferay-ui:search-container iteratorURL="<%=actionURL%>" delta="10"
        emptyResultsMessage="no-documents">
        <liferay-ui:search-container-results total="<%=list.size()%>"
            results="<%=ListUtil.subList(list,
                                        searchContainer.getStart(),
                                        searchContainer.getEnd())%>" />
        <liferay-ui:search-container-row modelVar="file"
            className="DLFileEntry">

            <!--other code-->

            <liferay-ui:search-container-column-text name='date'
                cssClass="txt-capitalize width-10">
                <fmt:formatDate value="${optionalDate}" pattern="MMM yyyy" />
            </liferay-ui:search-container-column-text>

            <!--other code-->

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

    </liferay-ui:search-container>

Is there a clean way to do all this?

Can someone tell me what's wrong with my code?


Solution

  • If you unwind all the loops, first in Java, then in the JSP, you're basically executing these commands (in this order), given 3 objects to be shown:

    renderRequest.setAttribute("optionalDate", someDate);
    renderRequest.setAttribute("optionalDate", someOtherDate);
    renderRequest.setAttribute("optionalDate", yetSomeOtherDate);
    

    followed by reading the value in the JSP:

    renderRequest.getAttribute("optionalDate");
    renderRequest.getAttribute("optionalDate");
    renderRequest.getAttribute("optionalDate");
    

    As setAttribute is not pushToQueue and getAttribute is not nextFromQueue (figuratively speaking), you'll only get yetSomeOtherDate for all iterations of your JSP loop, naturally.

    You can either

    • calculate the value in your JSP,
    • store an object that does the calculation for you, based on the current object,
    • store the attribute using the object's ID as part of its key, e.g. "optionalDate-" + file.getId() instead of just the generic "optionalDate". Then use the same key construction in the JSP to read the proper value. (IMHO this is quite inelegant, but might be pragmatic for your usecase)