Showing posts with label JSF2. Show all posts
Showing posts with label JSF2. Show all posts

Sunday, April 8, 2012

My First application of JSF2.0 with CDI



In this specific tutorial will list the steps of JSF2.0 that uses CDI. Used Jboss 6.1 application server which ships with the CDI implementation - Weld.

Step1:  We shall create a JSF page that shall  have 3 input text and bind to a managed bean.


<!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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">


<ui:composition>
  <h:body>
     <h:form>
<h:inputText value="#{employeeBean.name}"></h:inputText>
<h:inputTextarea value="#{employeeBean.id}"></h:inputTextarea>
<h:inputTextarea value="#{employeeBean.departmentBean.department}"></h:inputTextarea>
<h:commandButton value="submit" action="#{employeeBean.submit}"></h:commandButton>
     </h:form>
   </h:body>
</ui:composition>
</html>


Step2:  Now lets create a managed bean “EmployeeBean” and “DepartmentBean” which shall be a CDI managed java bean. You could notice there are new annotations @javax.enterprise.context.RequestScoped, @Dependent, @Named, @inject


package com.test;


import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;


@RequestScoped
@Named
public class EmployeeBean {
private String name;
private int id;

@Inject
private DepartmentBean departmentBean;


public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String submit(){
System.out.println("submit action called");
return "welcome";
}
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
}

Now lets take a look at the use of these new annotations:

@ javax.enterprise.context.RequestScoped: A typical web request scope. There are new scopes added apart from the typical (request, session, application) such as @conversationScoped, @Dependent. Shall cover the new scopes in a separate post.

@Named: This annotation lets the managed beans to be accessed through EL.  If there is no value attribute been used then default value is been assigned according to the naming convention. In this case it is “employeeBean”

@Dependent: you could note yet another new scoped bean called @Dependent which is also a default scope if none specified and will serve exactly one client (bean) and has the same life cycle of the client (bean).

@inject:  This annotation is used to inject one bean in to the other. In this example you could see the dependent scope departmentBean is injected to the request scoped employeeBean.



package com.test;

import javax.enterprise.context.Dependent;

@Dependent
public class DepartmentBean {
private String department;

public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}


Step3:  Now lets create a simple new page where the values got from the user are being displayed.

<!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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">

<h:body>
<h:form>
<h:outputText value="#{employeeBean.name}"/>
<h:outputText value="#{employeeBean.id}"/>
<h:outputText value="#{employeeBean.departmentBean.department}"/>
<h:commandButton value="back" action="Test?faces-redirect=true"></h:commandButton>
</h:form>
</h:body>
</html>

Step4: Apart from annotations you could have noticed there is nothing much difference in this application for CDI. The last small step is the addition of beans.xml. This xml is must required even if there is no configurations to be made. This shall allow the app server (jboss here) to use the CDI implementation (weld) to scan through for CDI beans and provide services.

This xml is to be placed in the web-inf folder.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:weld="http://jboss.org/schema/weld/beans" 
       xsi:schemaLocation="
          http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd
          http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">
 </beans>

Now deploy the application in App server(jboss)







Troubleshoot – JSF 2 (Mojarro – JSF-2.0.3)

Troubleshoot – JSF 2 (Mojarro – JSF-2.0.3)


Next in the troubleshoot series is the dumb illegal argument exception on request of a jsf page. This specific problem seems to be a bug in the Mojarro implementation where it swallows the specific exception caused because of simple mistakes in the xhtml pages.


1:30:17,375 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/TestJSF2].[Faces Servlet]] Servlet.service() for servlet Faces Servlet threw exception: java.lang.IllegalArgumentException: null source
at java.util.EventObject.(Unknown Source) [:1.6.0_23]
at javax.faces.event.SystemEvent.(SystemEvent.java:67) [:2.0.3-]
at javax.faces.event.ComponentSystemEvent.(ComponentSystemEvent.java:69) [:2.0.3-]
at javax.faces.event.PostRestoreStateEvent.(PostRestoreStateEvent.java:69) [:2.0.3-]
at com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:256


