JSF Page Navigation -...

15
JSF Page Navigation In this section, well look at how page navigation works using JSF. The examples in this section and the other sections are modified examples from courses.coresevlets.com. The first example well look at is available as jsf_ex2a.zip on your notes page. In this example, well start with a redirect from index.jsp to a page named register.jsp. register.jsp has a form on it with an action that goes back to itself. faces-config.xml will always direct output to a file named result.jsp, which the user will see no matter what. index.jsp looks like this: <% response.sendRedirect("register.faces"); %>

Transcript of JSF Page Navigation -...

Page 1: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

JSF – Page Navigation

In this section, we’ll look at how page navigation works using JSF. The examples in

this section and the other sections are modified examples from

courses.coresevlets.com.

The first example we’ll look at is available as jsf_ex2a.zip on your notes page.

In this example, we’ll start with a redirect from index.jsp to a page named

register.jsp.

register.jsp has a form on it with an action that goes back to itself.

faces-config.xml will always direct output to a file named result.jsp, which the

user will see no matter what.

index.jsp looks like this:

<% response.sendRedirect("register.faces"); %>

Page 2: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

web.xml contains this:

<?xml version = '1.0' encoding = 'windows-1252'?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee">

<description>Empty web.xml file for Web Application</description>

<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>

<filter>

<filter-name>faces-redirect-filter</filter-name>

<filter-class>FacesRedirectFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>faces-redirect-filter</filter-name>

<url-pattern>*.jsp</url-pattern>

</filter-mapping>

<session-config>

<session-timeout>35</session-timeout>

</session-config>

<mime-mapping>

<extension>html</extension>

<mime-type>text/html</mime-type>

</mime-mapping>

<mime-mapping>

<extension>txt</extension>

<mime-type>text/plain</mime-type>

</mime-mapping>

</web-app>

The servlet-mapping tag will cause all files that end with .faces to be handled by

the FacesServlet class.

Page 3: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

We now also have filter and filter-mapping tags. Any reference that has a .jsp

extension will be passed along to the FacesRedirectFiller class, which is defined

inside the project. This class will redirect to a version of the file with a .faces

extension.

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

/** Filter that redirects all requests sent to blah.jsp to blah.faces.

* Fixes the very annoying error messages you get if you access

* JSF pages with .jsp extensions. However, this filter assumes 3 things:

* The extension is .faces. You can change this in web.xml, but this

* code will not pick up the change automatically.

* You have no non-JSF JSP pages that you want to access with .jsp

* The welcome-file name is index.jsp. If the URL ends with / and the

* system forwards to a .jsp page, the filter is invoked but is not

* told the file name.

*/

public class FacesRedirectFilter implements Filter {

private final static String EXTENSION = "faces";

public void doFilter(ServletRequest req,

ServletResponse res,

FilterChain chain)

throws ServletException, IOException {

HttpServletRequest request = (HttpServletRequest)req;

HttpServletResponse response = (HttpServletResponse)res;

String uri = request.getRequestURI();

if (uri.endsWith(".jsp")) {

int length = uri.length();

String newAddress =

uri.substring(0, length-3) + EXTENSION;

//System.out.println("Redirecting to " + newAddress);

response.sendRedirect(newAddress);

} else { // Address ended in "/"

//System.out.println("Redirecting to index.faces");

response.sendRedirect("index.faces");

}

}

public void init(FilterConfig config)

throws ServletException {

}

public void destroy() {}

}

Page 4: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

register.jsp is this:

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

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

<f:view>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD><TITLE>New Account Registration</TITLE>

<LINK REL="STYLESHEET"

HREF="./css/styles.css"

TYPE="text/css">

</HEAD>

<BODY>

<CENTER>

<TABLE BORDER=5>

<TR><TH CLASS="TITLE">New Account Registration</TH></TR>

</TABLE>

<P>

<h:form>

Email address: <h:inputText/><BR>

Password: <h:inputSecret/><BR>

