介紹如何使用 JSF 的轉換器及驗證器, 顯示並驗證表單的資料. 此外, 也介紹如何停用(disable)及繞過(pass by)驗證器轉跳其他頁面
全文: https://hychen39.github.io/jsf_teaching/2018/11/15/JSF_Unit08.html
2018年11月14日 星期三
2018年10月31日 星期三
頁面樣板(JSF Templates)
介紹如何使用 JSF 樣板製作頁面, 使得每個頁面可以有相同的頁首, 頁尾或共同的顯示外觀。
全文參考: https://hychen39.github.io/jsf_teaching/2018/10/31/JSF_Unit07.html
全文參考: https://hychen39.github.io/jsf_teaching/2018/10/31/JSF_Unit07.html
2018年8月2日 星期四
建立 Maven 專案開發 JSF 應用程式
使用 Netbeans, 建立一個 Maven 專案, 開發 JSF 應用程式.
文章請參考: https://hychen39.gitbook.io/tech-notes/javaserver-faces/maven_jsf_project_
文章請參考: https://hychen39.gitbook.io/tech-notes/javaserver-faces/maven_jsf_project_
2018年4月24日 星期二
2017年4月27日 星期四
ui:debug 和 flash.keep 的衝突
若在 facelet 中使用 ui:debug,則在同一個 facelet 中使用 flash.keep 時無法正常顯示 flash scope 中的變數。
測試資料
References:
[1] ui:debug
[2] Flash class
測試資料
References:
[1] ui:debug
[2] Flash class
2017年2月23日 星期四
如何對 Datatable 上的某一個資料列進行編輯? - 使用 p:dataTable 元件
原理:
1. 利用 p:dataTable 中的 selection 屬性取得目前選擇的物件. selection 屬性要和 Managed Bean 的 property 綁在一起.
2. 設計一個 UI 提供使用者輸入新的資料. 這個 UI 可以是 Dialog, 也可以是 Page. 此 UI 的輸入元件會取得先前 Managed Bean Property 的資料並何其繫結在一起.
3. 在 Managed Bean 提供一個方法, 例如 saveDB(), 呼叫 EJB 的方法, 將修改後的資料儲存到資料庫中.
2017年1月30日 星期一
將 JSF Composite Component 包裝成 jar 檔供其他 Web 專案使用
1.技術問題
JSF 的 composite component (複合元件) 的功能可以組合現有 UIComponent 成為新的、重複使用的元件。可以組合成的複合元件使用、驗證器、轉換器、JSF 系統事件、及 AJAX。 完成的複合元件會包含:- facelet: 檔案名稱為新的標籤的名稱,其內容定義標籤的屬性及組合現有的元件。
- java class: 支援此複合元件執行所需要的 java 程式碼。
h:outputLabel
, h:inputText
, h:commandButton
等三個元件,再加上一個驗證器成為新的元件專門用來輸入電子郵件。
當你完成複合元件時,你可以在現有 Web 專案的 facelet 中直接使用此元件的標籤。但是,如何將此複合元件變成一個獨立的程式庫供其他的 Web 專案使用呢?
2017年1月27日 星期五
h:inputxxx 標籤所支援的 ajax behavior event 有哪些?
技術問題:
jsf 提供 f:ajax 標籤讓元件具備 Ajax 處理的能力。f:ajax 的 event 屬性要指定與攔截的客戶端的事件[1]。若沒有指定,會使用預設的事件。
h:inputText, h:inputTextArea, h:inputSecret 標籤提供哪些 ajax 事件行為呢?
參考答案:
h:inputText, h:inputTextArea, h:inputSecret 三個標籤的元件皆是屬於 javax.faces.component.EditableValueHolder 類別的元件。這類的元件的預設 ajax 事件為 valueChange。詳細的事件如下:
2017年1月2日 星期一
PrimeFaces 處理 Ajax request 過程中所產生的 callbacks 及 events
在執行 Ajax Request 的前後, 我們可以有機會執行 Javascript 完成瀏覽器上的操作。過程中的一連串的過程如下:
- User clicks button in client
onclick
JavaScript code is executed- JavaScript prepares ajax request based on
process
and current HTML DOM tree onstart
JavaScript code is executed- JavaScript sends ajax request from client to server
- JSF retrieves ajax request
- JSF processes the request lifecycle on JSF component tree based on
process
actionListener
JSF backing bean method is executedaction
JSF backing bean method is executed- JSF prepares ajax response based on
update
and current JSF component tree - JSF sends ajax response from server to client
- JavaScript retrieves ajax response
- if HTTP response status is 200,
onsuccess
JavaScript code is executed - else if HTTP response status is 500,
onerror
JavaScript code is executed
- if HTTP response status is 200,
- JavaScript performs
update
based on ajax response and current HTML DOM tree oncomplete
JavaScript code is executed
References: http://stackoverflow.com/a/20146879
2016年11月21日 星期一
Overlay Edit 的實現 - JSF
UI樣式
在表單或者表格上,顯示 Overlay Dialog,讓使用者輸入新的值,或是進行確認的動作。Instance 1
1. 點選表格上的 Edit 按鈕,將該列的欄位值預設顯示在對話框中。 2. 完成編輯後,使用者按下確認按鈕,系統顯示更新後的值。Facelets and Backing Beans
2016年6月28日 星期二
Primefaces FontAwesome 中的 mime-type 設定
使用 primefaces 中的 FontAwesome 時,要加入以下的 mine-type 至 web.xml 檔案中:
否則會產生警告訊息。
參考資料:http://forum.primefaces.org/viewtopic.php?f=3&t=42002
<mime-mapping> <extension>eot</extension> <mime-type>application/vnd.ms-fontobject</mime-type> </mime-mapping> <mime-mapping> <extension>otf</extension> <mime-type>font/opentype</mime-type> </mime-mapping> <mime-mapping> <extension>ttf</extension> <mime-type>application/x-font-ttf</mime-type> </mime-mapping> <mime-mapping> <extension>woff</extension> <mime-type>application/x-font-woff</mime-type> </mime-mapping> <mime-mapping> <extension>svg</extension> <mime-type>image/svg+xml</mime-type> </mime-mapping> <mime-mapping> <extension>ico</extension> <mime-type>image/x-icon</mime-type> </mime-mapping> <mime-mapping> <extension>woff2</extension> <mime-type>application/x-font-woff2</mime-type> </mime-mapping>
2016年3月26日 星期六
JSF References
JavaServer Faces References
General
- Java EE 7 Platform API Specification: 查詢 Java EE 相關的 API
- JavaServer Faces 2.2 Facelets Tag Library Documentation: JSF tag 文件
- Package javax.faces.component Description: 說明 javafx.faces.component 套件中的類別, 提供 class diagram.
- Java Platform, Enterprise Edition (Java EE) 7: Java EE 文件入口
- The Java EE 7 Tutorial
- TutorialsPoints: 提供許多的 Example:
- JSF HTML Tag Reference (http://www.jsftoolbox.com/): 提供 tag 的說明及 render 後的畫面。
- JSF 2.0 Tutorial (http://www.mkyong.com/) : 另一個提供 JSF 介紹的網站, 裡面的 Example 有非常詳盡的說明。
- JSF Request Life-Cycle (圖片)
Converters and Validators
About Standard JSF Converters (Oracle.com): Provide the various converter and their full class name.
Time Zone and Locale List
DateTime Converter
Date Format Pattern SyntaxTime Zone and Locale List
Validators
另一個方法, 只需使用
ResourceBundle bundle = ResourceBundle.getBundle("resources.msgs");
即可。
Immediate attribute for UICommand and UIInput components
Tips
Reset the form
How do I reset input fields after a validation failure? by John Yeary
介紹 f:ajax 中的 resetValues 屬性及 f:resetValues 標籤的使用。
在JSF 2.2 後, 提供了 f:resetValues 標籤,放在 h:command 元件中。Example:
Is It Possible to Bind An HTML5 Component (input type="“date”") To A Managed Bean Property?
HTML5 support in JSF 2.2
介紹 f:ajax 中的 resetValues 屬性及 f:resetValues 標籤的使用。
在JSF 2.2 後, 提供了 f:resetValues 標籤,放在 h:command 元件中。Example:
HTML5 and JSF
Is It Possible to Bind An HTML5 Component (input type="“date”") To A Managed Bean Property?
HTML5 support in JSF 2.2
Others
Useful posters of the GoF patterns2015年11月21日 星期六
JSF 中的 UIInput Component 也是一種 UIOutput Component. 為什麼這樣設計呢?
UIInput
元件的被設計用來顯示資料給 User 並接受請求的參數, 所以 UIInput 是 UIOutput 元件的子類別之一。參考 [1] 的說明就會清楚了.那麼, UIInput 元件如果有使用 Converter 或者 Validator,是在那個階段執行 Converter 或者 Validator 呢? 預設是在 Process Validators 階段套用 Converter 進行型別轉換及使用 Validator 進行資料驗證。
驗證通過後發生什麼事? 如果驗證通過,JSF 會 queue 一個 ValueChangeEvent 事件,並 Broadcast 到註冊的 Listener 去。
Reference:
JSF tag 中的 binding 屬性有什麼作用呢? 何時使用?
參考 StackOverflow 中的這篇文章, 瞭解 JSF 中的 Component Binding 的功能及使用時間。
What is component binding in JSF? When it is preferred to be used?
簡單來說, 當你要在 Backing Bean 中控制 UIComponent 時, 便要使用到 Component Binding 的功能。
延伸閱讀:
2015年11月10日 星期二
在 JSF Page 中如何依條件顯示特定元件
在 JSF Page 中如何依條件顯示特定元件? 例如, 當 user login 後在 nav bar 上顯示 logout icon. 若尚未login 則顯示 login icon.
請參考 Stackoverflow 中的這則討論 How to use if, else condition in jsf to display image. 可以使用的選項:
請參考 Stackoverflow 中的這則討論 How to use if, else condition in jsf to display image. 可以使用的選項:
- c:if
- c:choose
- render attribute for the UIComponent
2015年11月9日 星期一
Cookie Helper
對處理 Cookie 很煩嗎? 試試這個 Cookie Helper.
原作者: Vasil Lukach, 2014/01/05
Source: http://stackoverflow.com/questions/20934016/how-to-add-cookie-in-jsf
1: public class CookieHelper {
2: public void setCookie(String name, String value, int expiry) {
3: FacesContext facesContext = FacesContext.getCurrentInstance();
4: HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
5: Cookie cookie = null;
6: Cookie[] userCookies = request.getCookies();
7: if (userCookies != null && userCookies.length > 0 ) {
8: for (int i = 0; i < userCookies.length; i++) {
9: if (userCookies[i].getName().equals(name)) {
10: cookie = userCookies[i];
11: break;
12: }
13: }
14: }
15: if (cookie != null) {
16: cookie.setValue(value);
17: } else {
18: cookie = new Cookie(name, value);
19: cookie.setPath(request.getContextPath());
20: }
21: cookie.setMaxAge(expiry);
22: HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
23: response.addCookie(cookie);
24: }
25: public Cookie getCookie(String name) {
26: FacesContext facesContext = FacesContext.getCurrentInstance();
27: HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
28: Cookie cookie = null;
29: Cookie[] userCookies = request.getCookies();
30: if (userCookies != null && userCookies.length > 0 ) {
31: for (int i = 0; i < userCookies.length; i++) {
32: if (userCookies[i].getName().equals(name)) {
33: cookie = userCookies[i];
34: return cookie;
35: }
36: }
37: }
38: return null;
39: }
40: }
2015年8月19日 星期三
JSF 選擇式元件的使用
JSF 選擇式元件的使用
2015/08/20
簡介
介紹 h:selectManyListBox,h:selectOneListBox,h:selectOneMenu,f:selectItems
等標籤的使用方式。
使用 產生不同形式的網頁中選擇式元件,如 List
Box、Check
Box List、Radio List及Menu,參考下圖[1]:
在 的 body 中使用 f:selectItem 或者 f:selectItems
帶入可選擇的清單項目。
相較於 f:selectItem 需手動列舉項目清單,使用 f:selectItems 可以自動地將
Collection 或者 Arrary 轉成清單項目。Collection
或
Array 中的成員需是 SelectItem 物件或者 Java Object[3]。
以下說明使用 f:selectItems 的方式,一為項目清單使用 SelectItem 物件表示,另一為使用 Java Object 表示。
回傳 SelectItem Collection 產生項目清單
Backing beans
#45-47 的 getOptions() 方法傳回 SelectItem List
JSF Page
#13 中的 的 value 屬性是對應到 cashier backing bean 中的 newsLetters property。
HTML Output
Rendered Results
回傳 Java Object Collection 產生項目清單
Backing Bean
在 Company class 下定義的 Employee 子類別:
在 #41~43 定義的Company 類別的 getEmployee()
傳回
Employee List。
JSF Page
使用 取得項目清單值。 中的 value
屬性指向
backing bean 中傳回 Java Object Array 的屬性; var 屬性為
Array 中的 Object; itemLabel 設為 Object 中做為標籤名稱的
property;itemValue 設為Object 中做為標籤值的 property。
HTML Output
Rendered Result
2015年8月6日 星期四
Custom Component 簡介
Custom Component 簡介
hychen39@gmail.com
Steps to create a custom component[1]:
Step 1: 建立一個javax.faces.component.UIComponent 的子類別。使用 @FacesComponent
annotation 註冊此元件。
Step 2: 若要將元件顯示的工作委由另一個 Render
class 處理,則建立一個 javax.faces.render.Renderer 子類別。此為選項步驟。使用
@FacesRenderer annotation 註冊此
Renderer。
Step 3: 建立一個 Tag Library Descriptor,宣告使用客製元件時所使用的custom
tag。在TLD
檔中宣告客製元件的
namespace, tag name, component type,
attribute (optional)等。使用 @FacesComponent
註冊元件只能宣告元件的 namespace, tag name, 及 component
type,不能宣告元件的屬性,元件的屬性需在 TLD 檔中宣告。在 JSF2.2 以後,若使用
@FacesComponent( createTag=true)
時,若不需要標籤屬性可以不要建立
TLD 檔。TLD 檔名稱結尾需為 taglib.xml,檔案必須位置 [context_root]/WEB-INF下。此外,需在 web.xml
註冊此 TLD 檔,註冊的方式為使用 param
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/your_tag.taglib.xml</param-value>
Step 4: 在 JSF 頁面中引入客製標籤的 name space 並使用 custom
tag.
建立一個javax.faces.component.UIComponent 的子類別。
每個 custom tag 都會對應到一個 UIComponent 的子類別。實務上會建立 javax.faces.component.UIComponentBase 子類別,該子類別已實作
UIComponent class 中的抽象方法。也可以直接建立 UIOutput、UIInput、或者 UICommand
子類別,視元件的用途而定。
覆寫 UIComponentBase 的方法
當建立 UIComponentBase 子類別時,還必須覆寫其 getFamily():String 方法,傳回元件所屬的元件族群(Component Family)。JSF 會利元件所屬的元件族群及
Renderer 的 type 來選擇適合元件使用的 Render[2]。
若要元件本身要負責 Renderer 的工作,則必須負責decode 及encode
兩個階段的工作。在decode
階段需將請求中的參數取出放到元件的 submittedValue
屬性。接著再進行轉換及驗證的動作,成功後才會放到元件中的 value 屬性中(或稱 Local Value)。在 decode 階段需覆寫以下的方法:
·
decode()
在 encode 階段,要將元件中的 value 屬性的取出,並輸出成 HTML 元件。此時需覆寫以下三個方法:
·
encodeBegin()
·
encodeChildren()
·
encodeEnd()
委任 Renderer 工作給 javax.faces.render.Renderer class
若客製元件要將
Render 工作,則需將工作委外給 javax.faces.render.Renderer 類別。Renderer
類別的工作內容就是執行 decode 及 encode 兩個階段的工作。
Renderer class 的建立步驟如下:
1.
建立 javax.faces.render.Renderer子類別並覆寫 decode 及 encode 階段會被呼叫的方法,包括:
·
decode()
·
encodeBegin()
·
encodeChildren()
·
encodeEnd()
2.
在 JSF 中註冊 Renderer
3.
在 UIComponent
子類別中:
·
覆寫 getFamily():String 方法,傳回的字串需和註冊時使用的 標籤內容一致。
·
設定其 rendererType 屬性,其值需和 Step 2
所註冊的 Readerer 的 Renderer Type 一致。使用 UIComponent 的setRenderType()
設定 renderType 屬性。或者直接覆寫元件的 getRenderType():String
使其傳回註冊的 Render Type
完成上述設定後,JSF
會自動由 Render Kit 中找到指定的 Family 下的 render type 類別並自動建立物件實體讓我們使用。
Annotation 和其在 faces-config.xml
中的對應的
XML
Tag Library Descriptor
Decoding 階段會做的事及使用到的類別及方法
取得請求的 client id
facesContext.getExternalContext.getRequestParameterMap() 方法取得存放請求參數的Requests
Map。
取得 Request Map 中的參數, requestMap.get(Object Key) 或者 requestMap.containsKey(Object Key):boolean。
和 UIComponent 相關的操作
取得 client id
uIComponent.getClientID(FacesContext) 取得 UIComponent 的client
id (Return a client-side identifier for this component)
例如,下圖中的 UIComponent 的 Client id 為 monthSpinner。
取得UIComponent 中的屬性
取得 UIComponent 中的屬性 uIComponent.getAttributes().get(Object Key)。
uIComponent.getAttributes() 會傳回存放 attributes 的 map 物件。
設定 UIComponent 的 submittedValue特性及 local value
將request 的值存到
UIInput 元件的 submittedValue property,以準備進行 Validation,使用 uIInput.setSubmittedValue() 執行上述的動作[6]。這個動作是發生在 Apply Request Phase。在 Process Validators Phase,若
UIInput 中的 submittedValue 轉換並驗證通過,使用 uIInput.setValue()
將轉換後的值設定到
UIInput 元件的 Local Value 中。
觀察Request Map 中的值如何產生
以下例子說明 Request Map 中的值的產生
當按下 month spinner 的 > 按鈕時,會
submit form。Form 的 id 為 spinnerForm。在spinnerForm 中有2個 input field,其 id 分別為 spinnerForm:monthSpinner
及 spinnerForm:yearSpinner。
參考下圖,當 submit form 時,以下的參數會被提出
1.
#6 的 spinnerForm = “SpinnerForm”
2.
#14 的 spinnerForm:monthSpinner
= “1”
3.
#14 的 spinnerForm:monthSpinner.more = “>”
4.
#21 的 spinner:yearSpinner = “2010”
以下是在 Netbeans
中觀察到的 Request Map 中的值。
Encoding 階段會做的事及使用到的類別及方法
取得 Response Writer
需取得 Response Writer 將回應寫到輸出串流傳給 browser。使用 facesContext.getResponseWriter():ResponseWriter 取得
Writer。
取得 UIComponent 中的: client ID, local values 及 attributes
要取得 UIComponent
的Client
ID,使用 uIComponent.getClientID(facesContext):String。
取得 UIComponent 中的 Local
value,使用 uIComponent.getValue():Object
取得 UIComponent 中的
attribute,使用 uIComponent.getAttributes.get(Object
Key):Object
Render a HTML element
要開使輸出 HTML element,使用 responseWriter.startElement(String name, UIComponent
Component):void,其中:
·
Name: 是 HTML Tag 的元素
·
Component 是對應到此元素 UIComponent,該元件中的 pass-through attributes 會被直接寫出到 HTML 元素成為該元素的屬性。
當執行 responseWriter.startElement() 後,便可使用 responseWriter. writeAttribute(String
name, Object value, String property) 輸出該元素的屬性,其中:
·
name: HTML 元素中的屬性名稱
·
value: HTML 元素中的屬性值
結束輸出使用 responseWriter.endElement(String name)
訂閱:
文章 (Atom)