Sie sind auf Seite 1von 60

Struts to JavaServer™

Faces Architecture:
A Programmer’s Guide
Kevin Hinners
Senior Technical Analyst
FedEx Services
http://fedex.com
Session TS-3364

2005 JavaOneSM Conference | Session TS-3364 1


Goal of Talk

Learn how to migrate a Struts Web


application to a JavaServer™ Faces
architecture

2005 JavaOneSM Conference | Session TS-3664 | 2


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 3
Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 4
Struts
What is it?
• Web application framework
• JSP™ tag libraries
• Validator plug-in
• Tiles plug-in
• Internationalization

2005 JavaOneSM Conference | Session TS-3664 | 5


JavaServer Faces Architecture
What is it?
• User interface framework
• Server-side UI components
• Event model
• Component state
• Renderers
• Validation
• Type conversion
• Internationalization

2005 JavaOneSM Conference | Session TS-3664 | 6


Model View Controller
MVC pattern
• MVC Model-2 for the Web

2005 JavaOneSM Conference | Session TS-3664 | 7


Struts
Model view controller design

2005 JavaOneSM Conference | Session TS-3664 | 8


JavaServer Faces Architecture
Model view controller design

2005 JavaOneSM Conference | Session TS-3664 | 9


Struts
Benefits
• Open source
• Jakarta Apache project
• Wide industry acceptance
• Mature technology
• Controller-centric
• Tiles layout management
• Validation framework

2005 JavaOneSM Conference | Session TS-3664 | 10


Struts
Drawbacks
• Learning curve
• Framework-specific classes
• Form JavaBeans
• Unit testing is more difficult
• Rigid design

2005 JavaOneSM Conference | Session TS-3664 | 11


JavaServer Faces Architecture
Benefits
• Standard
• Developed under JSR 127
• View-centric
• Server-side component model
• Device independence
• Optimized for JSP, HTML
• Extensible
• Tool-friendly technology

2005 JavaOneSM Conference | Session TS-3664 | 12


JavaServer Faces Architecture
Drawbacks
• Immature vendor support
• Navigation model
• Tag library limitations
• Slow adoption rate

2005 JavaOneSM Conference | Session TS-3664 | 13


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary

2005 JavaOneSM Conference | Session TS-3664 | 14


DEMO
Pager Scheduling Application

2005 JavaOneSM Conference | Session TS-3664 | 15


Demo Application
Page flow diagram

2005 JavaOneSM Conference | Session TS-3664 | 16


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 17
Containment Strategy

• Objective
• Place existing Struts application code in containment
• Implementation
• Configure the project for JSF
• Any code written for the Struts framework becomes legacy
• Action and ActionForm classes, Struts tags in JSPs
• All new development work is pure JavaServer Faces
• Provide hooks to JSF-based pages
• Write managed bean classes
• Configure managed beans, navigation rules
• Create new JSPs using JSF tags

2005 JavaOneSM Conference | Session TS-3664 | 18


Containment Strategy
Configure the project for JavaServer Faces architecture
• Prerequisites
• Servlet 2.4
• JSP 2.0
• Copy jsf-api.jar, jsf-impl.jar, and Jakarta
Commons libraries to WEB-INF/lib
• Copy jsf_core.tld and html_basic.tld to
WEB-INF/tld
• Create faces-config.xml file in WEB-INF

2005 JavaOneSM Conference | Session TS-3664 | 19


Containment Strategy
Configure the project for JavaServer Faces architecture
• Add FacesServlet definition to web.xml
<servlet>
<servlet-name>faces</servlet-name>
<servlet-class>
javax.faces.webapp.FacesServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>faces</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>

2005 JavaOneSM Conference | Session TS-3664 | 20


Containment Strategy
Configure the project for JavaServer Faces architecture
• Add tag library definitions to web.xml
<taglib>
<taglib-uri>html_basic.tld</taglib-uri>
<taglib-location>
/WEB-INF/tld/html_basic.tld
</taglib-location>
</taglib>