<h:commandButton value="Sign Me Up!" action="register"/>

</h:form>

</CENTER></BODY></HTML>

</f:view>

Notice the <h:form> tag defining the form. The action of the form is automatically

the current URL and the method is automatically POST.

Within the form, we have three form elements – inputText, inputSecret, and

commandButton. The inputText and inputSecret don’t really do anything – they

don’t even have names.

The commandButton contains a value attribute (the text inside the button) and

an action attribute (register). If we are doing static navigation, the action attribute

is just a string for the action of the commandButton.

Page 5: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

In faces-config.xml, we now have a navigation-rule tag.

<?xml version="1.0" encoding="windows-1252"?>

<!DOCTYPE faces-config PUBLIC

"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config

1.1//EN"

"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config xmlns="http://java.sun.com/JSF/Configuration">

<navigation-rule>

<from-view-id>/register.jsp</from-view-id>

<navigation-case>

<from-outcome>register</from-outcome>

<to-view-id>/WEB-INF/results/result.jsp</to-view-id>

</navigation-case>

</navigation-rule>

</faces-config>

The general form of a navigation-rule is:

<navigation-rule>

<from-view-id>/the-input-form.jsp</from-view-id>

<navigation-case>

<from-outcome>string-from-action</from-outcome>

<to-view-id>/WEB-INF/…/something.jsp</to-view-id>

</navigation-case>

</navigation-rule>

The <from-view-id> tag defines the input-form page.

For each page we might be going to, we need a <navigation-case>

The <from-outcome> defines the action, and the <to-view-id> defines the location

we’re going to. By putting the page inside /WEB-INF, it cannot be directly

accessed. The URL doesn’t change when we go to the new page – it remains

register.faces.

Note: input-form jsps can’t be put inside /WEB-INF. That’s why we use the filter –

so all .jsp files will be treated as .faces.

Page 6: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

Here, result.jsp is pretty simple:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD><TITLE>Success</TITLE>

<LINK REL="STYLESHEET"

HREF="./css/styles.css"

TYPE="text/css">

</HEAD>

<BODY>

<CENTER>

<TABLE BORDER=5>

<TR><TH CLASS="TITLE">Success</TH></TR>

</TABLE>

<H2>You have registered successfully.</H2>

</CENTER>

</BODY></HTML>

The next example will do dynamic navigation, instead of the static navigation

from the first example. We’ll use the project located in jsf_ex2b.zip on your notes

page.

We’ll again start with index.jsp, which does a redirect to signup.faces (really

signup.jsp).

<% response.sendRedirect("signup.faces"); %>

Page 7: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

signup.jsp is below. Note the empty h:inputText and h:Textarea tags. The action

of the h:commandButton is #{healthPlanController.signup}. This means

the signup property of the healthPlanController bean gets called.

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

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

<f:view>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD><TITLE>Health Plan Signup</TITLE>

<LINK REL="STYLESHEET"

HREF="./css/styles.css"

TYPE="text/css">

</HEAD>

<BODY>

<CENTER>

<TABLE BORDER=5>

<TR><TH CLASS="TITLE">Health Plan Signup</TH></TR>

</TABLE>

<P>

<h:form>

First name: <h:inputText/><BR>

Last name: <h:inputText/><BR>

SSN: <h:inputText/><BR>

Complete medical history since the day you were born:<BR>

<h:inputTextarea/><BR>

<h:commandButton

value="Sign Me Up!"

action="#{healthPlanController.signup}"/>

</h:form>

</CENTER></BODY></HTML>

</f:view>

Page 8: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

faces-config.xml:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE faces-config PUBLIC

"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config

1.1//EN"

"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

<managed-bean>

<managed-bean-name>healthPlanController</managed-bean-name>

<managed-bean-class>

HealthPlanController

</managed-bean-class>

<managed-bean-scope>request</managed-bean-scope>

</managed-bean>

<navigation-rule>

<from-view-id>/signup.jsp</from-view-id>

<navigation-case>

