Using Window Scope

compared with
Current by Brad Kroeger
on Dec 10, 2010 18:15.


 
Key
These lines were removed. This word was removed.
These lines were added. This word was added.

View page history


There are 2 changes. View first change.

 h1. Using Window Scope Tutorial
  
 Window Scope is a custom scope added by ICEfaces 2 to JSF 2. The purpose of this scope is to fill the niche between ViewScoped and SessionScoped by providing a slightly longer object lifespan than ViewScoped, but without the overhead of SessionScoped.
  
 This tutorial assumes the reader has an understanding of JSF and ICEfaces and creating and working with projects related to those technologies. The focus is not to teach those basics, but instead to learn more about Window Scope.
  
 The goal of this tutorial is to create a basic ICEfaces 2 project and examine the differences between View, Window, and Session scoped beans. The example will contain two basic pages that are navigated between, and some output information about our various scopes so we can see when a bean is created and destroyed.
 \\
 \\
 ----
 {panel}Here is the entire list of steps worked through during this tutorial:
  
 # [Make the windowScope Project|#step1]
 # [Add ICEfaces|#step2]
 # [Create 3 Beans with Different Scopes|#step3]
 #* [Create WindowBean.java|#step3a]
 #* [Create ViewBean.java|#step3b]
 #* [Create SessionBean.java|#step3c]
 # [Create PageController.java|#step4]
 # [Create Two Pages|#step5]
 #* [Create page1.xhtml|#step5a]
 #* [Create page2.xhtml|#step5b]
 # [Deploy and Test the Application|#step6]
  
 * [Tutorial Source Code Downloads|#downloads]
 {panel}
 ----
 h3. Development Tools Used
  
 The following tools were used to create the project.
 * [Eclipse|http://eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/heliossr1] IDE for Java EE Developers - Version Helios
 * [Tomcat 7.x|http://tomcat.apache.org/download-70.cgi] Web Server
 * [Java 6.x|http://www.oracle.com/technetwork/java/javase/downloads/]
 * [ICEfaces 2.0 Beta 2|http://www.icefaces.org/JForum/posts/list/17890.page]
  * ICEfaces 2
  
 h3. {anchor:step1}1. Make the {{windowScope}} Project
  
 * Using Eclipse create a new Dynamic Web Project called {{windowScope}}** Target runtime: Apache Tomcat v7.0
 ** Dynamic web module version: 3.0
 ** Configuration: JavaServer Faces v2.0 Project (Mojarra)
  
 h3. {anchor:step2}2. Add ICEfaces
  
 Add the {{icefaces.jar}} to your project from the ICEfaces 2 bundle. This can be added to the project through a custom User Library or by putting it into {{windowScope/WEB-INF/lib/}}. The approach doesn't matter as long as the jar is included in the deployed {{war}} file.
  
 h3. {anchor:step3}3. Create 3 Beans with Different Scopes
  
 We will now create a Window Scope, ViewScoped, and SessionScoped bean. Aside from the naming and scope annotation these beans are exactly the same. Each will track a {{Timestamp}} value of when they were created. This will help us determine when a bean was re-created as part of the JSF lifecycle.
  
 h4. {anchor:step3a}3a. Create {{WindowBean.java}}
  
 Create a new Java class file called {{WindowBean}} in the package {{org.icefaces.tutorial.windowscope.beans}} and paste the code below:
  
 {code:title=WindowBean.java}package org.icefaces.tutorial.windowscope.beans;
  
 import java.io.Serializable;
 import java.sql.Timestamp;
  
 import javax.faces.bean.CustomScoped;
 import javax.faces.bean.ManagedBean;
  
 @ManagedBean(name="windowBean")
 @CustomScoped(value = "#{window}")
 public class WindowBean implements Serializable {
  private Timestamp created;
  
  public WindowBean() {
  created = new Timestamp(System.currentTimeMillis());
  }
  
  public Timestamp getCreated() {
  return created;
  }
  
  public void setCreated(Timestamp created) {
  this.created = created;
  }
 }
 {code}
 The custom ICEfaces 2 Window Scope is used by this class. As the scope is custom, the JSF annotation {{javax.faces.bean.CustomScoped}} is used, with a value of {{\#\{window\}}}. This will declare the bean as Window Scope.
  
 h4. {anchor:step3b}3b. Create {{ViewBean.java}}
  
 Create a new Java class file called {{ViewBean}} in the package {{org.icefaces.tutorial.windowscope.beans}} and paste the code below:
  
 {code:title=ViewBean.java}package org.icefaces.tutorial.windowscope.beans;
  
 import java.io.Serializable;
 import java.sql.Timestamp;
  
 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.ViewScoped;
  
 @ManagedBean(name="viewBean")
 @ViewScoped
 public class ViewBean implements Serializable {
  private Timestamp created;
  
  public ViewBean() {
  created = new Timestamp(System.currentTimeMillis());
  }
  
  public Timestamp getCreated() {
  return created;
  }
  
  public void setCreated(Timestamp created) {
  this.created = created;
  }
 }
 {code}
 h4. {anchor:step3c}3c. Create {{SessionBean.java}}
  
 Create a new Java class file called {{SessionBean}} in the package {{org.icefaces.tutorial.windowscope.beans}} and paste the code below:
  
 {code:title=SessionBean.java}package org.icefaces.tutorial.windowscope.beans;
  
 import java.io.Serializable;
 import java.sql.Timestamp;
  
 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.SessionScoped;
  
 @ManagedBean(name="sessionBean")
 @SessionScoped
 public class SessionBean implements Serializable {
  private Timestamp created;
  
  public SessionBean() {
  created = new Timestamp(System.currentTimeMillis());
  }
  
  public Timestamp getCreated() {
  return created;
  }
  
  public void setCreated(Timestamp created) {
  this.created = created;
  }
 }
 {code}
 h3. {anchor:step4}4. Create {{PageController.java}}
  
 Create a new Java class file called {{PageController}} in the package {{org.icefaces.tutorial.windowscope.controller}} and paste the code below:
  
 {code:title=PageController.java}package org.icefaces.tutorial.windowscope.controller;
  
 import java.io.Serializable;
  
 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.SessionScoped;
 import javax.faces.event.ActionEvent;
  
 @ManagedBean(name="pageController")
 @SessionScoped
 public class PageController implements Serializable {
  public String navigatePage1() {
  System.out.println("Redirect to Page 1");
  
  return "page1";
  }
  
  public String navigatePage2() {
  System.out.println("Redirect to Page 2");
  
  return "page2";
  }
  
  public String action() {
  System.out.println("Action Fired");
  
  return null;
  }
  
  public void actionListener(ActionEvent event) {
  System.out.println("ActionListener Fired");
  }
 }
 {code}
 This is a basic page backing bean that allows our tutorial application to simulate a few common use cases. The class provides two methods for navigation (between our two basic pages, which will be created next). The class also has a basic {{action}} and {{actionListener}}. By triggering each of these methods we will be able to see how Window Scope responds in comparison to ViewScoped and SessionScoped.
  
 h3. {anchor:step5}5. Create Two Pages
  
 We will now create two basic pages called {{page1.xhtml}} and {{page2.xhtml}}. Both pages are very similar except for the naming and which redirect methods (from {{PageController.java}}) they use.
  
 h4. {anchor:step5a}5a. Create {{page1.xhtml}}
  
 Create a new page called {{page1.xhtml}} and paste the code below:
  
 {code:title=page1.xhtml}<!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:f="http://java.sun.com/jsf/core">
 <h:head>
  <title>Window Scope - Page 1</title>
 </h:head>
 <h:body>
  <h2>Page 1</h2>
  <h:panelGrid columns="2">
  <h:outputLabel for="viewBean" value="View Bean:" style="font-weight: bold;"/>
  <h:outputText id="viewBean" value="#{viewBean} created #{viewBean.created}"/>
  
  <h:outputLabel for="windowBean" value="Window Bean:" style="font-weight: bold;"/>
  <h:outputText id="windowBean" value="#{windowBean} created #{windowBean.created}"/>
  
  <h:outputLabel for="sessionBean" value="Session Bean:" style="font-weight: bold;"/>
  <h:outputText id="sessionBean" value="#{sessionBean} created #{sessionBean.created}"/>
  </h:panelGrid>
  
  <h:form>
  <h:panelGrid columns="4">
  <h:commandButton value="Redirect to Page 2" action="#{pageController.navigatePage2}"/>
  <h:commandButton value="Refresh Page"
  action="#{pageController.navigatePage1}"/>
  <h:commandButton value="Use an Action"
  action="#{pageController.action}"/>
  <h:commandButton value="Use an Action Listener"
  actionListener="#{pageController.actionListener}"/>
  </h:panelGrid>
  </h:form>
 </h:body>
 </html>
 {code}
 h4. {anchor:step5b}5b. Create {{page2.xhtml}}
  
 Create a new page called {{page2.xhtml}} and paste the code below:
  
 {code:title=page2.xhtml}<!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:f="http://java.sun.com/jsf/core">
 <h:head>
  <title>Window Scope - Page 2</title>
 </h:head>
 <h:body>
  <h2>Page 2</h2>
  <h:panelGrid columns="2">
  <h:outputLabel for="viewBean" value="View Bean:" style="font-weight: bold;"/>
  <h:outputText id="viewBean" value="#{viewBean} created #{viewBean.created}"/>
  
  <h:outputLabel for="windowBean" value="Window Bean:" style="font-weight: bold;"/>
  <h:outputText id="windowBean" value="#{windowBean} created #{windowBean.created}"/>
  
  <h:outputLabel for="sessionBean" value="Session Bean:" style="font-weight: bold;"/>
  <h:outputText id="sessionBean" value="#{sessionBean} created #{sessionBean.created}"/>
  </h:panelGrid>
  
  <h:form>
  <h:panelGrid columns="4">
  <h:commandButton value="Redirect to Page 1" action="#{pageController.navigatePage1}"/>
  <h:commandButton value="Refresh Page"
  action="#{pageController.navigatePage2}"/>
  <h:commandButton value="Use an Action"
  action="#{pageController.action}"/>
  <h:commandButton value="Use an Action Listener"
  actionListener="#{pageController.actionListener}"/>
  </h:panelGrid>
  </h:form>
 </h:body>
 </html>
 {code}
 h4. {anchor:step6}6. Deploy and Test the Application
  
 Now that the application is setup we can build and deploy it and begin testing.
  
 There are several use cases that demonstrate the difference between the custom Window Scope and the standard JSF 2 scopes. Open a web browser and try the following:
  
 * Click "Redirect to Page 1". Notice the ViewScoped bean is re-created, but Window and Session scope maintain their state.
 * Click "Refresh Page". Notice the ViewScoped bean is re-created, but Window and Session scope maintain their state.
 * Manually refresh or reload the web browser. A similar outcome as the "Refresh Page" button occurs.
 * Click "Use an Action" and "Use an Action Listener". All beans maintain their state through the processing of those buttons.
 * Open a second tab or window in the web browser. Notice the ViewScoped bean _and_ Window Scope bean are re-created, but Session scope maintains their state.
  * Open a second tab or window in the web browser. Notice new ViewScope _and_ Window Scope beans are created, but the Session scope bean is still in scope.
  
 As you can see, Window Scope lives longer than ViewScoped, but not quite as long as SessionScoped. Therefore this custom scope is a perfect candidate for page level backing beans. Using Window Scope instead of ViewScoped can help with user friendliness (as values aren't reset as often) without the memory footprint and overhead of SessionScoped.
  
 ----
 h3. {anchor:downloads}Tutorial Source Code Downloads
  
 || Example || Source || Notes ||
 | Window Scope project | [windowScope source code |^windowScope.zip|Download Source Code] | Basic example project demonstrating how to use the custom ICEfaces 2 Window Scope. |

© Copyright 2018 ICEsoft Technologies Canada Corp.