<taglib>
<taglib-uri>jsf_core.tld</taglib-uri>
<taglib-location>
/WEB-INF/tld/jsf_core.tld
</taglib-location>
</taglib>

2005 JavaOneSM Conference | Session TS-3664 | 21


Containment Strategy
Provide hooks to JSF-based pages
<tr>
<td rowspan="3" class="formValue">&nbsp;</td>
<td class="formValue">
<html:link page="/historyAction.do?action=History">
<bean:message key="page.link.pager.history.view"/>
</html:link>
</td>
</tr>
<tr>
<td class="formValue">
<f:view>
<h:form>
<h:commandLink id="pager" action="retrieve">
<h:outputText value="Pager Maintenance"/>
</h:commandLink>
</h:form>
</f:view>
</td>
</tr> SM
2005 JavaOne Conference | Session TS-3664 | 22
Containment Strategy
Write managed beans
package com.fedex.pager.bean;

public class PagerBean {

private List pagers;

public List getPagers() {


List pagers = new ArrayList();

try {
pagers = PagerDAO.selectAll();
}
catch (SQLException e) {
logger.error("Error retrieving pager list: ", e);
}

return pagers;
}
2005 JavaOneSM Conference | Session TS-3664 | 23
Containment Strategy
Configure managed beans, navigation rules
<faces-config>
<managed-bean>
<managed-bean-name>pagerBean</managed-bean-name>
<managed-bean-class>
com.fedex.pager.bean.PagerBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/home.jsp</from-view-id>
<navigation-case>
<from-outcome>retrieve</from-outcome>
<to-view-id>/pagerList.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

2005 JavaOneSM Conference | Session TS-3664 | 24


Containment Strategy
Create new JSPs
<%@ taglib uri="html_basic.tld" prefix="h" %>
<%@ taglib uri="jsf_core.tld" prefix="f" %>

<f:view>
<f:loadBundle var="bundle" basename="resource"/>
<html>
<head>
<title>
<h:outputText value="#{bundle['maintenance-title']}"/>
</title>
<link rel="stylesheet" type="text/css"
href="html/pager.css"/>
</head>
<body>
<%@ include file="html/header.html" %>
<h1>
<h:outputText value="#{bundle.maintenance-title}"/>
</h1>
2005 JavaOneSM Conference | Session TS-3664 | 25
Containment Strategy
Create new JSPs (Cont.)
<h:form>
<h:dataTable styleClass="dataTable"
headerClass="dataHeading"
rowClasses="dataValue"
cellspacing="2" cellpadding="5"
value="#{pagerBean.pagers}"
var="pager">
<h:column>
<h:commandLink title="Edit Pager"
value="Edit" action="edit"
actionListener="#{pagerBean.editPager}">
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{bundle.pager-type}"/>
</f:facet>
<h:outputText value="#{pager.pagerType}"/>
</h:column> SM
2005 JavaOne Conference | Session TS-3664 | 26
Containment Strategy

• Consequences
• Some ongoing knowledge of Struts required
• Both Struts Web application and JSF user interface
frameworks in use
• Complex mixture of Struts, JSF tags in JSPs possible
• Easier transition
• Small learning curve
• Some transitions between Struts and JSF difficult
• Temptation to refactor requires discipline

2005 JavaOneSM Conference | Session TS-3664 | 27


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 28
Rewrite Strategy

• Objective
• Replace all existing Struts code with JSF
• Implementation
• Configure the project for JSF
• Update domain model objects (usually not required)
• Convert ActionForms to managed beans (POJO)
• Rewrite JSP pages to use JSF core and HTML tags
• Add JSF navigation rules to faces-config.xml
• Implement methods to handle actions

2005 JavaOneSM Conference | Session TS-3664 | 29


Rewrite Strategy
Convert action forms—ScheduleForm.java before
package com.fedex.pager.form;

public class ScheduleForm extends ActionForm {


private PagerVO pager;
private List contacts;
private List schedule;

public PagerVO getPager() {


return pager;
}

public void setPager(PagerVO pager) {


this.pager = pager;
}

...
}

2005 JavaOneSM Conference | Session TS-3664 | 30


Rewrite Strategy
Convert action forms—ScheduleBean.java after
package com.fedex.pager.bean;

public class ScheduleBean {


private PagerVO pager;
private List contacts;
private List schedule;
private CoverageVO coverage;

public PagerVO getPager() {


return pager;
}

public void setPager(PagerVO pager) {


this.pager = pager;
}

...
}
2005 JavaOneSM Conference | Session TS-3664 | 31
Rewrite Strategy
Convert action forms—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>scheduleBean</managed-bean-name>
<managed-bean-class>
com.fedex.pager.bean.ScheduleBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
...
</faces-config>

2005 JavaOneSM Conference | Session TS-3664 | 32


Rewrite Strategy
Rewrite JSPs—home.jsp before
<%@ taglib uri="struts-html.tld" prefix="html" %>
<%@ taglib uri="struts-bean.tld" prefix="bean" %>
<%@ taglib uri="struts-logic.tld" prefix="logic" %>
<%@ taglib uri="struts-nested.tld" prefix="nested" %>

<html>
<head>
<title>
<bean:message key="page.pager.title"/>
</title>
<link rel="stylesheet" type="text/css"
href="html/pager.css" title="Default">
</head>

<body>
<%@ include file="html/header.html" %>

<html:form action="/viewAction">
2005 JavaOneSM Conference | Session TS-3664 | 33
Rewrite Strategy
Rewrite JSPs—home.jsp after
<%@ taglib uri="html_basic.tld" prefix="h" %>
<%@ taglib uri="jsf_core.tld" prefix="f" %>

<f:view>
<f:loadBundle var="bundle" basename="resource"/>

<html>
<head>
<title>
<h:outputText value="#{bundle['page.pager.title']}"/>
</title>
<link rel="stylesheet" type="text/css"
href="html/pager.css" title="Default">
</head>

<body>
<%@ include file="html/header.html" %>

<h:form> 2005 JavaOneSM Conference | Session TS-3664 | 34


Rewrite Strategy
Add navigation rules—struts-config.xml before
<action path="/viewAction"
type="com.fedex.pager.action.ViewAction"
name="scheduleForm"
scope="request"
validate="true">
<forward name="view"
path="/view.jsp"
redirect="false"/>
</action>

2005 JavaOneSM Conference | Session TS-3664 | 35


Rewrite Strategy
Add navigation rules—faces-config.xml after
<navigation-rule>
<from-view-id>/home.jsp</from-view-id>
<navigation-case>
<from-outcome>view</from-outcome>
<to-view-id>/view.jsp</to-view-id>
</navigation-case>
</navigation-rule>

2005 JavaOneSM Conference | Session TS-3664 | 36


Rewrite Strategy
Implement actions—ViewAction.java before
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) {

ScheduleForm scheduleForm = (ScheduleForm) form;

String pagerType = request.getAttribute("pagerType");


PagerVO pager = PagerDAO.selectByType(pagerType);
scheduleForm.setPager(pager);

...

List schedule = CoverageDAO.selectByDate(startDate,


endDate, pagerType);
scheduleForm.setSchedule(schedule);

return (mapping.findForward("view"));
}
2005 JavaOneSM Conference | Session TS-3664 | 37
Rewrite Strategy
Implement actions—ScheduleBean.java after
public void viewSchedule(ActionEvent event) {

// Retrieve selected pager from the event.


UIData pagerData = (UIData)
event.getComponent().findComponent("pagerTable");
PagerVO pager = (PagerVO) pagerData.getRowData();
String pagerType = pager.getPagerType();

...

List schedule = CoverageDAO.selectByDate(startDate,


endDate, pagerType);

setPager(pager);
setSchedule(schedule);
}

