Dr. Winston Prakash Ph.D. 

Personal Website

Understanding Netbeans Visual JSF Web Application

Netbeans Visual JSF Web Application is a strict Java EE Application and follows the Java Server Faces standards. In order to support rich JSF application development, Visual Web introduces few extension libraries.

  • Dataprovider for uniform accessing of data, irrespective  of whether the data is fetched via CachedRowset or the data is stored as Array or List of Objects.
  • Application Model for easy integration of user business logic in to the over all JSF Life Cycle, with out the need to understand the complex phases of JSF Life Cycle.
  • Designtime API to integrate JSF components, which tells Netbeans how to handle the component for rich design time experience.
  • ErrorHandler, to support proper redirection of page when error occurs in the application.

 When Visual JSF framework is added to a Netbeans Web project, under the hood it creates all the code required for a basic Java Server Faces Application  

  • Creation of a JSP file (Page1.jsp)
  • Creation of Java file (Page.java) to be used as backing bean for Page1.jsp, which contains the methods of the Application model.
  • Creation of three scoped beans RequestBean, SessionBean, ApplicationBean
  • Addition of required libraries to the project
    • Woodstock Component  related (webui-jsf, dojo, jason etc)
    • Dataprovider  (dataprovider.jar)
    • Error Handler (errorhandler.jar)
    • Application Model (appbase.jar)
  • Injection of entries in to WEB-INF/web.xml
    • JSF Servlet
    • Context parameters to customize JSF application
    • Theme Servlet
    • File Upload Filter
    • Error Handler Servlet
    • Initial Page information
  • Injection of entries in to the WEB-INF/faces-config.xml

What happens when you drag and drop a component?

  • The entry corresponding to the component is added to the JSP page.  Ex
    <webuijsf:button binding="#{Page1.button1}" id="button1" text="Button"/> 
  • Corresponding binding information gets added to the backing bean (Java). Ex
    private Button button1 = new Button(); 
    public Button getButton1() { 
      return button1; 
    } 
    public void setButton1(Button b) { 
      this.button1 = b; 
    } 
    Note: As of NB 6.1, this no longer happens. If needed, click on the component and select "Create Binding".

What happens you drag and drop database table on to a component?

  • Dataprovider entry gets added to the backing bean. Ex
    private void _init() throws Exception {
      customerDataProvider.setCachedRowSet((javax.sql.rowset.CachedRowSet) 
          getValue("#{SessionBean1.customerRowSet}"));
    }
    private CachedRowSetDataProvider customerDataProvider = 
                                            new CachedRowSetDataProvider();
    public CachedRowSetDataProvider getCustomerDataProvider() {
      return customerDataProvider;
    }
    public void setCustomerDataProvider(CachedRowSetDataProvider crsdp) {
      this.customerDataProvider = crsdp;
    }
  • Cachedrowset entry gets added to the session bean. Ex
    private CachedRowSetXImpl customerRowSet = new CachedRowSetXImpl();
    public CachedRowSetXImpl getCustomerRowSet() {
      return customerRowSet;
    }
    public void setCustomerRowSet(CachedRowSetXImpl crsxi) {
      this.customerRowSet = crsxi;
    }
    private void _init() throws Exception {
      customerRowSet.setDataSourceName("java:comp/env/jdbc/APP_ApacheDerby");
      customerRowSet.setCommand("SELECT * FROM APP.CUSTOMER");
      customerRowSet.setTableName("CUSTOMER");
    }
  • Some binding information are created to link the database table to the component and the JSP code corresponding to the component is modified. Ex
    <webuijsf:button binding="#{Page1.button1}" id="button1" 
    text="#{Page1.customerDataProvider.value['CUSTOMER.NAME']}"/>
  • The datasource information to create the database connection at runtime is written to  setup/sun-resources.xml & WEB-INF/sun-web.xml (Application Server specific)

How does the application works at runtime?

When the browser sends request to webserver or appserver, the "Initial Page" information specified in the web.xml is accessed. Since the initial page has "faces" as prefix, the page is routed via the Faces Servlet specified in the web.xml, which invokes the Faces Application to process the web page and the Application Life Cycle occurs.

How does the Visual Web Application Model hooks in to the JSF Application Life Cycle?

Java Server faces allows to configure the Faces Application via Application Configuration files. When Faces Application Context gets initialized, it finds all the faces-config.xml files (Ex. specified in META-INF of jar files, WEB-INF/faces-config.xml or specified in the context-param of web.xml) to configuare the Faces Application. Visual Web Application Model takes advantage of this and creates a  Custom PhaseListener and registers it to the JSF application via META-INF/faces-config.xml file of the library jar.  

The PhaseListener registered by Visual Web Application model will be notified at the beginning and ending of processing for each standard phase of the request processing lifecycle, which in turn invokes the methods such as init(), preprocess(), prerender() and destroy() of the Page Bean.

Unfortunately, in order to find the page bean (Page1.java) corresponding to the page (Page1.jsp), the Application Model relies on

  • Name of the Page (i.e page1.jsp must have a backing bean by name page1.java)
  • The package name of the backing bean should match the path of the folder in which JSP page resides.

Understanding the life of Managed beans

It is important to understand the life of a Managed Bean in order to design a better scalable application. The life of Managed Beans depend on the scope of Managed Bean as specified in the managed-bean element of the faces-config file.

As I mentioned above, when a database table is bound to a component, information is stored in Page1.jsp, page1.java and SessionBean1.java. When Page1.jsp is processed, the following happens

  • Expression Language (EL) Resolver tries to resolve the expression
    text="#{Page1.customerDataProvider.value['CUSTOMER.NAME']}"
    This ends up instantiating the class Page1.java and invoking the method getCustomerDataProvider().
  • During Restore View Phase of the life cycle, Visual Web Application model PhaseListener is notified, which instantiates the Page1.java (if managed instance not available already) and invokes the init() method, which in turn invokes the  _init() method. As we have seen above _init() methods contains
    customerDataProvider.setCachedRowSet((javax.sql.rowset.CachedRowSet) 
          getValue("#{SessionBean1.customerRowSet}"));
    When 
    #{SessionBean1.customerRowSet}
    is resolved SessionBean is instantiated and the method getCustomerCachedRowset() is invoked. The necessary parameter of the CustomerCachedRowset is set when init() -> _init() of the SessionBean  is invoked by the Application Model.

Even though, both Page1.java & SessionBean1.java are instantiated, since Page1.java is a request scope managed bean, the instance of Page1.java will be garbage collected after the faces application completes the browser's request for Page1.jsp. However, SessionBean1.java is a Session scope bean and it will survive garbage collection until the user's session ends (times out). So data in the Session Bean should be carefully managed, to avoid unnecessary overloading of the Server that hosts the application.

If there are data which will not change and can shared by all users visiting the web site, then they should be kept in the Application scope Managed Bean (ApplicationBean1.java). For example, list of countries or states in a country.