The problem that might caused this exception would be because of a simple error in the xhtml page like missing tag or xml not well formed etc., Facelets is expected to throw exception with detailed message but the exception is swallowed. The issue seems to be still in open

http://java.net/jira/browse/JAVASERVERFACES-1758



Wednesday, April 4, 2012

Injection in JSF

Injection in JSF:

The dependent managed bean can be injected in to the managed bean using the @ManagedBean property annotation in JSF2

Say for example TestBean is holding a property of type DepartmentBean, the bean shall be injected to the TestBean as below.

@ManagedBean
@RequestScoped
public class TestBean {

   @ManagedProperty(value="5")
    private int id;

   @NotNull(message="Name cannot be blank")
    private String name;

   @ManagedProperty(value="#{departmentBean}")
   private DepartmentBean deptBean;

   public DepartmentBean getDepartmentBean() {

     return deptBean;
   }


   public void setDepartmentBean(DepartmentBean deptBean) {
     this.deptBean= deptBean;
  }

   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 }


@ManagedBean
@RequestScoped
public class DepartmentBean {


   @ManagedProperty(value="admin")
   public String dept;

   public String getDept() {
     return dept;
   }

   public void setDept(String dept) {
     this.dept = dept;
 }
}

In the above example you could notice the managed bean injection performed using the @ManagedProperty annotation and also EL is been used to refer the dependent bean (#{departmentBean}. You could also notice there is no name attribute is been used in both the managed beans and hence the default value is been assigned with the naming conventions.
 
The same can be done in JSF1.2 using the faces Config xml configuration

<managed-bean>

    <managed-bean-name>testBean</managed-bean-name>
    <managed-bean-class>com.test.TestBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
         <property-name>deptBean</property-name>
         <value>#{departmentBean}</value>
     </managed-property>
</managed-bean>


<managed-bean>
    <managed-bean-name>departmentBean</managed-bean-name>
    <managed-bean-class>com.test.DepartmentBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
<managed-bean>



Initializing Managed Bean Property

Initializing the MangedBean property:
Managed beans shall be initialized on the object creation and this shall be performed using configuration in Faces Config xml in JSF1.2 and using annotations in JSF2.0
Initializing a property in JSF1.2:

<managed-bean>

                      <managed-bean-name>testBean</managed-bean-name>
                      <managed-bean-class>com.test.TestBean</managed-bean-class>
                      <managed-bean-scope>session</managed-bean-scope>
                      <managed-property>
                                 <property-name>name</property-name>
                                <property-class>java.lang.String</property-class>
                                <value>Enter the Name</value>
                      </managed-property>

               </managed-bean>

Initializing the same in JSF2.0: Take a look at the annotation @ManagedProperty introduced in JSF2.0 and the value attribute holds the default value to be initialized.

@ManagedBean

@RequestScoped
public class TestBean {

  @ManagedProperty(value="Enter the Name")
   private String name;
   /**
     * @param name the name to set
     */
    public void setName(String name) {
          this.name = name;
     }
   
    /**
     * @return the name
     */
     public String getName() {
         return name;
    }

-----------------------------------------------



JSF Managed Bean

MangedBean in JSF:

Managed Beans are the mere POJO that represents model of the JSF application and are managed by the JSF container. Managed Beans are to be registered in the JSF container through Faces Config xml in JSF1.2 and via annotations in JSF2.0 onwards. By registering it in annotation entry in the faces Config can be avoided. But still one can register managed bean in Faces Config without using annotations in JSF2.0. The criteria for managed bean are same as java bean conventions.

Registering a managed bean in Faces Config (JSF 1.2) :

<managed-bean>
                           <managed-bean-name>testBean</managed-bean-name>
                           <managed-bean-class>com.test.TestBean</managed-bean-class>
                           <managed-bean-scope>session</managed-bean-scope>
              </managed-bean>

Sample Managed Bean:

               public class TestBean {

                       private int id;
                       Private String name;

                      /** Getters and setters for Properties **/
                     
                 }


Registering in JSF2.0 :

@ManagedBean

              @RequestScoped
              public class TestBean {
              -------------------
             ---------------------------

Binding Managed Bean in XHTML:
               <h:inputText value="#{testBean.name}"></h:inputText>


Tuesday, April 3, 2012

Features in JSF2.0

New Features in JSF2.0


JSF2.0 has introduced many new features in align with its design goals. Few of the major new features are listed below.

 1. Avoid entries to Faces-Config.xml with annotations. There are new annotations added in JSF2 for declaring managed beans, scopes for managed bean. Few annotations are listed below
    • @javax.faces.bean.ManagedBean
    • @javax.faces.bean.RequestScoped
    • @javax.faces.bean.SessionScoped
    • @javax.faces.bean.ApplicationScoped
    • @javax.faces.bean.ViewScoped
    • @javax.faces.bean.NoneScoped
    • @javax.faces.validator.FacesValidator
    • @javax.faces.convert.FacesConverter  
2. Bean names are assigned with default if not explicitly stated in the @ManagedBean annotation with name attribute. In the below code, the ManagedBean annotation is not explicitly named and hence the managedbean name shall be defaulted with testBean (javaBean naming convention) 
                         @ManagedBean
                         @RequestScoped
                         public class TestBean {--------
                          -------------------------------------- 
3. Facelets are the default view technology for the JSF from JSF2.0 and JSP view technology for JSF is deprecated from JSF2.0. Facelets provides a powerful Templating for the application
4. Creating a custom component is made much easier in JSF2.0 compared to its earlier version and JSF2 brings in an enhanced resource handling

5. JSF has support to Groovy and hence all the managed bean, validators, converters, renderers shall be a based on groovy

6. Default Navigation mappings using the result of the action method. The page navigation shall be defaulted using the result of the action method. In the below piece of action method, the next page is defaulted to welcome.xhtml. By this way the navigation configuration in the Faces xml shall be avoided 

 /* * on the call of this action method, the user name is placed in the flash scope
   * and redirected to the new page.
   * @return welcome page string
   */
    public String save() {
         Flash flash=FacesContext.getCurrentInstance().getExternalContext().getFlash();
         flash.put("name",this.name);
         return "welcome";
     }

7. Ajax is enabled in JSF2.0 architecture and thus it is not necessary to depend on third party API for ajax features. Ajax shall be used using the f:ajax tag.

       <h:commandButton action="#{testBean.save}" value="submit">
                  <f:ajax execute="@form" render="@displayPanel" event="click"/>
       </h:commandButton>

8. Creating a custom component is made much easier in JSF2.0 compared to its earlier version and JSF2 brings in an enhanced resource handling.

9. JSF has support to Groovy and hence all the managed bean, validators, converters, renderers shall be a based on groovy

            

Monday, April 2, 2012

New Scopes in JSF2.x


New Scopes in JSF2.x

In JSF2, beans can defined in two additional scopes apart from the existing scopes (request, session and application scope). Those are View Scope and Flash Scope

ViewScope:
  1. Defining a bean in view scope: Bean can be defined in view scope using the annotation @ViewScoped (javax.faces.bean.ViewScoped). Beans can be defined through annotations from JSF2 and is not required to define in the faces-config.xml file.

  2. Beans of viewscope shall be alive till the current view (page) is active. That is the bean shall be alive till the user interacts with the same page and doesn’t navigate to new view (page).

  3. The scope of viewscope is higher than the request and less to session scope.

  4. If the same page is returned in the action method, the bean shall be dead and shall not be retained in view scope, since the same view is recreated again.

FlashScope:
  1. The object placed in the flash scope shall be retained till the next request cycle. Thereafter it is destroyed. It is handy and most commonly used for post-redirect-get cycle where the messages need to be transferred to the request on a redirect

  2. Placing object in a FlashScope: (in the below example also note the redirection done using the the attribute “faces-redirect=true”
  3. public String save() {
    Flash flash=FacesContext.getCurrentInstance().getExternalContext().getFlash();
    flash.put("name",this.name);
    return "welcome?faces-redirect=true";
    }

  4. The flash scoped objects shall accessed using the EL object flash.
    <h:outputLabel value="Hi #{flash.name}"</h:outputLabel>