ฉันกำลังทำงานร่วมกับแอพพลิเคค่อนข้างใหญ่เขียนในJSF 1.2 JSF 1.2 มีอายุประมาณ 6 ปี ฉันต้องการอัปเกรดเป็น JSF 2.0 จะเจ็บปวดขนาดไหน? ฉันสังเกตเห็นว่ามีการเปลี่ยนแปลงคุณลักษณะบางอย่างในแท็กที่กำหนดเองเป็นต้น
ฉันกำลังทำงานร่วมกับแอพพลิเคค่อนข้างใหญ่เขียนในJSF 1.2 JSF 1.2 มีอายุประมาณ 6 ปี ฉันต้องการอัปเกรดเป็น JSF 2.0 จะเจ็บปวดขนาดไหน? ฉันสังเกตเห็นว่ามีการเปลี่ยนแปลงคุณลักษณะบางอย่างในแท็กที่กำหนดเองเป็นต้น
คำตอบ:
ความเจ็บปวดจากการอัปเกรด JSF 1.2 เป็น 2.0 ขึ้นอยู่กับเทคโนโลยีมุมมองที่คุณกำลังใช้อยู่และที่คุณต้องการใช้
ไม่ว่าสวิตช์เทคโนโลยีมุมมองจะเป็นอย่างไรควรทำขั้นตอนต่อไปนี้อย่างน้อยที่สุด :
/WEB-INF/lib
(ถ้ามี)/WEB-INF/lib
(ถ้า JSF 1.2 เป็น servletcontainer ที่ให้มาคุณอาจต้องการเปลี่ยนนโยบายการโหลดคลาสเพื่อโหลดไลบรารี webapp ก่อนก่อนไลบรารี servletcontainer โปรดดูปัญหาการโหลดคลาส JSF2 ในแอ็พพลิเคชันเซิร์ฟเวอร์ด้วย )อัปเดตการประกาศรากของfaces-config.xml
เพื่อให้สอดคล้องกับข้อกำหนด JSF 2.0
<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_0.xsd"
version="2.0">
หมายเหตุ: เมื่อคุณใช้ JSF 2.2 หรือใหม่กว่าให้ใช้http://xmlns.jcp.org
โดเมนเนมสเปซแทนhttp://java.sun.com
ข้อมูลโค้ด XML ด้านบน
ตรวจสอบให้แน่ใจว่าการประกาศ root web.xml
เป็นไปตามอย่างน้อย Servlet 2.5 JSF 2.0 จะไม่ทำงานบน 2.4 หรือต่ำกว่า ( แม้ว่าจะแฮ็กได้ )
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
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_2_5.xsd"
id="YourWebappID"
version="2.5">
หมายเหตุ: เมื่อคุณใช้ Servlet 3.0 หรือใหม่กว่าให้ใช้http://xmlns.jcp.org
โดเมนเนมสเปซแทนhttp://java.sun.com
ข้อมูลโค้ด XML ด้านบน
หากคุณกำลังใช้JSP 2.xและต้องการที่จะให้ใช้มันแล้วคุณโดยทั่วไปไม่จำเป็นต้องเปลี่ยนแปลงอะไรอื่น
หากคุณใช้คำต่อท้ายurl-pattern
สำหรับสิ่งที่FacesServlet
ชอบอยู่*.jsf
แล้วคุณควรทราบว่าไฟล์FacesServlet
จะสแกนหา*.xhtml
ไฟล์ก่อนและหากไม่มีอยู่ให้สแกนหา*.jsp
ไฟล์ สิ่งนี้ช่วยให้คุณมีพื้นที่ในการค่อยๆแปลงจาก JSP เป็น Facelets เบื้องหลังโดยไม่ต้องเปลี่ยน URL
แต่ถ้าคุณใช้คำนำหน้าurl-pattern
เช่น/faces/*
และคุณต้องการค่อยๆอัปเกรดจาก JSP เป็น Facelets คุณต้องเปลี่ยนเป็น*.jsf
และอาจเป็นลิงก์ทั้งหมดในหน้า JSP ที่มีอยู่
คุณเพียงต้องจำไว้ว่า JSF 2.0 ใหม่ที่ให้การนำทางโดยนัยไม่สแกนหาไฟล์ที่มีอยู่ แต่ก็จะไปที่outcome.xhtml
อยู่ดี ดังนั้นหากคุณต้องการมาจากหรือไปที่*.jsp
คุณยังต้องรวมไว้ใน viewid ด้วยวิธี JSF 1.x
หากคุณใช้Facelets 1.xเป็นเทคโนโลยีมุมมองและต้องการใช้Facelets 2.0 ที่ให้มาด้วย JSF 2.0 คุณต้องทำตามขั้นตอนเพิ่มเติมดังต่อไปนี้:
/WEB-INF/lib
จากFaceletViewHandler
faces-config.xml
FaceletViewHandler
การใช้งานแบบกำหนดเองใด ๆจำเป็นต้องได้รับการอัปเดตเพื่อขยายViewHandlerWrapper
แทน<context-param>
ค่าที่เกี่ยวข้องกับ Facelets 1.x web.xml
ซึ่งเป็นค่าเริ่มต้นอยู่แล้วใน Facelets 2.0 เช่นเดียวjavax.faces.DEFAULT_SUFFIX
กับค่า*.xhtml
.อัปเดตการประกาศรากของ Facelet taglib XML ที่มีอยู่เพื่อให้สอดคล้องกับ Facelets 2.0
<facelet-taglib
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-facelettaglibrary_2_0.xsd"
version="2.0">
หมายเหตุ: เมื่อคุณใช้ JSF 2.2 หรือใหม่กว่าให้ใช้http://xmlns.jcp.org
โดเมนเนมสเปซแทนhttp://java.sun.com
ข้อมูลโค้ด XML ด้านบน
โดยพื้นฐานแล้วควรเป็นอย่างนั้น
หากคุณใช้JSP 2.xเป็นเทคโนโลยีมุมมองและคุณต้องการอัปเกรดเป็นFacelets 2.0ทันทีคุณจะต้องทำการเปลี่ยนแปลงมากมายก่อนที่ไซต์จะสามารถใช้งานได้ โดยพื้นฐานแล้วคุณกำลังเปลี่ยนเทคโนโลยีมุมมองที่นี่
ในทุกหน้าต้นแบบคุณต้องเปลี่ยนเทมเพลต JSP พื้นฐานต่อไปนี้ ..
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html>
<f:view>
<html lang="en">
<head>
<title>JSP page</title>
</head>
<body>
<h:outputText value="JSF components here." />
</body>
</html>
</f:view>
.. ไปยังเทมเพลต Facelets พื้นฐานต่อไปนี้:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>XHTML page</title>
</h:head>
<h:body>
<h:outputText value="JSF components here." />
</h:body>
</html>
หมายเหตุ: เมื่อคุณใช้ JSF 2.2 หรือใหม่กว่าให้ใช้http://xmlns.jcp.org
โดเมนเนมสเปซแทนhttp://java.sun.com
ข้อมูลโค้ด XHTML ด้านบน
หากหน้า JSP ที่มีอยู่ของคุณได้รับการออกแบบมาอย่างดีคุณไม่ควรมีโค้ดสคริปต์เล็ตบรรทัดใด ๆและคุณควรมี<jsp:include>
เฉพาะแท็กเฉพาะ JSP เท่านั้น สิ่งเหล่านี้จำเป็นต้องเปลี่ยนจาก:
<jsp:include page="include.jsp" />
ถึง
<ui:include src="include.xhtml" />
JSP พื้นฐานประกอบด้วยเทมเพลตเพจของ ..
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:subview id="include">
<h:outputText value="JSF components here." />
</f:subview>
.. ควรเปลี่ยนเป็น Facelets พื้นฐานต่อไปนี้รวมถึงเทมเพลตหน้า:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:outputText value="JSF components here." />
</ui:composition>
หมายเหตุ: เมื่อคุณใช้ JSF 2.2 หรือใหม่กว่าให้ใช้http://xmlns.jcp.org
โดเมนเนมสเปซแทนhttp://java.sun.com
ข้อมูลโค้ด XHTML ด้านบน
คุณต้องเปลี่ยนไฟล์ JSP TLD เป็นไฟล์ Facelets TLD ตามที่อธิบายไว้ในคู่มือการย้าย Mojarraนี้
ไม่ว่าจะใช้วิธีการย้ายข้อมูลแบบใดคุณค่อยๆกำจัดfaces-config.xml
คำอธิบายประกอบ JSF 2.0 ใหม่หรือแม้แต่CDIได้ ใด ๆ ที่<managed-bean>
สามารถข้อเขียน@ManagedBean
:
@ManagedBean(name="managedBeanName")
@RequestScoped
public class SomeBean {}
ถัดจาก@RequestScoped
นี้ยังมี@ViewScoped
, @SessionScoped
และ@ApplicationScoped
สามารถใช้ได้ หากคุณละเว้นname
แอตทริบิวต์ของแอตทริบิวต์@ManagedBean
นั้นจะเป็นค่าเริ่มต้นเป็นชื่อคลาสโดยมีอักขระตัวที่ต่ำกว่า
@ManagedBean
@RequestScoped
public class SomeBean {}
In this particular example, it will be #{someBean}
.
Any <managed-property>
can be annotated using @ManagedProperty
:
@ManagedProperty("#{otherBean}")
private OtherBean otherBean;
Any <validator>
can be annotated using @FacesValidator
:
@FacesValidator("someValidator")
public class SomeValidator implements Validator {}
Any <converter>
can be annotated using @FacesConverter
@FacesConverter("someConverter")
public class SomeConverter implements Converter {}
Any <renderer>
can be annotated using @FacesRenderer
@FacesRenderer(componentFamily="someComponentFamily", rendererType="someRendererType")
public class SomeRenderer extends Renderer {}
Any <navigation-case>
which uses the filename of the XHTML page as both <from-outcome>
and <to-view-id>
can be removed since this will be implicitly done. This can be gradually done by changing all outcome values to match the filename of the target view.
Finally, any session scoped bean which was been put in the session with the sole reason to retain the bean data in subsequent requests in the same tab/window can better be marked @ViewScoped
, because this way the bean won't be affected when the enduser opens the same page in different tabs/windows.
Note that I don't take any 3rd party componant libraries like PrimeFaces/RichFaces/IceFaces into account in this answer, it would then be impossible to write a reliable answer since it basically boils down to "it depends". In general it's sufficient to just upgrade the component library to a -by themselves verified- JSF 2.0 compatible version as per their instructions. Best is to just write unit tests, run them before and after the upgrade and fix any issues individually.
Here are at least some useful links with regard to migration of the specific component library:
PrimeFaces has no migration guide for PrimeFaces 1.x to 2.x as PrimeFaces 1.x requires Facelets 1.x already, so you just have to follow Facelets 1.x to 2.x migration steps. However, there's a PrimeFaces 2.x to 3.x (and higher) migration guide which might apply as well on migrating from PrimeFaces 1.x to 3.x (or higher). Tomahawk has also no migration guide. Basically the only which you need to change are the JARs and if necessary get rid of all <t:saveState>
references on a request scoped bean by making the bean view scoped.
javax.faces.VALIDATE_EMPTY_FIELDS
parameter to false
to get the validation sorted. See also: stackoverflow.com/questions/6113935/…
One thing to mention is that if anyone is using JSTL with JSF 1.2 then when upgrading to JSF2 you should change the namespace from:
to:
JSF 2.0 have many new features and components and I don't feel migration will be painful. Only area you will find difficult is in using thrid party libraries. If your application is heavily dependant upon libraries like Richfaces then you will face problem. Not all the components from Richfaces 3 is ported to Richfaces 4.
This also might help JSF 1.2 application migration to JSF 2.0
Also check this What is new in JSF 2?
Web.xml
Add the jars
1. jsf-api-2.0.jar
2. jsf-impl.2.0.2.jar
Step 1: Change web.xml
<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"
id="WebApp_ID" version="2.5">
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
Step 2: webmvc-config.xml
<!-- Handles requests mapped to the Spring Web Flow system -->
<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
<property name="flowExecutor" ref="flowExecutor" />
<property name="ajaxHandler">
<bean class="org.springframework.faces.webflow.JsfAjaxHandler" />
</property>
</bean>
Step3:facess-config.xml
<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_0.xsd" version="2.0">
If you are using Apache Trinidad you'll also have to upgrade it to version 2.0 so that it will support JSF 2.0. There's more info at Hacker's Valhalla.