2016-04-06 24 views
0

Ich habe ein seltsames Problem beim Rendern von JSF2 (Facelet) Seiten. Es ist die übliche Seite, die eine id über GET empfängt und das Objekt anzeigt. Das Objekt hat eine Liste <> im Inneren, und das Problem ist, dass manchmal diese Liste nichts druckt und manchmal ich refresh und druckt die Liste teilweise (alle Elemente, aber nicht alle Informationen über sie). Es passiert auch mit anderen Objektattributen (einige Daten). Ich habe mit etwas Protokollierung überprüft und die Informationen sind korrekt aus der DB und dem Objekt set s die Informationen erhalten.Einige Daten von JSF2 Bean aus der Datenbank zur Renderzeit nicht verfügbar

Ich bin mir ziemlich sicher, dass dies ist, weil preRenderView kurz vor dem Rendern erfolgt, so dass die Bohne zufällig nicht verfügbar ist, wenn ich c:if oder c:each verwende. Für den zweiten Fall, vielleicht ui:repeatwould solve my problem?.

Meine Fragen sind:

  1. Wie kann ich dieses Problem beheben?
  2. Gibt es einen Weg in Facelets, um zB zu rendern. a <section> oder <time> (wie in meinem document.xhtml unten) und nicht den leeren Tag drucken, wenn gerendert auf false berechnet? Ich weiß, ich kann c:if verwenden, aber gerendert wird in Facelets empfohlen.
  3. Hat die DB Javabean Document auch (neben DocumentController)?

bitte auch, wenn es eine bessere Art und Weise zu tun, was ich tue (einer Seite, die ein id über GET und zeigt das Objekt erhält), bitte beraten. Ich bin total neu in JSF.

Btw, ich habe verworfen es ist wegen 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> 
+0

Es scheint, was Sie tun möchten, ist zu verwenden, um eine 'h: dataTable' in Ihrem Verbundbauteil statt den Aufbau einer Tabelle selbst . Sehen Sie sich die Komponente an. Auch für Ihre zweite Frage könnten Sie, da es sich um Standard-HTML-Tags handelt, dann in ein 'ui: fragment' verpacken, das auch das' gerendert'-Attribut enthält und keinen zusätzlichen HTML-Code darstellt. –

+0

Bei einigen Elementen würde ich lieber mein eigenes HTML5 anstelle von h: XXX verwenden. Auch dies würde das Problem nicht lösen, denn wie gesagt, es passiert auch mit meinem

Antwort

0

1. Wie kann ich das beheben?

Wie ich vermutete, hatte dies etwas mit preRenderView zu tun. Hinweise, dies herauszufinden, waren, dass die Protokolle die Bean mit den Daten zeigten, und dass, wenn ich SessionScoped verwendet, auf meiner Aktualisierung die Daten auf wundersame Weise erschienen, aber nie mit einer RequestScoped erschienen, egal wie oft ich aktualisiert - was bedeutet, dass die Daten waren tatsächlich innerhalb der Bohne, aber konnte nicht zum ersten Mal angezeigt werden.Ich reparierte sie durch Änderung:

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

zu

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

Siehe auch: When to use f:viewAction/preRenderView versus PostConstruct?

ich, keine Antwort für (2) (3) oder die beste Praxis für was ich versuche zu tun, aber zumindest wollte ich die Hauptproblemlösung schreiben, falls jemand es braucht.

2. Offenbar gibt es keine, zumindest in der aktuellen JSF-Version. Dies kann getan werden, aber es ist nicht ideal:

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

3. Nop