Thursday, December 15, 2011

Finalizing and Testing The Environment Setup.

We have finished setting up the persistence environment, and created entities to be managed.  Now we have a couple of details to complete.

We need a beans.xml file.  This file can be an empty file, but CDI injection requires it.  This file is located in: JSFDemoApp/WEB-INF/beans.xml.  This is IMPORTANT!  If you do not have it, you will pull your hair out wondering why nothing works.  Nothing says beans.xml is not found.  You will not remember you need it.  You will forget you did not create it.  etc. etc. etc. And...  (Yes, I'm rambling because I've lived this scenario several times).  Just remember to have it and I hope they fix this requirement or at least make the error more obvious.

Next we need a web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
   <context-param>
      <param-name>javax.faces.PROJECT_STAGE</param-name>
      <!-- note: set to Production because otherwise you will get a Mojarra bug that says: The form component needs to have a UIForm in its ancestry. Suggestion: enclose the necessary components within <h:form>-->
      <param-value>Production</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>
   <context-param>
      <param-name>facelets.FACELETS_SKIP_COMMENTS</param-name>
      <param-value>true</param-value>
   </context-param>
   <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>/faces/*</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name> 

        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

   <session-config>
      <session-timeout>
         30
      </session-timeout>
   </session-config>
   <welcome-file-list>
      <welcome-file>faces/startPage.xhtml</welcome-file>
   </welcome-file-list>
</web-app>

Notice the FACELETS_SKIP_COMMENTS parameter.  This tells facelets to not pass comments in your JSF page on to the rendered html page.  Considering that you may want to put private comments in your source code, you should always have this turned on.

The url-pattern tells the Faces Servlet to process any url that has faces in it.  i.e. http://localhost:8080/JSFDemoApp/faces/startPage.xhtml will be process by the Faces Servlet.  Notice we have 2 setting for url-pattern.  We could put both in one servlet-mapping, but only for serlets 2.5 or greater.  If you aren't sure what you are running, the method of declaring 2 servlet-mappings will work for all senarios.  The second one says anything that ends in .xhtml should be processed by the faces servlet.

The <session-timeout>30</session-timout> tells the JEE server to end a session after 30 minutes of inactivity.

The <welcom-file>xxx</welcome-file> tells the JEE server what page to load when a user goes to the root of the app.  I have an index.xhtml, but it is not loaded when a user goes to http://localhost:8080/JSFDemoApp.  Why?  because the welcome-file is set to faces/startPage.xhtml.  That means startPage is loaded instead.

Lastly, we need a model to test the environment, and a view to display it.  Since we are using JSF, we create a simple JSF page to display a field in a request bean that will hit the database.  The two files are:

TestBean.java:

package com.sample;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext
import javax.persistence.Query;
import javax.transaction.UserTransaction;

@ManagedBean(name = "testBean")
@RequestScoped
public class TestBean {
    @PersistenceContext(unitName = "JSFDemoPU")
    EntityManager em;
    @Resource
    UserTransaction utx;
    private static final Logger logger = Logger.getLogger("com.sample.TestBean");
    public TestBean() {
    }
    public int count() {
        List results = new ArrayList();
        logger.log(Level.FINE, "Counting how many parts are in the database.");
        try {
            logger.log(Level.FINE, "Creating a transaction.");
            utx.begin();
            PartEntity p = new PartEntity();
            logger.log(Level.FINE, "Persisting a new part.");
            em.persist(p);
            logger.log(Level.FINE, "Retrieving all parts.");
            Query q = em.createQuery("select p from PartEntity p");
            results = q.getResultList();
            logger.log(Level.FINE, "Cleaning up.");
            em.remove(p);
            utx.commit();
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Fatal error in persistence environment: ", e);
        }
        return results.size();
    }
}

And testPage.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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">
<h:head>
</h:head>
<h:body>
   Number of parts current in the database is: <h:outputText value="#{testBean.count()}"/>.</h:body>
</html>


I will leave the discussion of what is happening here to other parts of the tutorial.  These here are simply to close the loop on all the setup we have done thus far.


The directory structure for the current set of files is :
JSFDemoApp.war
|---web
|------testPage.xhtml
|------WEB-INF
|---------beans.xml
|---------web.xml
|---------classes
|------------com
|---------------sample
|------------------OrderEntity.class
|------------------OrderPartsEntity.class
|------------------PartEntity.class
|------------------TestBean.class
|------------META-INF
|---------------persistence.xml

When you navigate to http://localhost:8080/JSFDemoApp/faces/testPage.xhtml you should see:
   Number of parts current in the database is: 1.

Now you know your environment can make a round trip - from the view to the database and back again.
  This is a big hurdle.  It is very difficult to move forward if your environment is not set up correctly.  Hopefully I have given you the information required to accomplish this first task.

No comments:

Post a Comment