<from-outcome>accepted</from-outcome>

<to-view-id>/WEB-INF/results/accepted.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>rejected</from-outcome>

<to-view-id>/WEB-INF/results/rejected.jsp</to-view-id>

</navigation-case>

</navigation-rule>

</faces-config>

We again have a navigation-rule, but we now also have a managed-bean

declared. The bean has a name (the name we’ll use for the bean in our files), a

class (here it’s HealthPlanController), and a scope (here it’s request – so it stays

active with the request, as opposed to session or application).

By the way, it doesn’t matter in what order you write the <navigation-rule> nodes

and the <managed-bean> nodes.

Page 9: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

The HealthPlanController class is pretty simple – the signup method will randomly

accept or reject an applicant. Notice that the method returns a String – either

“accepted” or “rejected”.

public class HealthPlanController {

public String signup()

{

if (Math.random() < 0.2)

{

return("accepted");

}

else

{

return("rejected");

}

}

}

Let’s now look at that navigation-rule inside faces-config.xml:

<navigation-rule>

<from-view-id>/signup.jsp</from-view-id>

<navigation-case>

<from-outcome>accepted</from-outcome>

<to-view-id>/WEB-INF/results/accepted.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>rejected</from-outcome>

<to-view-id>/WEB-INF/results/rejected.jsp</to-view-id>

</navigation-case>

</navigation-rule>

So from signup.jsp, there are two navigation-cases – if the from-outcome is

“accepted”, we go to accepted.jsp. If it was “rejected”, we go to rejected.jsp.

Page 10: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

Here are these files:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD><TITLE>Accepted!</TITLE>

<LINK REL="STYLESHEET"

HREF="./css/styles.css"

TYPE="text/css">

</HEAD>

<BODY>

<CENTER>

<TABLE BORDER=5>

<TR><TH CLASS="TITLE">Accepted!</TH></TR>

</TABLE>

<H2>You are accepted into our health plan.</H2>

Congratulations.

</CENTER>

</BODY></HTML>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD><TITLE>Rejected!</TITLE>

<LINK REL="STYLESHEET"

HREF="./css/styles.css"

TYPE="text/css">

</HEAD>

<BODY>

<CENTER>

<TABLE BORDER=5>

<TR><TH CLASS="TITLE">Rejected!</TH></TR>

</TABLE>

<H2>You are rejected from our health plan.</H2>

Get lost.

</CENTER>

</BODY></HTML>

Page 11: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

Let’s think about some other things we can do.

We can use * as a wildcard in a navigation rule.

In the example below, all forms will go to success.jsp.

<navigation-rule>

<from-view-id>*</from-view-id>

<navigation-case>

<from-outcome>success</from-outcome>

<to-view-id>/WEB-INF/results/success.jsp</to-view-id>

</navigation-case>

</navigation-rule>

The following shows the advantage of doing this. We want to do the same thing

from two different views when we see “unknown-user”.

<navigation-rule>

<from-view-id>/page1.jsp</from-view-id>

<navigation-case>

<from-outcome>condition1</from-outcome>

<to-view-id>/WEB-INF/results/result1.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>unknown-user</from-outcome>

<to-view-id>/WEB-INF/results/unknown.jsp</to-view-id>

</navigation-case>

</navigation-rule>

<navigation-rule>

<from-view-id>/page2.jsp</from-view-id>

<navigation-case>

<from-outcome>condition2</from-outcome>

<to-view-id>/WEB-INF/results/result2.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-outcome>unknown-user</from-outcome>

<to-view-id>/WEB-INF/results/unknown.jsp</to-view-id>

</navigation-case>

</navigation-rule>

Page 12: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

It’s simpler like this: <navigation-rule>

<from-view-id>*</from-view-id>

<navigation-case>

<from-outcome>unknown-user</from-outcome>

<to-view-id>/WEB-INF/results/unknown.jsp</to-view-id>

</navigation-case>

</navigation-rule>

<navigation-rule>

