views:

225

answers:

1

I have a very simple page that is displaying canned data. I experienced this problem with data from a DB so I made this simple example and still have the issue. When this page is navigated to for the first time for a session, the first column in the first row shows no data.

It doesn't matter if I change the scope to request or session, nor does it make a difference if I use firefox or IE. All I know is that if I reload the page or navigate away and come back it will all of a sudden show my data - until I close all instances of that browser and load up a new one. Then, again, it won't show my data until I reload the page.

The question is why does my beloved first title of my first book never show up until i reload the page ("Operating System Concepts" doesn't show, but "Silberschatz" does)?

Below is the relevant code.

HomePage.java:

public class HomePage {

    private Book[] books;

    public HomePage() {
     books = new Book[3];
     books[0] = new Book("Operating System Concepts", "Silberschatz");
     books[1] = new Book("Learning Sql", "Beaulieu");
     books[2] = new Book("Effective Java", "Bloch");
    }

    public Book[] getBooks() {
     return books;
    }
    public void setBooks(Book[] books) {
     this.books = books;
    }
}

Book.java

public class Book {

    private String title;
    private String author;

    public Book() {}

    public Book(String title, String author) {
     this.title = title;
     this.author = author;
    }


    public String getTitle() {
     return title;
    }
    public void setTitle(String title) {
     this.title = title;
    }

    public String getAuthor() {
     return author;
    }
    public void setAuthor(String author) {
     this.author = author;
    }
}

home.jsp:

<html>
  <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
  <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

  <link href="../css/styles.css" rel="stylesheet" type="text/css" />
  <f:loadBundle basename="omitted.for.anonymity.bundle.home" var="msgs"/>

  <f:view>
    <body>
      <h:form>
        <h:panelGrid columns="2" columnClasses="sideControlColumn,contentColumn">
          <f:facet name="header">
            <f:subview id="header">
              <jsp:include page="header.jsp" />
            </f:subview>
          </f:facet>

          <f:subview id="sideControl" >
            <jsp:include page="sideControl.jsp" />
          </f:subview>

          <h:dataTable value="#{homePage.books}"
                var="book"
                styleClass="homeTable"
                rowClasses="evenColumn,oddColumn"
                >

            <h:column>
              <f:facet name="header">
                <h:outputText value="#{msgs.columnHeader1}"/>
              </f:facet>

              <h:outputText value="#{book.title}" />
            </h:column>

            <h:column>
              <f:facet name="header">
                <h:outputText value="#{msgs.columnHeader2}"/>
              </f:facet>

              <h:outputText value="#{book.author}" />
            </h:column>

          </h:dataTable>

        </h:panelGrid>
      </h:form>
    </body>
     </f:view>
</html>

faces-config.xml:

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
    "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
    "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"&gt;

<faces-config>

    <navigation-rule>
    <from-view-id>/pages/login.jsp</from-view-id>
     <navigation-case>
      <from-outcome>login</from-outcome>
      <to-view-id>/pages/home.jsp</to-view-id>
     </navigation-case>
    </navigation-rule>

    <navigation-rule>
    <from-view-id>/pages/home.jsp</from-view-id>
     <navigation-case>
      <from-outcome>searchForBooks</from-outcome>
      <to-view-id>/pages/searchCriteria.jsp</to-view-id>
     </navigation-case>
    </navigation-rule>

    <navigation-rule>
    <from-view-id>/pages/searchCriteria.jsp</from-view-id>
     <navigation-case>
      <from-outcome>searchForBooks</from-outcome>
      <to-view-id>/pages/searchCriteria.jsp</to-view-id>
     </navigation-case>
    </navigation-rule>

    <navigation-rule>
    <from-view-id>/pages/searchResults.jsp</from-view-id>
     <navigation-case>
      <from-outcome>searchForBooks</from-outcome>
      <to-view-id>/pages/searchCriteria.jsp</to-view-id>
     </navigation-case>
    </navigation-rule>

    <navigation-rule>
    <from-view-id>/pages/searchCriteria.jsp</from-view-id>
     <navigation-case>
      <from-outcome>search</from-outcome>
      <to-view-id>/pages/searchResults.jsp</to-view-id>
     </navigation-case>
    </navigation-rule>


    <managed-bean>
     <managed-bean-name>book</managed-bean-name>
     <managed-bean-class>omitted.for.anonymity.beans.Book</managed-bean-class>
     <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>homePage</managed-bean-name>
     <managed-bean-class>omitted.for.anonymity.beans.page.HomePage</managed-bean-class>
     <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>searchCriteriaPage</managed-bean-name>
     <managed-bean-class>omitted.for.anonymity.beans.page.SearchCriteriaPage</managed-bean-class>
     <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>searchResultsPage</managed-bean-name>
     <managed-bean-class>omitted.for.anonymity.beans.page.SearchResultsPage</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>

</faces-config>
+2  A: 

Table that sets a book request scope variable:

<h:dataTable value="#{homePage.books}"
    var="book"
    styleClass="homeTable"
    rowClasses="evenColumn,oddColumn">

Managed bean that sets a book session scope variable:

<managed-bean>
    <managed-bean-name>book</managed-bean-name>
    <managed-bean-class>omitted.for.anonymity.beans.Book</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Just guessing, but I wonder if the Expression Language is resolving the session bean here for some reason. It shouldn't - the ScopedAttributeELResolver "searches the page, request, session and application scopes for an attribute with the given name and returns it, or null if no attribute exists with the current name." But it isn't beyond possibility that there is a bug in the Expression Language implementation. Try changing the name of the var attribute to avoid collision or resolve it explicitly to the scope using #{requestScope.book.title}.

<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"&gt;

I notice from your doctype that you're using JSF 1.1. I recommend upgrading to at least 1.2 (preferably 2.0) if you can.

McDowell
You're the man. I added that line, but it only moved the problem to the author column. Additionally adding the same fix to the author column fixed everything. You hypothesized that there may be a "bug" in the EL - care to elaborate on what the prefix of requestScope "does" and why you thought this would fix it? Up vote and check marked as correct answer - will also look into upgrading JSF implementation. I know there were lots of dependencies to chase down, (had to match up with a specific jsp spec and stuff like that).
Russ
The JSP spec defines a strict ordering of how variables are resolved. Implicit variables (like requestScope and sessionScope) are always resolved first. Using this prefix means EL won't hunt through the scopes to resolve your object. See your version of the JSP spec for the defined order and list of implicit variables (probably JSR 245 or JSR 152).
McDowell