Creating a JSF 2 portlet

In this recipe, will create a JSF 2 portlet that creates a new stock purchase request. The portlet will also utilize JSR-303 for validating the form data before submission to the server.

Getting ready

The following are required for this recipe:

  • Apache Maven
  • An IDE of your choice
  • GateIn-3.2.0.Final-jbossas7-preview

How to do it...

To create a portlet that uses JSF 2:

  1. Create a new Maven project within your IDE, specifying Group Id: gatein.cookbook, Artifact Id: chapter10-jsf, and Packaging: war.
  2. Inside the project's pom.xml, add the following dependencies:
      <dependency>
        <groupId>javax.faces</groupId>
        <artifactId>jsf-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>javax.portlet</groupId>
        <artifactId>portlet-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-api</artifactId>
        <version>3.1.0.Alpha1</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-impl</artifactId>
        <version>3.1.0.Alpha1</version>
        <scope>runtime</scope>
      </dependency>
  3. Create an enum named Status within a package named gatein.cookbook.chapter10 with the following content:
    public enum Status {
    
      WAITING("Waiting"),
      COMPLETE("Complete"),
      CANCELLED("Cancelled");
    
      private String name;
    
      Status(String name) {
        this.name = name;
      }
    
      public String getName() {
        return this.name;
      }
    }
  4. Create an enum named TradeInstructionType within a package named gatein.cookbook.chapter10 with the following content:
    public enum TradeInstructionType {
    
      MARKET("Market"),
      LIMIT("Limit"),
      STOP_LOSS("Stop Loss"),
      TRAILING_STOP("Trailing Stop"),
      GOOD_TILL_CANCELLED("Good Till Cancelled"),
      DAY_ORDER("Day Order");
    
      private String name;
    
      TradeInstructionType(String name) {
        this.name = name;
      }
    
      public String getName() {
        return this.name;
      }
    }
  5. Create an enum named OrderType within a package named gatein.cookbook.chapter10 with the following content:
    public enum OrderType {
    
      BUY("Buy"),
      SELL("Sell");
    
      private String name;
    
      OrderType(String name) {
        this.name = name;
      }
    
      public String getName() {
        return this.name;
      }
    
    }
  6. Create a class named OrderManager within a package named gatein.cookbook.chapter10 with the following content:
    @ManagedBean
    @ApplicationScoped
    public class OrderManager implements Serializable {
    
      private static final long serialVersionUID = -5776345927432051634L;
    
      Set<Order> orders = new HashSet<Order>();
    
      public void addOrder(Order order) {
        orders.add(order);
      }
    
      public Set<Order> getOrders() {
        return orders;
      }
    
      public void setOrders(Set<Order> orders) {
        this.orders = orders;
      }
    }
  7. Create a class named Order within a package named gatein.cookbook.chapter10 with the following content:
    @ManagedBean
    @RequestScoped
    public class Order implements Serializable {
    
      private static final long serialVersionUID = -1343926602596381203L;
    
      @ManagedProperty(value = "#{orderManager}")
      private OrderManager orderManager;
    
      public Order() {
        this.status = Status.WAITING;
        this.entryDate = new Date();
      }
    
      private OrderType type;
    
      private TradeInstructionType tradeInstruction;
    
      private String accountNumber;
    
      private Integer numberStocks;
    
      private Date entryDate;
    
      private Status status;
    }
  8. Add the following getter and setter methods to Order:
      public OrderType getType() {
        return type;
      }
    
      public void setType(OrderType type) {
        this.type = type;
      }
    
      public TradeInstructionType getTradeInstruction() {
        return tradeInstruction;
      }
    
      public void setTradeInstruction(TradeInstructionType tradeInstruction) {
        this.tradeInstruction = tradeInstruction;
      }
    
      public String getAccountNumber() {
        return accountNumber;
      }
    
      public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
      }
    
      public Integer getNumberStocks() {
        return numberStocks;
      }
    
      public void setNumberStocks(Integer numberStocks) {
        this.numberStocks = numberStocks;
      }
    
      public Date getEntryDate() {
        return entryDate;
      }
    
      public void setEntryDate(Date entryDate) {
        this.entryDate = entryDate;
      }
    
      public Status getStatus() {
        return status;
      }
    
      public void setStatus(Status status) {
        this.status = status;
      }
  9. Add the following methods to Order:
      public SelectItem[] getOrderTypeValues() {
        SelectItem[] items = new 
          SelectItem[OrderType.values().length];
        int i=0;
        for (OrderType type : OrderType.values()) {
          items[i++] = new SelectItem(type, type.getName());
        }
        return items;
      }
    
      public SelectItem[] getTradeInstructionValues() {
        SelectItem[] items = new 
          SelectItem[TradeInstructionType.values().length];
        int i=0;
        for (TradeInstructionType type : 
              TradeInstructionType.values()) {
          items[i++] = new SelectItem(type, type.getName());
        }
        return items;
      }
    
      public SelectItem[] getStatusValues() {
        SelectItem[] items = new 
          SelectItem[Status.values().length];
        int i=0;
        for (Status status : Status.values()) {
          items[i++] = new SelectItem(status, status.getName());
        }
        return items;
      }
  10. Add the following methods to Order:
      public void setOrderManager(OrderManager orderManager) {
        this.orderManager = orderManager;
      }
    
      public String create() {
        orderManager.addOrder(this);
        return "orderSuccess";
      }
  11. Create layout.xhtml in the src/main/webapp/templates folder of the project.
  12. Add the following content into layout.xhtml:
    <f:view xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    
    <h:head>
    </h:head>
    
    <h:body>
    
      <div id="header">
        <ui:insert name="header">
          <h2>New Stock Purchase</h2>
        </ui:insert>
      </div>
    
      <div id="content">
        <ui:insert name="content">
        </ui:insert>
      </div>
    
    </h:body>
    </f:view>
  13. Create newOrder.xhtml in the src/main/webapp folder of the project.
  14. Add the following content into newOrder.xhtml:
    <f:view xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    
      <h:body>
        <ui:composition template="/templates/layout.xhtml">
          <ui:define name="content">
            <h:form>
              <h:panelGrid columns="2">
                <h:outputLabel value="Order Type" for="orderType" />
                <h:selectOneMenu id="orderType" value="#{order.type}" required="true">
                  <f:selectItems value="#{order.orderTypeValues}"/>
                </h:selectOneMenu>
    
                <h:outputLabel value="Trade Instruction" for="tradeInstructionType" />
                <h:selectOneMenu id="tradeInstructionType" value="#{order.tradeInstruction}" required="true">
                  <f:selectItems value="#{order.tradeInstructionValues}"/>
                </h:selectOneMenu>
    
                <h:outputLabel value="Account Number" for="acctNum" />
                <h:inputText id="acctNum" value="#{order.accountNumber}" />
    
                <h:outputLabel value="How many Stocks?" for="stocks" />
                <h:inputText id="stocks" value="#{order.numberStocks}" />
              </h:panelGrid>
              <h:commandButton action="#{order.create}" value="Create Order" />
            </h:form>
          </ui:define>
        </ui:composition>
      </h:body>
    </f:view>
  15. Create orderSuccess.xhtml in the src/main/webapp folder of the project.
  16. Add the following content into orderSuccess.xhtml:
    <f:view xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    
      <h:body>
        <ui:composition template="/templates/layout.xhtml">
              <ui:define name="header">
                 <h3>Order Success!</h3>
              </ui:define>
    
             <ui:define name="content">
                <h5>Congratulations, your order was submitted for processing</h5>
                <h:form>
                   <h:commandButton action="newOrder" value="Place another order" />
                </h:form>
             </ui:define>
          </ui:composition>
       </h:body>
    </f:view>
  17. Create portlet.xml in the src/main/webapp/WEB-INF folder of the project.
  18. Add the following content to portlet.xml:
    <?xml version="1.0" encoding="UTF-8"?><portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" 
       version="2.0">
    
      <portlet>
        <portlet-name>Order-JSF</portlet-name>
        <portlet-class>javax.portlet.faces.GenericFacesPortlet</portlet-class>
        <init-param>
          <name>javax.portlet.faces.defaultViewId.view</name>
          <value>/newOrder.xhtml</value>
        </init-param>
        <supports>
          <mime-type>text/html</mime-type>
          <portlet-mode>VIEW</portlet-mode>
        </supports>
        <portlet-info>
          <title>Order JSF Portlet</title>
        </portlet-info>
      </portlet>
    </portlet-app>

    Tip

    For an existing JSF 2 application that needs to be run as a portlet, the first, and often only, step is to add a portlet.xml file into the WEB-INF folder of the project for it to be recognized as a portlet.

  19. Create web.xml in the src/main/webapp/WEB-INF folder of the project.
  20. Add the following content to web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
      <display-name>chapter10-jsf</display-name>
    
      <context-param>
        <param-name>javax.portlet.faces.renderPolicy</param-name>
        <param-value>ALWAYS_DELEGATE</param-value>
      </context-param>
      <context-param>
        <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
        <param-value>*.xhtml</param-value>
      </context-param>
      <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
      </context-param>
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
      </servlet-mapping>
    </web-app>
  21. Create faces-config.xml in the src/main/webapp/WEB-INF folder of the project.
  22. Add the following content to faces-config.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
        version="2.1">
    
    </faces-config>
  23. Run the following command in the root of the project directory to build the web archive:
    >mvn clean package
    
  24. Copy the generated web archive, chapter10-jsf-1.0.0.SNAPSHOT.war, from the target folder into the deployment folder of where you unpacked the GateIn installation.
  25. Start the server and log in as an administrator.
  26. Click through the top-menu navigation with the following path: Group | Administration | Application Registry.
  27. Click on Import Applications to make the new portlet available.
  28. Create a new page in the Site area of the portal and add the Order-JSF portlet to it. The Order-JSF portlet can be found under the Chapter10-jsf category.
  29. Click on the Finish icon to save the page.
  30. The portlet page should look like the following screenshot:
    How to do it...
  31. Enter some data into the form and click on Create Order, and the portal page will redirect you to the Order Success! page.
    How to do it...
  32. Clicking on Place another order will return the user to a blank order form.

