Tuesday, June 30, 2009

Shopping Cart Web Application - Part 6 - Facelets

Introduction
Facelets  (JavaServer Faces View Definition Framework) is a view technology that focuses on building JSF component trees. Facelets includes many features such as:

  • Works with JSF 1.1 and JSF 1.2, including Sun's RI and Apache MyFaces.
  • Fast Templating/Decorators for Components and Pages
  • The ability to specify UIComponent trees in separate files (UICompositions)
  • Line/Tag/Attribute precise Error Reporting
  • Full EL support, including Functions
  • Plugable Decorators to really make designer's job easy 
  • Works with any RenderKit

What you need before we get started
  • ShoppingCartFaceletsPart6 sample application. - This is an Eclipse archive file that contains two Eclipse projects. Please import these projects into your Eclipse environment. 
  • You will need the previous third party libraries that were mentioned and used in earlier parts to this tutorial
  • The following libraries need to be added to your existing Libs project

What we will cover
  • Facelets template ability
  • XHTML and JSPX
  • Shopping Cart application changes

Level
  • Beginner

Template
I am primarily using Facelets for its template ability. We have three JSP pages and each of them share common parts of the page, such as the header where the banner goes. Our site is pretty simple so there is not much to it. In the previous tutorial I used a JSP include tag to pull the header section into every JSP page. In this tutorial I am going to show you how you can define a template using Facelets and allow your pages to define which template to use.

XHTML and JSPX
One of the first things you may have noticed is that all the JSP files have been replaced by JSPX files. By default, Facelets expects pages to use the *.xhtml file extension. XHTML (The Extensible Hypertext Markup Language) is a markup language that has the same depth of expression as HTML, but also conforms to XML syntax. XHTML is a stricter and cleaner version of HTML. Unfortunately we can not use .xhtml files because Eclipse does not recognize files of this type to be used with JSF as a result Eclipse does not offer tag completion or validation for the libraries registered in the XML namespaces.


There is a work around to this and that is using the .jspx file extension as opposed to the .xhtml file extension. The tag completion in Eclipse is built to support JSPX, and all that Facelets requires is a valid XML page. Facelets is none the wiser that the XML being used is rooted as JSP. The declarations appearing in the XML namespaces now provide Eclipse with what it needs to offer tag library support while informing Facelets which components to load. The only requirement is to ensure that the corresponding TLD file for each tag library is located on the classpath. Even though Facelets does not require TLDs, Eclipse needs them to load the tag libraries definitions, as it does not understand the tag configurations used by Facelets. I copied the jsf-ui.tld tag library to the tlds folder in our WebContent/WEB-INF directory.

Shopping Cart
These are the changes I made to the Shopping Cart application in order to use Facelets:

web.xml
Set the default suffix parameter to .jspx:

<context-param>
 <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
 <param-value>.jspx</param-value>
</context-param> 

faces-config.xml
I overwrote the default view handler implementation with Facelets own view handler implementation. The view handler class is called during the Restore View and Render Response phases of the request processing lifecycle.

<application>
 <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>


Facelets Template
I created a facelets template called template.jspx. Every other page will inherit from. It contains the layout of our page as well as the header section:

Notice the facelets ui:insert tag. This tag declares a named content element to be defined by another Facelet. You will see in the pages to come that it is used with the ui:define tag to pass values between Facelets.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  version="2.0">
<ui:composition>
<html xmlns="http://www.w3.org/1999/xhtml">
<f:loadBundle var="msg" basename="Application-Resources" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>#{msg.title}</title>
<link rel="stylesheet"
 href="#{facesContext.externalContext.request.contextPath}/styles/shopping.css"
 type="text/css" />
</head>
<body>
 <div class="header"><h:outputText id="headerOutTxt"
  value="#{msg.title}" styleClass="headerOutputText" /></div>
 <p />
 <ui:insert name="body"></ui:insert>
</body>
</html>
</ui:composition>
</jsp:root>


items.jspx
There are 2 things I would like to highlight in this page, they are:
  • ui:compostion – this tag wraps content to be included in another Facelet. I use this tag to  specify which template should be applied to this page
  • ui:define – this tag is used to define the name of the content. It is used in conjunction with the insert tag specified in our template

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
    xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core" 
    version="2.0">