<from-view-id>/page1.jsp</from-view-id>

<navigation-case>

<from-outcome>condition1</from-outcome>

<to-view-id>/WEB-INF/results/result1.jsp</to-view-id>

</navigation-case>

</navigation-rule>

<navigation-rule>

<from-view-id>/page2.jsp</from-view-id>

<navigation-case>

<from-outcome>condition2</from-outcome>

<to-view-id>/WEB-INF/results/result2.jsp</to-view-id>

</navigation-case>

</navigation-rule> 44

If we omit the from-outcome, it means all other return conditions match (except

for null, which always means re-display the form). So here, if we have condition1

returned, we go to result1.jsp. If null was returned, we go back to some-page.jsp.

But if anything else was returned, we go to default.jsp.

<navigation-rule>

<from-view-id>/some-page.jsp</from-view-id>

<navigation-case>

<from-outcome>condition1</from-outcome>

<to-view-id>/WEB-INF/results/result1.jsp</to-view-id>

</navigation-case>

<navigation-case>

<to-view-id>/WEB-INF/results/default.jsp</to-view-id>

</navigation-case>

</navigation-rule>

Page 13: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

If you had two commandButtons on a form (each with a different method call),

you can have a different navigation case for each. But you would then need to

have a <from-action> tag. This would allow you have a different response for the

same String that was returned.

<navigation-rule>

<from-view-id>/somepage.jsp</from-view-id>

<navigation-case>

<from-action>#{beanName.method1}</from-action>

<from-outcome>error</from-outcome>

<to-view-id>/WEB-INF/results/err1.jsp</to-view-id>

</navigation-case>

<navigation-case>

<from-action>#{beanName.method2}</from-action>

<from-outcome>error</from-outcome>

<to-view-id>/WEB-INF/results/err2.jsp</to-view-id>

</navigation-case>

</navigation-rule>

The JSF controller methods do not have direct access to request and response.

You would have to use this code to get it:

ExternalContext context =

FacesContext.getCurrentInstance().getExternalContext();

HttpServletRequest request =

(HttpServletRequest)context.getRequest();

HttpServletResponse response =

(HttpServletResponse)context.getResponse();

But, you don’t need to do this to get request parameters – these come to the

bean automatically, as we’ll see.

Page 14: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

Many errors will cause the current form to be re-displayed. This isn’t helpful in

finding a problem! Use System.out.println statements to help you figure out

where you are.

Some common errors where pushing the button causes nothing to happen:

1. Return value of controller method does not match from-outcome of navigation-case

• Remember values are case sensitive 2. Using from-action instead of from-outcome

<navigation-case> <from-action>accepted</from-action> Should be from-outcome, not from-action <to-view-id>/WEB-INF/results/accepted.jsp</to-view-id>

</navigation-case> • This is really a special case of (1), since there is now no from-outcome

3. Forgetting # in action of h:commandButton <h:commandButton

value="Button Label" action="{beanName.methodName}"/>

Should have # here • This is really a special case of (1), since action="beanName.methodName" means the literal String "beanName.methodName" is the from-outcome • In this situation and several others, it is very helpful to put a print statement in controller method to see if/when it is invoked

4. Typo in from-view-id • This is a special case of (1), since the from-outcome applies to nonexistent page

5. Controller method returns null • This is often done on purpose to redisplay the form, but can be done accidentally as well.

6. Type conversion error • You declare field to be of type int, but value is not an integer when you submit. • Behavior of redisplaying form is useful here. See validation section.

Page 15: JSF Page Navigation - faculty.strose.edufaculty.strose.edu/avitabij/cis531summer2011/notes/jsf2.pdfJSF – Page Navigation In this section, we’ll look at how page navigation works

7. Missing setter method • You associate textfield with bean property foo, but there is no setFoo method in your bean. • Debugging hint: You will see printout for bean being instantiated, but not for controller method

8. Missing h:form • If you use h:inputText with no surrounding h:form, textfields will still appear but nothing will happen when you press submit button