How it works...

Step 2 adds the JBoss Portlet Bridge dependency to the project, which enables JSF 2 to work in a portal environment.

Note

At the time of writing, the latest release of JBoss Portlet Bridge for JSF 2 is 3.1.0.Alpha1. Please check http://www.jboss.org/portletbridge for the latest available version.

Steps 3, 4, and 5 create Java enumerations for properties of an order where we have a set of valid values.

Step 6 creates OrderManager, which uses the JSF @ManagedBean annotation to specify it is a JSF backing bean, and it is also marked with @ApplicationScoped to signify that all users will see the same instance of this class. It holds a Set of orders that have been entered through the form.

Steps 7, 8, and 9 create the Order bean, which holds the details of an order. Step 7 specifies that the bean is @RequestScoped, which means there will be a new instance created for each page request. Step 7 also sets the @ManagedProperty annotation to indicate to JSF that there is a separate backing bean with the name of orderManager that should be set onto this property.

Step 9 defines some methods to convert the enum values into SelectItems for use in the JSF form. The methods are called from the <f:selectItems> tag in Step 14.

Step 10 specifies the setter associated with the @ManagedProperty, which is required for the JSF injection to work correctly. It also adds a create method to be called when the form is submitted, with the returned string representing the name of the page to navigate to next.

Steps 11 and 12 create a basic Facelet template for the portlet.

Steps 13 and 14 create the order form page in JSF. It consists of tags to specify different types of input elements, such as text and select lists. The action on the h:commandButton is set to call Order.create() when clicked, represented through the expression language names.

Steps 15 and 16 create the success page that the user is redirected to once the order has been recorded.

Steps 17 and 18 define the metadata for the portlet. The class that the portlet uses is GenericFacesPortlet, which is part of JBoss Portlet Bridge, so there is no need to create a portlet to use JSF. The init-param is important as it informs the JBoss Portlet Bridge which JSF page to display for the view Portlet Mode.

Steps 19 and 20 create the web.xml of the project. It defines the FacesServlet for JSF, determines which file suffixes are supported, and ensures that the JBoss Portlet Bridge should always delegate to JSF to render the content of the page.

See also

  • The Using portlet events in JSF 2 recipe
  • The Creating a RichFaces 4 portlet recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.159.178