0

I am running into a weird problem when rendering JSF2 (Facelet) pages. It is the usual page that receives an id via GET and displays the object. The object has a List<> inside, and the problem is that sometimes that list prints nothing and sometimes I refresh and prints the list partially (all the elements but not all the information about them). It also happens with other object's attributes (some dates). I have checked with some logging and the information is obtained correctly from the DB and the object sets the information.

I am quite sure that this is because preRenderView is done just before the render, so the bean is by chance not available when I use c:if or c:each. For the second case, perhaps ui:repeat would solve my problem?.

My questions are:

  1. How can I fix this?
  2. Is there a way in Facelets, to render f.ex. a <section> or <time> (as in my document.xhtml below) and don't print the empty tag if rendered computes to false? I know I can use c:if, but rendered is recommended in Facelets.
  3. Has the DB Javabean Document to be Named as well (besides DocumentController)?

Also, please, if there is a better way to do what I am doing (a page that receives an id via GET and displays the object), please advise. I am totally new to JSF.

Btw, I have discarded it is due to this problem.

DocumentController.java

@Named(value = "DocumentController")
@SessionScoped
public class DocumentController implements Serializable {
    private String id;
    private Document document;

    /**
     * @return the id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the Document
     */
    public Document getDocument() {
        return document;
    }

    /**
     * @param Document the Document to set
     */
    public void setDocument(Document document) {
        this.document = document;
    }


    public void load() {
        FacesContext ctx = FacesContext.getCurrentInstance();
        if (ctx.isValidationFailed()) {
            ctx.getApplication().getNavigationHandler()
                    .handleNavigation(ctx, "#{DocumentController.load}", "invalid");
            return;
        }

        try (DataStore dst = new DataStore()) {
            dst.connect();
            document = dst.getDocument(id);

        } catch (NoData | ConnectionError | IllegalArgumentException ex) {
            ctx.getApplication().getNavigationHandler()
                    .handleNavigation(ctx, "#{DocumentController.load}", "invalid");
        }
    }

}

document.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:utils="http://java.sun.com/jsf/composite/utils"
                template="template.xhtml">
    <ui:define name="content">
        <f:metadata>
            <f:viewParam name="id" value="#{documentController.id}" required="true"/>
            <f:event type="preRenderView" listener="#{documentController.load}"/>
        </f:metadata>
...
        <section rendered="#{not empty documentController.document.participants}">
            <utils:participants
                participants="#{documentController.document.participants}
                cid="example"/>
....
    </ui:define>
</ui:composition>

participants.xhtml

<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:cc="http://xmlns.jcp.org/jsf/composite"
              xmlns:c="http://java.sun.com/jsp/jstl/core"
              xmlns:ui="http://java.sun.com/jsf/facelets">
    <cc:interface>
        <cc:attribute name="participants" type="java.util.List" required="true"/>
        <cc:attribute name="cid" type="String" required="true"/>
    </cc:interface>

    <cc:implementation>
        <table>
...
            <tbody>
                <c:forEach items="#{cc.attrs.participants}" var="participant">
                    <tr>
                        <td><a href="#">#{participant.name}</a></td>
                        <td>#{participant.lastName}</td>
                        <td>#{participant.role(cc.attrs.cid)}</td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </cc:implementation>
</ui:component>
Community
  • 1
  • 1
user1156544
  • 1,725
  • 2
  • 25
  • 51
  • It seems what you want to do is use a `h:dataTable` in your composite component instead of building a table yourself. Have a look at the component. Also, for your second question, as they are standard HTML tags, you could wrap then in a `ui:fragment`, which has the `rendered` attribute too and renders no additional HTML code. – Aritz Apr 07 '16 at 06:40
  • On some elements, I would prefer to use my own HTML5 instead of depending on h:XXX. Also, this would not solve the problem since as I said, it happens with my – user1156544 Apr 07 '16 at 07:32

1 Answers1

0

1. How can I fix this?

As I suspected, this had something to do with preRenderView. Clues to find this out were that the logs showed the bean having the data, and that if I used SessionScoped, on my refresh the data appeared miraculously, but never appeared with a RequestScoped no matter how many times I refreshed - meaning that the data was indeed inside the bean, but could not be displayed at the first time. I fixed it by changing:

<f:event type="preRenderView" listener="#{documentController.load}"/>

to

<f:viewAction action="#{projectController.load}" />

See also: When to use f:viewAction / preRenderView versus PostConstruct?

I don't have an answer for (2), (3), or the best practice for what I am trying to do, but at least I wanted to write the main problem solution, in case someone needs it.

2. Apparently there is none, at least in the current JSF version. This can be done but it is not ideal:

<ui:fragment rendered="...">

3. Nop

Community
  • 1
  • 1
user1156544
  • 1,725
  • 2
  • 25
  • 51