<ui:composition template="/template.jspx">
 <ui:define name="body">
  <h:outputText id="headingOutTxt" value="#{msg.items_txt_heading}"
   styleClass="headingOutputText" />
  <h:form id="itemListFrm">
   <h:dataTable id="itemsTbl" var="items" value="#{pc_Items.items}"
    binding="#{pc_Items.itemsTable}" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    headerClass="dataTableHeader">
    <h:column id="nameCol">
     <f:facet name="header">
      <h:outputText id="nameHeaderOutTxt"
       value="#{msg.items_txt_name_col_header}" />
     </f:facet>
     <h:outputText id="nameOutTxt" value="#{items.name}" />
    </h:column>
    <h:column id="descriptionCol">
     <f:facet name="header">
      <h:outputText id="descriptionHeaderOutTxt"
       value="#{msg.items_txt_description_col_header}" />
     </f:facet>
     <h:outputText id="descriptionOutTxt" value="#{items.description}" />
    </h:column>
    <h:column id="priceCol">
     <f:facet name="header">
      <h:outputText id="priceHeaderOutTxt"
       value="#{msg.items_txt_price_col_header}" />
     </f:facet>
     <h:outputText id="priceOutTxt" value="#{items.price}">
      <f:convertNumber pattern="#{msg.currency_pattern}" />
     </h:outputText>
    </h:column>
    <h:column id="addActionCol">
     <h:commandLink id="buyLnk" value="#{msg.items_lnk_buy}"
      action="#{pc_Items.addItemToBasket}" />
    </h:column>
   </h:dataTable>
   <p />
   <h:dataTable id="basketTbl" var="basketItem"
    value="#{shoppingViewHelper.basket.items}"
    binding="#{pc_Items.basketTable}">
    <h:column id="basketCol">
     <f:facet name="header">
      <h:outputText id="basketTblHeaderOutTxt"
       value="#{msg.items_txt_basket_header}" />
     </f:facet>
     <h:outputText id="basketItemOutTxt" value="#{basketItem.name}" />
    </h:column>
    <h:column id="removeActionCol">
     <h:commandLink id="removeLnk" value="#{msg.items_lnk_remove}"
      action="#{pc_Items.removeItemFromBasket}" />
    </h:column>
   </h:dataTable>
   <p />
   <h:commandButton id="checkoutBtn" value="#{msg.btn_checkout}"
    action="#{pc_Items.checkout}" />
  </h:form>
 </ui:define>
</ui:composition>
</jsp:root>

The same principles apply to the checkout.jspx and the payment-processed.jspx files.

Saturday, June 20, 2009

Shopping Cart Web Application - Part 5 - Web Development

Introduction
This tutorial describes the steps I took when developing and deploying the Shopping Cart web application we have used in previous tutorials. For an introduction to Java web applications I would suggest the Web Tier chapter outlined in Sun’s JEE online tutorial as well as the chapter on JSF.

