Alvin Sim's Blog

Dynamically include a JSF

Currently I am working on a prototype program, building a CRUD program using JSF together with PrimeFaces. Being totally new in both, I started to get my hands dirty in code without properly going through the tutorials. I am still at the beginning chapters of the Java EE 6 tutorial.

In this program, I have a layout with 4 main sections – top, left, center and bottom. This is done using PrimeFaces layout component. In this component, there are three sub-components whereby its position are defined as “North”, “West”, “Center” and “South”.

primefaces-include

For the purpose of this demo, the program has been simplified to best describe the scenario.

Lets have an overview of the file hierarchy first. There is an “index.html”, which is the screen capture above. And in the same directory, there are “documentA.xhtml” and “documentB.xhtml”. The contents of these two documents will be displayed on the center section of the layout.

On the left section, there are two buttons – “Search Document A” and “Search Document B”.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head><title>Test Layout Include</title></h:head>
    <h:body>
        <p:layout fullPage="true">
            <p:layoutUnit position="north" size="60">NORTH</p:layoutUnit>
            <p:layoutUnit position="west" size="200">
                <h:form>
                    <h:panelGroup>
                        <p:commandButton id="btnPoSearch" value="Search Document A" />
                        <p:commandButton id="btnList" value="Search DocumentB" />
                    </h:panelGroup>
                </h:form>
            </p:layoutUnit>
            <p:layoutUnit position="center">
                <h:form id="frmContent">
                    <p:panel id="pnlContent">
                        <ui:include src="documentA.xhtml" />
                    </p:panel>
                </h:form>
            </p:layoutUnit>
            <p:layoutUnit position="south" size="60">SOUTH</p:layoutUnit>
        </p:layout>
    </h:body>
</html>

And in “documentA.xhtml”, we should not use any of the <html />, <head />, <body /> and <form /> tags. The code for “documentA.xhtml” is as below.


1
2
3
4
5
6
7
8
<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:p="http://primefaces.org/ui"
                xmlns:ui="http://java.sun.com/jsf/facelets">
    <h3>Document A</h3>
    <p:commandButton id="btnSearch" value="Search" type="submit" action="#{documentAController.doSearch}" />
</ui:composition>

With this, the contents of “documentA.xhtml” could be displayed in the “index.xhtml”. So, we come to my second problem. I want the contents on the center section to be dynamic i.e. clicking on the “Search Document A” button will display contents from “documentA.xhtml” and clicking on the “Search Document B” button will display contents from “documentB.xhtml”.

To do this, we have to use JSF’s managed beans. It is a type of Java Bean. If you are familiar with the MVC pattern, managed bean is the controller.

In the managed bean, I need to declare a property “page” of String type and also its getters and setters.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/** === Getter / Setter === **/

public String getPage() {
    return page;
}

public void setPage(String page) {
    this.page = page;
}

/** === Properties === **/

private String page = "documentA";

I have also set “documentA.xhtml” as my default page i.e. when “index.xhtml” loads in the browser, it will always display contents from “documentA.xhtml”.

In the “index.xhtml”, I make the below change.

1
<ui:include src="#{menuController.page}.xhtml" />

The value in the src attribute is using an Expression Language, or commonly called EL. By using EL, it makes it possible to easily access application data stored in the JavaBean component. In this context, we are getting the value of the page property instantiated in the managed bean.

We need to add two attributes to the two buttons in the left section – action and update.

1
2
3
4
<p:commandButton id="btnPoSearch" value="Search Document A"
                 action="#{menuController.doViewDocumentA()}" update=":frmContent:pnlContent" />
    <p:commandButton id="btnList" value="Search DocumentB" update=":frmContent:pnlContent"
                     action="#{menuController.doViewDocumentB()}" />

In the action attribute, we use EL to have it call method doViewDocumentA() in the managed bean. In the managed bean, the method is as below.

1
2
3
public void doViewDocumentA() {
    this.page = "documentA";
}

So, by clicking on the button “Search Document A”, it is calling a method which sets the page property to “document A”. And by clicking the “Search Document B” button, it changes the page property to “document B”. The content in the center section will also be changed based on the page property value.

But how does the content get changed? This is where the button’s update attribute comes into play. If you look at the value, it is :frmContent:pnlContent. This means that upon clicking on the button, whatever happens, it should update the contents of the panel which is in the form with the id of “frmContent” and panel with the id of “pnlContent”.

1
2
3
4
5
6
7
<p:layoutUnit position="center">
    <h:form id="frmContent">
        <p:panel id="pnlContent">
            <ui:include src="#{menuController.page}.xhtml" />
        </p:panel>
    </h:form>
</p:layoutUnit>

One final thing to note. The managed beans for both “documentA.xhtml” and “documentB.xhtml” must be set to use either RequestScoped, SessionScoped or ApplicationScoped. Initially I had it set to ViewScoped and upon change the content to “documentB.xhtml”, the “Search” button’s action which calls a managed bean’s method was not called at all. For more details on each scope, you can refer to BalusC’s explanation.

I have uploaded the source code to my bitbucket account. Do feel free to fork and comment. The intention of this post is basically for Java EE Developers who are starting to use JSF and PrimeFaces that they understand the correct way to dynamically include JSF contents. I had a hard time scoring through internet and asking in forums trying to fix these problems which I faced.

Thanks.

Single Post Navigation

14 thoughts on “Dynamically include a JSF

  1. Hi

    Thanks for sharing this. I was looking for something like this for a long time. I have a question regarding scope, you mean to say that view scope will not work for the pages which needs to be added?

  2. Sorry for the misinformation. It DOES work in viewscope. I must have done something wrong at the time I wrote this blog post.

    • Alvin thanks for the reply. I have a question regarding displaying the contents when a link or button is clicked. When I pressed button B, it doesn’t shows contents in middle of the page, the default value in private String page = “documentA”; is always gets displayed.

      And is it possible to use a Tree menu in left menu?

  3. For button B, did you specify it to update the panel where your is? In my example, whenever Button A or B is clicked, it will update panel pnlContent. Here is how it looks:

    .

    And here is how code of the panel looks like.

    You can check out the sourcecocde at my bitbucket.

    Yes, you can do it using a Tree menu.

  4. Hi,

    I have tried the solutions, but the problem is that every time a button is pushed into the index.html, the viewController of A or B is instanced with a new constructor, so, they don’t keep the old attributes of the view map.

    Have you checked it ? I have just checked with a log on the constructor of A and B classes. Have you a solutions ?

    Very Thanks, Carlo

  5. Greetings, There’s no doubt that your site may be having internet browser compatibility problems. When I take a look at your blog in Safari, it looks fine however, if opening in I.E., it has some overlapping issues. I simply wanted to provide you with a quick heads up! Apart from that, great blog!

  6. umur inan on said:

    thank you very much to share this code. I have been searching something like that about 2 days finally i found your blog and the code run perfectly. Again thank you.

  7. R063R on said:

    Thank you!

  8. Johnb206 on said:

    A big thank you for your article.Thanks Again. Great. bgdfbgfegfeg

  9. Thanks for your personal marvelous posting!
    I seriously enjoyed reading it, you could be a great author.I will make certain to
    bookmark your blog and will often come back sometime soon. I want
    to encourage you to continue your great job, have a nice holiday weekend!

  10. Every weekend i used to pay a quick visit this website, because i want enjoyment, since this this website
    conations truly fastidious funny stuff too.

  11. Waqas on said:

    Good Work

Leave a comment