2005 JavaOneSM Conference | Session TS-3664 | 38


Rewrite Strategy

• Consequences
• Initial detailed knowledge of Struts
• Experience with JavaServer Faces Architecture beneficial
• Steep learning curve
• Easy to introduce new bugs
• Clean solution
• More consistent look and feel
• Custom components may be beneficial

2005 JavaOneSM Conference | Session TS-3664 | 39


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 40
Integration Strategy

• Objective
• Use JavaServerFaces Architecture for view components and
Struts for Controller components
• Implementation
• Configure the project for JSF
• Configure the project for Struts-Faces Integration library
• Update navigation rules
• Struts Action and ActionForm classes remain largely unchanged
• Rewrite JSPs using JSF and Struts-Faces tags
• Create managed bean classes to forward to Action classes

2005 JavaOneSM Conference | Session TS-3664 | 41


Integration Strategy
Configure Struts-Faces Integration library
• Prerequisites
• JDK 1.3 or later
• Servlet 2.3 or later
• JSP 1.2 or later
• Copy struts-faces.jar to WEB-INF/lib
• Add request processor to struts-config.xml:
<controller>
<set-property property="processorClass"
value="org.apache.struts.faces.
application.FacesRequestProcessor"/>
</controller>

2005 JavaOneSM Conference | Session TS-3664 | 42