What you need before we get started

    What we will cover
    • Tomat introduction 
    • Eclipse configuration
    • JSF configuration
    • Resource bundles
    • Log configurations
    • Stylesheets
    • Shopping cart application changes

    Level
    • Beginner

    Tomcat introduction


    "Apache Tomcat (or Jakarta Tomcat or simply Tomcat) is an open source servlet container developed by the Apache Software Foundation (ASF). Tomcat implements the Java Servlet and the JavaServer Pages (JSP) specifications from Sun Microsystems, and provides a "pure Java" HTTP web server environment for Java code to run."


    Configuring Tomcat in Eclipse
    I chose to have our application running off the Tomcat web server. To configure the Tomcat server in Eclipse do the following:
    • Download and install Tomcat
    • Open Eclipse
    • Navigate to: Window -> Preferences -> Server -> Runtime environments
    • Click the Add button
    • Select Apache -> Apache Tomcat v6.0
    • Check the check box that says "Create a new local server" -- this will create a server in your server view for you so you won’t have to do it later on
    • In the tomcat installation directory enter in the location where you installed tomcat, example: /opt/tomcat
    • Click the Finish button
    • Open a Server view (if not already open) by going: Window -> Show view -> Server
    • A tabbed view should appear in your workspace along with your newly created tomcat server
    • Right click on your server and say start
    • Review logs in console to see if any errors

    Create web project in Eclipse
    To create a web project in Eclipse do the following:
    • Click on File -> New -> Dynamic Web Project
    • A wizard window will appear where you can enter in values for your web application:
      • Project Name - I have called our application Shopping-cart-web-web-dev-part5)
      • Target runtime - Should have our server we created earlier in the drop down, i.e.: Apache Tomcat v6.0.18.
      • Configuration - Here you can choose different configurations for your web application. Choose Default configuration for Apache Tomcat.
      • You can go right ahead and click the Finish button. The project will be created in your workspace.
    • The next thing to do is test if the web application runs on your Tomcat server:
      • In your Servers view (if you can’t see it go to Window -> Show view -> Servers) you should see your Apache Tomcat Server. If it is not there…then what the heck are you doing here…go back to the configure the application server section man!!!
      • Right click on your server and say Add and remove projects.
      • Select the Shopping-cart-web-web-dev-part5 application and then select the Add button.
      • Select the Finish button.
      • Start / restart your server and examine the Console (logs) for any errors.
      • If no errors your application should be deployed. However there isn’t anything to see so we can’t test it in a browser. We will do that in the next step.

    Configure your application to use JSF
    • Copy the libraries you should have downloaded for this tutorial and place them in your projects lib directory (WebContent/WEB-INF/lib).
    • Open your web deployment descriptor. What is that? It is your web.xml file located in your WebContent/WEB-INF directory of your Shopping-cart-web-web-dev-part5 application. So again what is that? It is your configuration file for you web application…we put a whole lot of configuration stuff in it. And for starters we will add our JSF configurations to it. When you open the file make sure you are in the source part of it…so we can edit the text.
    • Add the faces servlet to the web.xml file:
    <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>
    

    Faces Managed Beans
    I told JSF (Faces) what java beans it should manage for me. Manage meaning to create to destroy and when and how … so when I need an instance of a faces managed been I don’t have to create it or anything JSF will do it for me.

    Remember the beans we created earlier in the Design tutorial? To tell my application that I want these Java beans to be managed by JSF I edited the JSF configuration file by adding these three beans to it. This configuration file is called faces-config-xml and can be found in your WebContent/WEB-INF directory.
    <managed-bean>
     <managed-bean-name>pc_Items</managed-bean-name>
     <managed-bean-class>com.mydomain.shoppingcart.view.Items</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>
     <managed-property>
      <property-name>shoppingViewHelper</property-name>
      <value>#{shoppingViewHelper}</value>
     </managed-property>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>pc_Checkout</managed-bean-name>
     <managed-bean-class>com.mydomain.shoppingcart.view.Checkout</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>
     <managed-property>
      <property-name>shoppingViewHelper</property-name>
      <value>#{shoppingViewHelper}</value>
     </managed-property>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>pc_Confirmation</managed-bean-name>
     <managed-bean-class>com.mydomain.shoppingcart.view.Confirmation</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>
     <managed-property>
      <property-name>shoppingViewHelper</property-name>
      <value>#{shoppingViewHelper}</value>
     </managed-property>
    </managed-bean>
    <managed-bean>
     <managed-bean-name>shoppingViewHelper</managed-bean-name>
     <managed-bean-class>com.mydomain.shoppingcart.view.ShoppingViewHelper</managed-bean-class>
     <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    

    Resource bundle
    A resource bundle is a properties file with a whole lot of words in it. It contains text used on the buttons (e.g.: OK, Submit, Cancel), labels (e.g.: First Name, Surname), messages (e.g.: There was an error processing your request), etc. Your JSP file references this resource bundle to get the words it wants to display to the user instead of having the words written in the JSP itself. You can translate your whole website into different languages by creating different language resource bundles.

    I have one English resource file called Application-Resources.properties and placed it in the src directory.

    In order to let your application load this file as the resource bundle we need to configure it in the applications configuration file, namely the web deployment descriptor (web.xml). Open the file if not already open and copy and paste the following lines of code into the file:
    <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>Application-Resources</param-value>
    </context-param>
    

    Your JSP file needs to references this resource file in order to use it. JSF has a tag that can help us out with this one:
    <f:loadBundle var="msg" basename="Application-Resources" />
    

    Before you can use any JSF tags you will need to include the JSF tag library at the top of the JSP page, e.g.:

    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
    

    Enable Log4J
    Logging is always important, and different levels of logging are also important and you also want to be able to switch on and off your logging. You don’t want System.out.println’s everywhere in your system. If you do your logs will be crowded with a lot of debugging information even when you move your application to production, this  makes the log file very large in size and it is difficult to read and track down a potential problem. Log4j is used to configure your logging settings in one properties file. You can set different levels of logging in different environments, i.e. in development you can set a level of debug (all your debug statements will be printed) and in production set a level of error (only error messages will be printed).

    It is quite simple to set this up:

    • Add the log4j library to the WEB-INF/lib directory
    • Create a file called log4j.xml and place it in your src directory. You can see an example of a log4j.xml file in the shopping-cart-web-web-dev-part5 project

    Stylesheets anyone?
    I added a stylesheet (shopping.css) to my project because hey…who doesn’t?  What is a stylesheet? A stylesheet is a file that contains styles to your website. Such as colour, font size, table widths, borders, images, e.t.c. What is the benefit of adding a stylesheet? Well since you asked the two most important benefits are:

    The content is separated from the design
    Because you are able to create a separate Stylesheet and link it to all your web documents, you have great control over how your website looks. So if you want to change a certain aspect of your page, you only need to alter one file: your Stylesheet!

    Your site uses less bandwidth and loads faster
    Stylesheets only need to load once as they are cached by the browser, your website will load much faster.

    In your JSP page you will have to create a link to the stylsheet so that the styles are applied to you page. If the link is not there your JSP page has no way of finding those styles and therefore never apply them. To link the stylesheet to your JSP you need to add this line of code within the <head> section of your JSP:
    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/shopping.css"
    type="text/css" />
    

    Shopping Cart JSP’s
    These are the three main JSP’s we are going to use for our Shopping Cart web application:

    • items.jsp - This page displays the list of shopping items to purchase
    • checkout.jsp - The checkout page that shows a summary of the items the user has added to their shopping cart and the total to how much everything costs
    • payment-processed.jsp - A page that displays a confirmation message to the user that their payment has been processed

    items.jsp
    The items.jsp is a paged created to display the list of shopping items a user can select to add to their basket. These are the key business requirements to keep in mind for this page:
    • Display the details of each item. I use a jsf datatable to render a table displaying all the items that the user can choose from. The value attribute is used to retrieve the list of items. The expression #{pc_Items.items} will invoke the getItems method in the Items class.
    • Each item must have a link associated to it so that the user can add the item to its basket. The JSF commandLink has an action attribute that defines which method to call when this link is clicked. In this case it is the doAddToBasket method in the Items class.
    • The details of the items added to the basket must be displayed below the item list table. We use another JSF datatable to display the items in the basket. The getItems method in the Basket class will be invoked when this page is rendered.
    • Each item in the basket must have a link associated to it so that the user can remove an item from the basket.
    • Finally there needs to be a button for the user to click to navigate to the checkout page. On clicking the button the method that is invoked returns the String value “checkout”. This value will determine which page will be shown next. This navigation rule is configured in the faces-config.xml file.

    checkout.jsp
    The checkout page is used as a summary and a cost breakdown page of all the items the user selected and added to their basket. The business requirements for this page are therefore:
    • Display all the details of the items the user added to their basket including the total price of how much everything cost
    • Button for the user to confirm the items and to proceed to the checkout page
    • Button used for the user to cancel the shopping and to return to the home page

    payment-processed.jsp
    The payment-processed page just displays a success message with a button for the user to go back to the home page.

    Deploying the project within Eclipse
    Compile, package and deploy the project to the Tomcat server in your Eclipse IDE. Since we already created our Tomcat server we can open up a Server view tab and see the Tomcat server we created. Right click on the server and choose “Add and Remove projects”. A new window will pop up. Select shopping-cart-web-web-dev-part5 project from the left panel and then click the “Add >” button. Click the “Finish” button. You may have to restart your server. Also if you make any changes to your project right click on the server and choose “Publish”.

    Deploying the project with Ant
    I created another build script for our web project and added a target to deploy the application to Tomcat.

    Once the application is deployed and the server is running you should be able to access the home page by opening a browser and navigating to:

    http://localhost:8080/shopping-cart-web-web-dev-part5