Search code examples
jsfrenderingdocument-bodyhtml-head

Contents of head is repeated in body


I'm working on a project in Java EE with JSF and Primefaces. I'm also using Hibernate as a ORM framework. As I see it, Primefaces and Hibernate doesn't interfere, but I mention it so you can get the full picture. I have a login and a register page. Both are Facelets Template Clients and you navigate from the first to the second. The register page is linked to 2 Managed Bean's properties and call a method from the first one. An MCVE would be:

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
  <body>
    <ui:composition template="./templates/mainTemplate.xhtml">
      <ui:define name="top"></ui:define>

      <ui:define name="content">
        <h:form>
          <h2>Login</h2>
            <h:panelGrid columns="2">
              <h:outputLabel for="user" value="User:" />
              <p:inputText id="user"/>
              <h:outputLabel for="password" value="Password:" />
              <p:password id="password"/>

              <!-- Still no connection to the Login's MB -->
              <p:commandButton value="Login"/>

              <!-- Go to register.xhtml -->
              <p:commandButton value="Register" action="register"/>
            </h:panelGrid>
          </h:form>
      </ui:define>

      <ui:define name="bottom">bottom</ui:define>
    </ui:composition>
  </body>
</html>

register.xhtml

<!--ui:composition nested in html and body as in index.xhtml-->
<ui:composition template="./templates/mainTemplate.xhtml">
  <ui:define name="top"></ui:define>

  <ui:define name="content">
    <h:form id="frmRegister">
      <h:panelGrid columns="2">
        <h:outputLabel for="name" value="Name:" />
        <p:inputText id="name" label="Name" required="true" size="50" 
                     value="#{personBean.person.name}"/>

        <h:outputLabel for="birthdate" value="Date of birth:" />
        <p:calendar id="birthdate" 
                    label="Date of birth"
                    placeholder="dd/mm/aaaa"
                    required="true"
                    value="#{personBean.person.birthdate}"/>

        <h:outputLabel for="password" value="Password(*):"/>
        <p:password id="password" label="Password" required="true" size="30"
                    value="#{userBean.user.password}"/>

        <h:outputLabel for="password-repeat" value="Repeat your password(*):"/>
        <p:password id="password-repeat" label="Repeated password" required="true" size="30"
                    value="#{userBean.repeatPassword}"/>

        <p:commandButton value="Register User" actionListener="#{personBean.addPerson()}"/>
        <p:commandButton value="Back" action="index" />
      </h:panelGrid>
    </h:form>
  </ui:define>

  <ui:define name="bottom">bottom</ui:define>
</ui:composition>

mainTemplate.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

  <h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <h:outputStylesheet name="./css/default.css"/>
    <h:outputStylesheet name="./css/cssLayout.css"/>
    <h:outputStylesheet name="./css/libs/bootstrap.min.css"/>
    <h:outputStylesheet name="./css/libs/bootstrap-theme.min.css"/>
    <title>Title</title>
  </h:head>

  <h:body>
    <div id="top">
      <ui:insert name="top">Top</ui:insert>
      <h1>A Test</h1>
    </div>

    <div id="content" class="center_content">
      <ui:insert name="content">Content</ui:insert>
    </div>

    <div id="bottom">
      <ui:insert name="bottom">Bottom</ui:insert>
    </div>

The problem is that when I try to load the page I get a blank page and when I open the Chrome's developers tools I can see that the body is rendered with the same info that the head. To get the picture:

<head>
  <link type="text/css" rel="stylesheet" href=".../theme.css?ln=primefaces-bootstrap">
  ...
  <script type="text/javascript" src="...jquery.js?ln=primefaces&amp;v=5.0"></script>
  ...
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>THE TITLE</title>
  <link rel="icon" href="resources/img/favicon.ico">
</head>

<body>
  <link type="text/css" rel="stylesheet" href=".../theme.css?ln=primefaces-bootstrap">
  ...
  <script type="text/javascript" src="...jquery.js?ln=primefaces&amp;v=5.0"></script>
  ...
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>THE TITLE</title>
  <link rel="icon" href="resources/img/favicon.ico">
  <div id="textarea_simulator" style="position: absolute; top: 0px; left: 0px; visibility: hidden;"></div>
</body>

And the console gives me the following error:

[Warning] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.
[Error] Uncaught TypeError: Cannot read property 'debug' of undefined

As you can see, it's the same thing, except for the <div id="textarea_simulator"> element. When I quit the references to the MB's person properties, the pages works fine (I mean delete the value=#{} in the <p:inputText /> element).

According to the video tutorial suggested in the JSF wiki, and to the Java EE documentation (ch 8.4 Using Facelets Template, p. 136), when you have a ui:composition tag (which is a Facelets Template Client), everything outside is ignored. Because of that, I tried putting the XML namespace definition within this tag for index and register, but the result is the same.

My Managed Beans are as follow:

personBean.java

@ManagedBean
@RequestScoped
public class PersonBean {
    @ManagedProperty("#{userBean}")
    private UserBean userBean;
    private Person person;

    //Empty constructor, getter/setter

    public void addPerson(){
        //In a try/catch block: open connection, make query with prepared statement and commit
    }  
}

userBean.java

@ManagedBean
@RequestScoped
public class UserBean {
    private User user;
    private String repeatPassword;

    //Constructor, getters and setters
}

Finally, Person and User are POJO's with properties, getters and setters (no constructor) Am I missing something? What is my mistake?

I'm working with Netbeans 8.0.2 and with Glasfish Sever 4.1. Any help is very appreciated. Thanks in advance.

Note

The Glassfish server gives me the following message:

SEVERE: JSF cannot create the managed bean personBean when it is required. Following errors have been found:
    - The property userBean does not exists for the managed bean personBean

(I am translating from the spanish, so the message may differ from the one you can get). I changed @ManagedProperty("#{userBean}") for @ManagedProperty("#{UserBean}") (uppercase) but the result is the same.


Solution

  • Got it. Instead of using @ManagedProperty annotation

    import javax.faces.bean.ManagedProperty;
    ...
        @ManagedProperty("#{userBean}")
        private UserBean userBean;
    

    I used the @Inject annotation

    import javax.inject.Inject;
    ...
        @Inject private UserBean userBean;
    

    And now renders perfectly. The solution came out from the The Java EE Tutorial, Release 7, chapter 23.7.- Injecting Beans, page 23.6 (400).

    I've seen other tutorials/examples using @ManagedProperty and working fine, but for some reason doesn't work here. In fact, I searched in the mentioned tutorial and there is NO REFERENCE to @ManagedProperty, but it is documented in the Java EE API.

    I've just find a very good discussion on this subject in this post