Integration Strategy
Configure Struts-Faces Integration library
• Tag Library Descriptor Option 1
• Add declaration to JSP:
<%@ taglib uri="http://struts.apache.org/tags-faces"
prefix="s" %>

2005 JavaOneSM Conference | Session TS-3664 | 43


Integration Strategy
Configure Struts-Faces Integration library
• Tag Library Descriptor Option 2
• Extract struts-faces.tld from struts-faces.jar
• Copy struts-faces.tld to WEB-INF/tld
• Add tag library definitions to web.xml:
<taglib>
<taglib-uri>stuts-faces.tld</taglib-uri>
<taglib-location>
/WEB-INF/tld/struts-faces.tld
</taglib-location>
</taglib>

• Add declaration to JSP:


<%@ taglib uri="struts-faces.tld" prefix="s" %>

2005 JavaOneSM Conference | Session TS-3664 | 44


Integration Strategy
Update navigation rules—struts-config.xml before
<action path="/viewAction"
type="com.fedex.pager.action.ViewAction"
name="scheduleForm"
scope="session"
validate="true">
<forward name="view"
path="/view.jsp"
redirect="false"/>
</action>

2005 JavaOneSM Conference | Session TS-3664 | 45


Integration Strategy
Update navigation rules—struts-config.xml after
<action path="/viewAction"
type="com.fedex.pager.action.ViewAction"
name="scheduleForm"
scope="session"
validate="true">
<forward name="view"
path="/view.faces"
redirect="false"/>
</action>

2005 JavaOneSM Conference | Session TS-3664 | 46


Integration Strategy
Rewrite JSPs—editLogin.jsp before
<%@ taglib uri="struts-html.tld" prefix="html" %>
<%@ taglib uri="struts-bean.tld" prefix="bean" %>
<%@ taglib uri="struts-logic.tld" prefix="logic" %>
<%@ taglib uri="struts-nested.tld" prefix="nested" %>
...
<body>
<html:form action="/editLoginAction">
...
<td class="formButton">
<html:submit property="action">
<bean:message key="page.button.pager.back"/>
</html:submit>
<html:submit property="action">
<bean:message key="page.button.pager.edit.login"/>
</html:submit>
</td>
...
</html:form>
</body> SM
2005 JavaOne Conference | Session TS-3664 | 47
Integration Strategy
Rewrite JSPs—editLogin.jsp after
<%@ taglib uri="html_basic.tld" prefix="h" %>
<%@ taglib uri="jsf_core.tld" prefix="f" %>
<%@ taglib uri="struts-faces.tld" prefix="s" %>

<f:view>
<f:loadBundle var="bundle" basename="resource"/>
<body>
<s:form action="/editLoginAction">
...
<h:panelGroup>
<h:commandButton immediate="true" action="back"
value="#{bundle['page.button.pager.back']}"/>
<h:commandButton actionListener="#{viewBean.login}"
value="#{bundle['page.button.pager.edit.login']}"/>
</h:panelGroup>
...
</s:form>
</body>
</f:view> SM
2005 JavaOne Conference | Session TS-3664 | 48
Integration Strategy
Create managed bean classes
package com.fedex.pager.bean;

public class ViewBean {

public void login(ActionEvent event) {


// Forward to action class.
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext external = context.getExternalContext();

try {
external.dispatch("/editLoginAction.do?action=Login");
}
catch (IOException e) {
throw new FacesException(e);
}
finally {
context.responseComplete();
}
} 2005 JavaOneSM Conference | Session TS-3664 | 49
Integration Strategy

• Consequences
• Promotes code reuse
• Leverages Struts controller-centric architecture
• Managed beans required as glue code
• Supports the use of Tiles for layout framework
• Struts and JSF knowledge required
• Integration library is not final or well-supported
• Quickest option to rewrite pages using JSF tags

2005 JavaOneSM Conference | Session TS-3664 | 50


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 51
Best Practices

• Write unit tests first


• Prevent functionality breakage when converting
• Eliminate bugs in business objects that cause
hidden errors in Web pages
• Stub out pages and navigation early
• Ensures page flow works before you dive in to code
• Minimize the use of JavaScript
• Leverage the validation frameworks that are available
• Eliminate Java code from JSPs

2005 JavaOneSM Conference | Session TS-3664 | 52


Pitfalls

• NullPointerExceptions
• Property getter returns null
• Referenced binding not found in scope
• Typos in the JSP
• NoSuchElementException
• Check managed bean and ActionForm scope
• Same page displayed when clicking button or link
• Missing navigation rule
• Missing action parameter on component

2005 JavaOneSM Conference | Session TS-3664 | 53


Agenda

Struts vs. JavaServer Faces Architecture


Application Demo
Migration Strategies
Containment Strategy
Rewrite Strategy
Integration Strategy
Best Practices/Pitfalls
Summary
2005 JavaOneSM Conference | Session TS-3664 | 54
Summary

• Shortest learning curve to using JSF in your


application is with the containment strategy
• The rewrite strategy is best used when
combined with refactoring your application
• Employ the integration strategy when you have
a significant investment in ActionForms, Actions,
and/or Tiles
• Use the strategy that best suits your
development team and project resources

2005 JavaOneSM Conference | Session TS-3664 | 55


For More Information

JavaServer Faces Architecture Specification and RI


http://java.sun.com/j2ee/javaserverfaces
Struts
http://struts.apache.org
Struts-Faces Integration library
http://tinyurl.com/aw3ha
Struts, Tiles, JSF integration
http://tinyurl.com/8dh28
JSF Central
http://www.jsfcentral.com
2005 JavaOneSM Conference | Session TS-3664 | 56
For More Information

JavaServerFaces Architecture Resources


http://www.jamesholmes.com/javaserverfaces
MyFaces
http://myfaces.apache.org
ADF Faces
http://www.tinyurl.com/6day6
Mastering JavaServer Faces Architecture
Bill Dudney, Jonathan Lehr, Bill Willis, and
Leroy Mattingly
John Wiley & Sons © 2004
2005 JavaOneSM Conference | Session TS-3664 | 57
Q&A
Kevin Hinners

2005 JavaOneSM Conference | Session TS-3664 | 58


Submit Session Evaluations
for Prizes!
Your opinions are important to Sun
• You can win a $75.00 gift certificate to the on-site
Retail Store by telling Sun what you think!
• Turn in completed forms to enter the daily drawing
• Each evaluation must be turned in the same day as
the session presentation
• Five winners will be chosen each day (Sun will send
the winners e-mail)
• Drop-off locations: give to the room monitors or use any
of the three drop-off stations in the North and South Halls
Note: Winners on Thursday, 6/30, will receive and can redeem
certificates via e-mail
2005 JavaOneSM Conference | Session TS-3664 | 59
Struts to JavaServer™
Faces Architecture:
A Programmer’s Guide
Kevin Hinners
Senior Technical Analyst
FedEx Services
http://fedex.com
Session TS-3364

2005 JavaOneSM Conference | Session TS-3364 60

Das könnte Ihnen auch gefallen