Академический Документы
Профессиональный Документы
Культура Документы
Available Pages
ICEfaces 2 Overview ICEfaces 2.x Release Notes ICEfaces 2.0.2 Release Notes ICEfaces 2.0.1 Release Notes ICEfaces 2.0.0 Release Notes ICEfaces 2.0.0 RC2 Release Notes ICEfaces 2.0.0 RC1 Release Notes ICEfaces 2.0.0 Beta 2 Release Notes ICEfaces 2.0.0 Beta 1 Release Notes ICEfaces-2.0.0-Alpha3 Release Notes
ICEfaces-2.0.0-Alpha2 Release Notes ICEfaces 2 Documentation ICEfaces 2 Features Getting Started Downloading ICEfaces Supported Platforms Adding ICEfaces to Your Application Building and Running ICEfaces Examples with Maven
Building and Running ICEfaces with Ant Key Concepts Automatic Ajax Direct-to-DOM Rendering Single Submit Ajax Push - Overview Core Framework Ajax Push - APIs Core Tags Annotations JavaScript Client API Handling Exceptions Configuration ICEpush Configuration
ICEfaces Components ICEfaces 2.0 Advanced Components Animation 2.0 CheckboxButton 2.0 DateTimeEntry 2.0 FileEntry 2.0 LinkButton 2.0 PushButton 2.0 SliderEntry 2.0
TabSet 2.0 ICEfaces Advanced Components Environment ACE ThemeRoller support ACE Source Artefacts and Generated Outputs ACE Meta Class ACE Component and Renderer Classes ACE Adding Resources to Meta Class ACE Skinning ACE Sprite Image Generation ACE CSS URL Mapping
API Documentation Tutorials Introductory Tutorials Creating ICEfaces 2.1 Applications with Eclipse Getting Started with ICEfaces 2 Creating ICEfaces Applications with Eclipse Converting ICEfaces 1.8 Applications to ICEfaces 2
Converting ICEfaces 1.8 Components to ICEfaces 2 ICEfaces Feature Tutorial Easy Ajax Push Using Single Submit Using Window Scope ICEfaces Component Tutorials Auto-Complete Calendar Chart Columns Connection Status Data Table Drag & Drop Effects
Page 2
Tree ICEfaces Advanced Component Tutorials Incremental Upload Processing Using FileEntryCallback General Tutorials Creating Your First Hibernate-Enabled Application Using ICEfaces with CDI Using ICEfaces with Spring Spring Web Flow 2 Spring Security Converters Creating a Composite Component Internationalization in ICEfaces Validators
Page 3
ICEfaces 2 Overview
This page last changed on Mar 16, 2011 by feras.nasser.
A New Standard
ICEfaces 2 is an open-source Rich Internet Application (RIA) development framework based on the JavaServer Faces (JSF) 2 standard. Like its predecessor, ICEfaces 1.8, ICEfaces 2 extends JSF to simplify development and enhance the standard JSF feature set - simultaneously improving developer efficiency and expanding the spectrum of RIA capabilities that can be included in any JSF-based web application. Adhering closely to the standard JSF 2 extension points allows ICEfaces to work transparently with the stock JSF framework, simplifying integration and fostering 3rd party compatibility with other JSF 2compliant libraries.
Rich Components
ICEfaces 2 offers a vast array of rich components from with to craft your user interfaces. The ICEfaces Components include all components from ICEfaces 1.8 and use a compatibility layer that enables them to function with JSF 2.0, and ICEfaces 2. These components provide a smooth migration path from ICEfaces 1.8. The ICEfaces Advanced Components leverage all the features of the JSF 2.0 component architecture, and are based on the all-new Advanced Component Environment (ACE). The YUI JavaScript library provides rich, client-side web controls, but packaged as JSF components, so you don't need to know or use any JavaScript to include them in your application. Important features of the Advanced Components include flexible form definition, UI theming/skinning, and W3C ARIA accessibility. The ICEfaces Enterprise Components are derived from the ICEfaces 1.8 Composite Component, but ported to the new JSF 2.0 Facelet architecture. Originally created by the ICEfaces application development team, these components can greatly reduce development time for a host of common application use cases. These components are available only in ICEfaces 2 Enterprise Edition.
Tools
ICEfaces 2 can be easily integrated into any Java EE development environment. In particular, IDE integration bundles are available for the open source IDEs Eclipse, and NetBeans.
Page 4
open source community, including a well-exercised code base, developer forums, and this wiki loaded with documentation and tutorials. ICEfaces is also enterprise grade software that is deployed in a wide range of Fortune 500 companies. If you need the assurances of professional support, you will get that and more from ICEfaces 2 Enterprise Edition (EE). With EE you get additional software, documentation, and deployment technologies like the Enterprise Push Server. You can learn more about the features and benefits of ICEfaces 2 EE here.
Page 5
Latest Release
Date 2011-12-22
Date 2011-05-13
Older Releases
Version ICEfaces 2.1.0 BETA 2 ICEfaces 2.1.0 BETA ICEfaces 2.0.1 ICEfaces 2.0.0
Page 6
Contents
These Release Notes include the following sections: About This Release Downloads Notable Changes Mojarra JSF 2.1.1-FCS Core Framework Changes Advanced Components Portlets Samples and Tutorials IDE Integrations Supported Platforms Known Issues Support
Downloads
ICEfaces 2.0.2 is available for download in the following formats: Binary and source-code bundles IDE Tool integration bundles Maven2 Public Repository (jars only) SVN repository checkout
Mojarra JSF 2.1.1-FCS This release has been tested against Mojarra JSF 2.1.1-FCS, and includes the JSF 2.1.1-FCS libraries in the download bundles. Note that JSF 2.1.1-FCS is referred to as 2.1.1_b04 in the public Mojarra Maven repository.
Page 7
Several issues that could cause problems when using Delta-Submit in specific circumstances have been resolved.
ICEfaces Advanced Components Support for Portlets The Advanced Components are now supported on Liferay 5.2. There remains a YUI-namespace collision issue that prevents the Advanced Components from being deployed to Liferay 6. See the Known Issues section for details. This issue is expected to be resolved with ICEfaces 2.1. Reduced JavaScript and CSS Static Footprint The Advanced Components now leverage compressed and combined JavaScript and CSS files which further reduces the number and size of the resource files that must loaded when initially visiting the page. The net result is that pages using the Advanced Components now load dramatically faster and overall response time when navigating between pages is substantially improved. A bug that prevented deploying ICEfaces applications that use ACE components to the ROOT context has been resolved. The focus indicator on the ace:sliderEntry component has been reduced in size. Previously it could grow to the width/height of the container in some browsers.
PortletFaces Bridge The included PortletFaces Bridge library has been updated to the 2.0.0 final release.
Samples & Tutorials Component Showcase Styling bugs in the panelTooltip and panelPositioned demos have been fixed.
IDE Integrations NetBeans 7 This release provides a new IDE integration for NetBeans 7. Eclipse 3.6 Eclipse 3.6 is also supported. MyEclipse 9.0.1 MyEclipse 9.0.1 will include an ICEfaces 2.0.2 integration (when released by Genuitec). Change Log For a complete list of all changes in this release, see the related JIRA Change Log.
Supported Platforms
This release has been tested on the following: JSF Runtimes Mojarra JSF 2.1.1-FCS / JSF 2.1.1-b04 This version is included in the release bundles Browsers Google Chrome 10
Page 8
Mozilla Firefox 3.6, 4.0 Microsoft IE 8, IE 9 Apple Safari 5 Application Servers Tomcat 6, 7 Glassfish 3.1 JBoss 6.0 Portal Containers Liferay Portal 5.2.3, 6.0.6 Using PortletFaces Bridge v2.0.0
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. The Delta-Submit function does not support cases where an Ajax DOM update in the browser dynamically introduces new form elements into the DOM that were not part of the form when the page was originally loaded. In order to use Delta-Submit successfully all form elements / components must be present on the page at the time the page is loaded. Due to an apparent bug in the Sun Mojarra JSF 2 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. ICEfaces Components ice:inputRichText The inputRichText component is not currently supported on IE9. This issue will be resolved in a future release. Advanced Components ace:fileEntry - occasionally the JavaScript error "Failed to load resource: javax.faces.resource/ listen.icepush.jsf" will appear in the JavaScript console after a successful file upload. This error can be ignored as it has no functional impact. Liferay Portal 6 The Advanced Components are not currently supported on Liferay Portal 6, with the exception of the fileEntry component (Liferay 5.2 is supported). Using the fileEntry component on Liferay 6 requires that the mandatoryResourceConfiguration configuration parameter be set in the web.xml as follows:
Page 9
</context-param
Mojarra JSF Note that the Mojarra JSF 2.1.0-FCS release has several serious issues that may impact your project: A bug that prevents it from supporting bean-annotation on non-Glassfish 3.1 application servers and servlet containers. Several bugs that prevent the IE9 browser from working properly with JSF-ajax operations. This release of ICEfaces includes the Mojarra JSF 2.1.1-FCS release libraries which resolves both of the issues noted above. When running a JSF application in JSF2 PROJECT_STAGE="Development" mode (which is the default setting for all ICEfaces sample applications), you may see the follow warning appear at the bottom of the page: "Form component needs to have a UIForm in its ancestry.". This issue is caused by a bug in Mojarra JSF, a suggested work-around is to set the JSF2 PROJECT_STAGE="Production" in the web.xml file. Browsers WebKit (Safari and Chrome) The WebKit-based browsers (Google Chrome and Apple Safari) request content-type "application/xhtml+xml" by default, which is different from virtually all other browsers. In cases where the application page doesn't set the contentType explicitly this can result in these browsers defaulting to a strict XHTML rendering mode, which can cause some unexpected styling and layout issues. In order to have WebKit-based browsers render markup consistently with other browsers, you must specify the content-type in the view tag on each page:
<f:view contentType="text/html">
Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See http:// jira.icefaces.org/browse/ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 (JEE 6 Platforms) It is necessary to have Mojarra JSF 2.1.0-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org.
Page 10
The ICEfaces community forums are available for questions, comments, or general discussions regarding ICEfaces 2.
Page 11
Contents
These Release Notes include the following sections: About This Release Downloads Notable Changes New Supported Platforms Core Framework Changes ICEfaces Components Advanced Components Samples and Tutorials Supported Platforms Known Issues Support
Downloads
ICEfaces 2.0.1 is available for download in the following formats: Binary and source-code bundles IDE Tool integration bundles Maven2 Public Repository (jars only) SVN repository checkout
New Supported Platforms Support for the following additional platforms is added in this release: Google Chrome 10 Mozilla Firefox 4.0
Page 12
Microsoft Internet Explorer 9 (IE 9) Oracle Glassfish 3.1 (final) JBoss 6.0 (final) Liferay Portal 5.2.3
Core Framework Lazy Window Scope Initialization Management of Window Scope requires HTTP messages to be sent to the server whenever browser navigation or window closing events occur. To avoid unnecessary network traffic, Window Scope initialization has been optimized to only perform Window Scope related HTTP transactions when Window Scope is being used by the application. Single-Submit Several improvements have been made to SingleSubmit to resolve issues with unnecessary double-submits occurring in specific circumstances. JavaScript Bridge Due to a bug in Mojarra, JSF full-page DOM updates performed via Ajax do not properly execute JavaScript included in the <HEAD> region of the page on some browsers (IEs, Firefox), resulting is unpredictable and hard-to-trace failures. A work-around for this issue has been included in this release. HTTP errors are now handled and reported by the ICEfaces bridge. There is an associated new ice.onNetworkError(callback) JavaScript Client API in support of this. It is now possible to disable the default ICEfaces error popup panels. By default, ICEfaces will report various connection or application errors in the form of popup dialog panels in the browser window. Using one of the techniques below, it is now possible to disable the default error dialogs, which is useful if you are implementing your own error reporting strategy, etc. - A new ice.disableDefaultErrorPopups JavaScript Client API is available for dynamically disabling the error popups on the client using JavaScript. - The new configuration parameter "org.icefaces.disableDefaultErrorPopups" can be specified in the web.xml file to disable the default error popups. See the Configuration topic for details. Several omissions and errors have been corrected in the JavaScript Client API topic in the ICEfaces 2 Documentation Wiki.
ICEfaces Components The JavaScript files used by the ICEfaces Components have been optimized to reduce their sizes, resulting in a 50% size savings vs. 2.0.0 (approx. 250KB). ice:dataPaginator A layout bug related to using "vertical" alignment has been fixed. ice:inputRichText Now supports the "partialSubmit" attribute. ice:outputResource Now supports the "disabled" attribute. ice:panelPopup Several issues with modal ice:panelPopups in various browsers and use-cases have been resolved. ice:selectOneMenu This component can now accept an array of Objects as input to create the list.
ICEfaces Advanced Components Reduced Static JavaScript Footprint The Advanced Components now leverage the YUI bootstrap loader which greatly reduces the number and size of the JavaScript files that must loaded when initially visiting the page. The net result is that pages using the Advanced Components now load dramatically faster and overall response time when navigating between pages is substantially improved. ace:fileEntry New support for stream-based processing of uploaded files, roughly analogous to the old ice:inputFile's outputStream property. Using this mode of operation, when files are uploaded
Page 13
they are not automatically written to the server file-system, but will instead be processed by the new FileEntryCallback interface, allowing for in-memory processing of the file. Typical usecases for this functionality are when the file may be stored in a database, needs to be virus scanned before being saved on the server, etc. The previously selected file/path information is now automatically cleared upon the successful completion of an upload. ace:slider Now supports displaying range labels on slider for min, median, and max values via the new "showLabels" attribute. All ACE input components now support the "disabled" attribute and associated skin style-classes and predefined skin styles.
Samples & Tutorials Support for building the portlet versions of various sample applications with Maven has been added in this release. Component Showcase A new demo has been added to demonstrate the use of the ice:menuItems sub-component, called "Dynamic Menu". A bug in the Output Resource demo has been fixed that caused the demo to attempt to download zero-length files. The following new tutorials are available: Using ICEfaces with CDI Using ICEfaces with Spring Security 3 Using ICEfaces with Spring WebFlow 2 Change Log For a complete list of all changes in this release, see the related JIRA Change Log.
Supported Platforms
This release has been tested on the following: JSF Runtimes Mojarra JSF 2.1.0-FCS Mojarra JSF 2.1.1-b03 JSF 2.1.1-b03 is an unofficial preview release from 3/22/2011, see Known Issues for details. This version is included in the release bundle. Browsers Google Chrome 10 Mozilla Firefox 3.6, 4.0 Microsoft IE 8, IE 9 Apple Safari 5
Application Servers Tomcat 6, 7 Glassfish 3.1 JBoss 6.0 Portal Containers Liferay Portal 5.2.3, 6.0.6 Both using PortletFacesBridge v2.0-RC1
Page 14
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. ICEfaces Components ice:inputRichText The inputRichText component is not currently supported on IE9. This issue will be resolved in the next release. Advanced Components ace:fileEntry - occasionally the JavaScript error "Failed to load resource: javax.faces.resource/ listen.icepush.jsf" will appear in the JavaScript console after a successful file upload. This error can be ignored as it has no functional impact. Portlets The Advanced Components are not currently supported for portlet development, with the exception of the fileEntry component. Using the fileEntry component on Liferay requires that the mandatoryResourceConfiguration configuration parameter be set in the web.xml as follows:
Mojarra JSF The official Mojarra JSF 2.1.0-FCS release has several serious issues that may impact your project: A bug that prevents it from supporting bean-annotation on non-Glassfish 3.1 application servers and servlet containers. Several bugs that prevent the IE9 browser from working properly with JSF-ajax operations. This release of ICEfaces includes the Mojarra JSF 2.1.1-b03 preview release libraries which resolves both of the issues noted above. It is recommended that the JSF 2.1.1-b03 libraries be used if either of the issues above will impact your project. Note that this is not an official Mojarra JSF release, so other issues may exist with it. When running a JSF application in JSF2 PROJECT_STAGE="Development" mode (which is the default setting for all ICEfaces sample applications), you may see the follow warning appear at the bottom of the page: "Form component needs to have a UIForm in its ancestry.". This issue is caused by a bug in Mojarra JSF, a suggested work-around is to set the JSF2 PROJECT_STAGE="Production" in the web.xml file.
Page 15
Browsers WebKit (Safari and Chrome) The WebKit-based browsers (Google Chrome and Apple Safari) request content-type "application/xhtml+xml" by default, which is different from virtually all other browsers. In cases where the application page doesn't set the contentType explicitly this can result in these browsers defaulting to a strict XHTML rendering mode, which can cause some unexpected styling and layout issues. In order to have WebKit-based browsers render markup consistently with other browsers, you must specify the content-type in the view tag on each page:
<f:view contentType="text/html">
Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See http:// jira.icefaces.org/browse/ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 (JEE 6 Platforms) It is necessary to have Mojarra JSF 2.1.0-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org. The ICEfaces community forums are available for questions, comments, or general discussions regarding ICEfaces 2.
Page 16
Downloads
ICEfaces 2.0 is available for download in the following formats: Binary and source-code bundles Maven2 Public Repository (jars only) SVN repository checkout
New Features
ICEfaces 2 provides some key feature enhancements over JSF 2, while inheriting all the new features available in JSF 2.
Framework Enhancements
The following framework enhancements extend the capabilities of standard JSF 2: Automatic Ajax ICEfaces 2 includes several innovative features that cumulatively result in Automatic Ajax, completely eliminating the need for developers to wire page updates together using standard JSF <f:ajax> tags. Direct-to-DOM Rendering (D2D) renders component markup to a server-side DOM that reflects the current client view. Each time the JSF lifecycle runs, a DOM comparison is done, and if there are any changes, a concise set of page updates are sent back to the client to be applied to the page. Simply adding the ICEfaces 2 library to an existing JSF 2 application will provide dynamic
Page 17
partial-page-updates for all compliant components, without the need to specify the JSF <f:ajax> component in your pages. Single Submit enables all components to automatically submit themselves base on user interaction. The JSF lifecycle executes on just that single component, and then the entire render phase is executed. From there the D2D mechanism determines the exact set of incremental page changes required in response to the Single Submit. Ajax Push Ajax Push enables real-time, multi-user collaboration in your JSF application. Any state change in the application can instantaneously push updates to other users of the application that need to be informed. New Ajax Push APIs make it simpler than ever to add collaborative features to your application. Window Scope The custom Window scope is designed to fill a gap in the existing scopes available for JSF 2.0, as it exists for the life of a browser window or tab, including surviving reloads and refreshes. Bean Management Annotations are provided that adjust the behavior of View-scoped beans. While View scope is a welcome addition for managing the lifecycle of beans, the behavior of View scope may not be intuitive in certain scenarios. Specifically, the annotations allow you to control the behavior of view-scoped beans across repeated navigation to the same view, and during view disposal. Scoped Resource Registry The ResourceRegistry allows an application to register javax.faces.application.Resource instances at run time. Each Resource is registered in a specified scope (Application, Session, View, Flash, or Window) so that the resource can be garbage collected when the scope expires. Portlet Development Portlet support in ICEfaces 2 is provided by the PortletFaces Bridge, an implementation of the JSR 329: Portlet 2.0 Bridge for JSF. The portlet bridge spec technically applies to JSF 1.2, but the PortletFaces version has been adapted to support JSF 2. The PortletFaces Bridge is tested and shipped with the ICEfaces 2 distribution and can be used to develop portlet applications with ICEfaces. JavaScript Client API In addition to enhancing the basic Ajax features provided by JSF 2, ICEfaces extends a client-side API for monitoring interesting events that occur on the client, such as form submission, event callbacks, and Ajax Push connection monitoring. Streamlined Configuration While JSF 2 simplifies configuration by leveraging annotations, ICEfaces also streamlines configuration in several areas. The ICEfaces-specific servlets and many of the configuration parameters in ICEfaces 1.x are no longer necessary with ICEfaces 2. This makes it even quicker and easier to add ICEfaces to your JSF application, and greatly reduces the possibility of lost productivity due to minor configuration errors. Minimized Dependencies ICEfaces 2 core has no 3rd-party library dependencies outside of those libraries specified in the JEE 6 "Web Profile". This further streamlines integration and software change management. Note that the ICEfaces 2 Compatibility Libraries do require additional 3rd-party libraries when used (same as those required by ICEfaces 1.8).
Page 18
Rich Components
All components used under ICEfaces 2 inherit the benefits of Automatic Ajax, including the standard JSF components. ICEfaces 2 offers a vast array of rich components beyond the standard ones available in JSF 2. The ICEfaces Components include the components from ICEfaces 1.8 and use a compatibility layer that enables them to function with JSF 2.0, and ICEfaces 2. These components provide a smooth migration path from ICEfaces 1.8. The ICEfaces Advanced Components leverage all the features of the JSF 2.0 component architecture, and are based on the all-new Advanced Component Environment (ACE). The YUI JavaScript library provides rich, client-side web controls, but packaged as JSF components, so you don't need to know or use any JavaScript to include them in your application. Important features of the Advanced Components include flexible form definition, UI theming/skinning, and W3C ARIA accessibility.
Supported Platforms
This release has been tested on the following: Mojarra JSF 2.0.3-FCS, JSF 2.0.4-b06, and JSF 2.1-b09 (Dec. 10th, 2010) Tomcat 6, 7 Glassfish 3.0, 3.1-M7 JBoss 6.0.0.CR1 Liferay Portal 6.0
(Note that any JEE6-compliant platform should work) For a complete list of all changes in this release, see the related JIRA Change Log.
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.3 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. An apparent bug in Mojarra JSF 2.0.3 (root cause not determined) causes ajax postbacks to ignore navigation. Upgrade to JSF 2.1 is required. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not present in ICEfaces 2: ice:inputFile (use ace:fileEntry instead)
Page 19
ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead)
Advanced Components Due to a bug in Mojarra JSF 2.0.x, it is not possible to use the Advanced Components in a dynamic page, such as having components be included via Facelets ui:include, with the JSF-default Partial State Saving enabled. It is required to disable Partial-State-Saving via the following context parameter in the web.xml file:
ace:fileEntry - occasionally the JavaScript error "Failed to load resource: javax.faces.resource/ listen.icepush.jsf" will appear in the JavaScript console after a successful file upload. This error can be ignored as it has no functional impact. Portlets Using ICEfaces 2.0.0 for portlet development requires the use of the included icefaces/libs/portlets/ jsf-api-2.0.4-b06a.jar, and jsf-impl-2.0.4-b06a.jar, which contain JSF fixes necessary for portlet development. The Advanced Components are not currently supported for portlet development on Liferay 6, with the exception of the fileEntry component. Using the fileEntry component on Liferay 6 requires that the mandatoryResourceConfiguration configuration parameter be set in the web.xml as follows:
See the Configuration topic for more information on mandatoryResourceConfiguration. Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 (JEE 6 Platforms) It is necessary to have Mojarra JSF 2.0.3-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Page 20
Support
Open source community support is available at http://www.icefaces.org. The ICEfaces community forums are available for questions, comments, or general discussions regarding ICEfaces 2.0.
Page 21
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.3 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. Advanced Components The Advanced Components are not currently supported for portlet development on Liferay 6, with the exception of the fileEntry component. Using the fileEntry component on Liferay 6 requires that the mandatoryResourceConfiguration configuration parameter be set in the web.xml as follows:
Page 22
See the Configuration topic for more information on mandatoryResourceConfiguration. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not present in ICEfaces 2: ice:inputFile (use ace:fileEntry instead) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead) Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 It is necessary to have Mojarra JSF 2.0.3-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 RC1 should be made in the ICEfaces Development Build Feedback forum.
Page 23
Page 24
ICEfaces Components selectInputDate calendar can now show week of year. selectInputDate can now have seconds drop down item in the date time picker. dataExporter component now works with ice:dataTables that use ice:columns for dynamic column definition. dataExporter now exports information defined in the footer of a dataTable Javascript tree update optimisations When using shortcut keys the hovered row should remain selected on newly rendered page when changed by the paginator Add title and alt attributes to dataExporter Add a tabindex attribute to the panelTabSet Update FCKEditor JS library used by ice:inputRichText to latest version Improved support for selectInputText, Drag & Drop, panelPositioned, inputRichText components when used in Portlets. General Bug Fixes. A bunch of bugs have been squashed since Beta 2. For a complete list of all changes in this release, see the related JIRA Change Log.
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.3 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. There is a regression that prevents path-style servlet mappings for the FacesServlet (e.g. /faces/*) from functioning correctly. For now, extension style mappings (e.g *.jsf) should be used instead. For details, see ICE-5366. Advanced Components The fileEntry component may log a Serialization exception to the console log in certain situations. This issue will be addressed prior to final release. The Advanced Components are not currently supported for portlet development on Liferay. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not present in ICEfaces 2: ice:inputFile (use ace:fileEntry instead) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead)
Page 25
Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 It is necessary to use Mojarra JSF 2.0.3-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 RC1 should be made in the ICEfaces Development Build Feedback forum.
Page 26
Page 27
@WindowDisposed - when found on a ViewScoped bean, that bean will be removed from the map when the browser window associated with that view is closed. See the Annotations page for details. New Core Framework APIs. The following new core framework APIs are now available: Focus Management - Enables server-side application control of the client-side focus. One-Time JavaScript Function Invocation - Enables server-side one-time execution of a client-side JavaScript function. See the ICEfaces Core API JavaDoc for more information. New Auction Example. The ICEfaces 2 'Auction' example application has been completely reimplemented to better illustrate best-practices and the use of ICEfaces 2 core framework features. General Bug Fixes. Hundreds of bugs have been squashed since Beta 1.
For a complete list of all changes in this release, see the related JIRA Change Log.
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.3 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. There is a regression that prevents path-style servlet mappings for the FacesServlet (e.g. /faces/*) from functioning correctly. For now, extension style mappings (e.g *.jsf) should be used instead. For details, see ICE-5366. Advanced Components The Advanced Components have had only basic functional testing completed on a variety of browsers, and many are missing key intended functionality in this release. The Advanced Components are not currently compatible with portlet development on Liferay due to a JavaScript namespace collision. This will be addressed in the final release. The Advanced Components may attempt to load certain .js resources directly from yahooapis.com. This issue will be corrected prior to final release. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not functional: ice:inputFile (An all-new input file component under development as a replacement to be provided in the next release (Beta2) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead) The "deltaSubmit" configuration mode is not currently supported when using the ICEfaces Compat library (icefaces-compat.jar). Application Servers Tomcat 6.0
Page 28
In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Glassfish 3 / JBoss 6 It is necessary to use Mojarra JSF 2.0.3-FCS or greater installed. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 Beta 2 should be made in the ICEfaces Development Build Feedback forum.
Page 29
(Note that any JEE6-compliant platforms should also work) Maven2 Archetype There is a new Maven2 archetype available for easily creating Maven projects using ICEfaces2 .0 - Beta 1. The archetype is available here: http://anonsvn.icefaces.org/repo/ maven2/snapshots/org/icefaces/icefaces-compat-webapp-archetype/ For more information, usage instructions, etc. see ICE-5324.
Page 30
significant bandwidth reduction while remaining completely transparent to the JSF lifecycle and application. The deltaSubmit mode is particularly useful when dealing with large forms that may be submitted for many small, incremental changes, and also when limited bandwidth is available, such as when connecting via a dial-up connection or ship-to-shore uplink, etc. See the Configuration page for details. Expanded Encoding Support. ICEfaces now supports all character encodings generally supported by the Java platform. Previously, it was a requirement for ICEfaces pages to use the UTF-8 encoding. Mojarra JSF v2.0.3 Support. This release includes the Mojarra JSF 2.0.3 JSF runtime libraries, and has been tested on both JSF 2.0.2 and JSF 2.0.3. General Bug Fixes. Lots of bugs squashed since Alpha 3. For a complete list of all changes in this release, see the related JIRA Change Log.
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0 - use Facelets. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.2 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The "ice:form" component must be used (in place of "h:form") when using the ICEfaces 1.8 Compatibility components. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not functional: ice:inputFile (An all-new input file component under development as a replacement to be provided in the next release (Beta2) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead) The "deltaSubmit" configuration mode is not currently supported when using the ICEfaces Compat library (icefaces-compat.jar). Application Servers Tomcat 6.0 In some cases, when running Tomcat on Windows, undeploying an ICEfaces 2 compatible application (i.e. that includes the icefaces-compat.jar) can cause an exception. See ICE-5222 for additional information about this issue. To prevent this, include a context.xml file with your application that includes the following Context attributes to prevent jar and resource locking:
Page 31
Glassfish 3 / JBoss 6 It is necessary to use Mojarra JSF 2.0.2-FCS, or 2.0.3-FCS specifically with this release. This may require updating the JSF Mojarra runtime libraries in Glassfish 3 or JBoss 6, depending on which JSF version is currently installed.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 Beta1 should be made in the ICEfaces Development Build Feedback forum.
Page 32
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0, use Facelets instead. It is required to specify "h:head" and "h:body" tags in your ICEfaces application pages. Due to an apparent bug in the Sun Mojarra JSF 2.0.2 runtime library, component binding is not reliable when used within a View scope. The recommended workaround is to use the ICEfaces "Window" or JSF "Session" scopes instead if component-binding is required. Alternatively, applications can be modified to avoid the requirement for using component-binding in View scope by
Page 33
using techniques similar to that used in the Data Paginator demo section of Compatible Component Showcase application. For details, see ICE-5226. 1.8.x Compatibility In ICEfaces 2.0, the "Request" scope is the "standard" JSF Request scope, and not the "Extended" Request scope that was the default in ICEfaces 1.x.. This change may result in failures for ICEfaces 1.x applications that relied on the Extended Request Scope behavior that are being moved to ICEfaces 2.0. The workaround for this issue is to adopt one of "View", "Window", or "Session" scopes in JSF/ICEfaces 2.0 instead. The "ice:form" component must be used (in place of "h:form") when using the ICEfaces 1.8 Compatibility components. See ICE-5090 for details. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not functional. ice:inputFile (An all-new input file component is planned as a replacement to be provided in the next release) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead) ICEpush ICEpush is limited to a single push application per server. Viewing multiple ICEfaces push applications in the same browser from the same host server concurrently will result in only one of the applications having functional push capabilities. Application Servers Tomcat 6.0 Including icepush.jar causes exception when redeploying application on Tomcat6.0 on WinXP. See ICE-5222 for a configuration work-around.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 Alpha should be made in the ICEfaces Development Build Feedback forum.
Page 34
Known Issues
The following section describes the most commonly encountered known issues with this release: General JSPs are not supported by ICEfaces 2.0, use Facelets instead. Due to a bug in the Sun Mojarra JSF 2 runtime library, navigation between ICEfaces and nonICEfaces pages is not working in this release. It is anticipated that the upcoming Mojarra JSF v2.0.3 release will correct this issue. See ICE-5157 for details. In some cases an NullPointerException may be logged against the org.icefaces.application.WindowScopeManager.
Page 35
This runtime error can be safely ignored. 1.8.x Compatibility The ice:inputFile component in the ICEfaces 1.8.2 Component Suite is not functional in this release. The following ICEfaces 1.8.2 Component Suite components are deprecated for ICEfaces 2.0 and are not functional. JSF 2.0 provides suitable replacements for these that should be used instead. ice:outputDeclaration (use Facelets standard approach instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead) The "ice:form" component must be used (in place of "h:form") when using the "ice" components via the ICEfaces 1.8 Compatibility components. See ICE-5090 for details. Due to a bug in the Sun Mojarra JSF 2 runtime library, component binding does not work when used within a View scope with the partial submit feature provided by the ICEfaces 1.8 compatibility library. See ICE-5226 for details. ICEpush ICEpush is limited to a single push application per server in this release. Viewing multiple ICEfaces push applications in the same browser from the same host server concurrently will result in only one of the applications having functional push capabilities. Applications using the PushRender (or SessionRenderer in the compatibility library) may experience sporadic premature time-outs of related push groups, causing the push-updates to stop functioning. A page reload will correct the problem. See ICE-227 for details. Application Servers Glassfish 3 When interacting with an ICEfaces 2 application on Glassfish 3, the warning below may be logged, with no impact on the application functionality:
WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /basic, because request parameters have already been read, or ServletRequest.getReader() has already been called.
Tomcat 6.0 Including icepush.jar causes exception when redeploying application on Tomcat6.0 on WinXP. See ICE-5222 for a configuration work-around.
Support
Open source community support is available at http://www.icefaces.org. All questions, comments, or general discussions specific to ICEfaces 2.0 Alpha should be made in the ICEfaces Development Build Feedback forum.
Page 36
ICEfaces 2 Documentation
This page last changed on Mar 30, 2011 by ken.fyten.
General Documentation
ICEfaces 2 Features Getting Started Downloading ICEfaces Supported Platforms Adding ICEfaces to Your Application Building and Running ICEfaces Examples with Maven Building and Running ICEfaces with Ant Key Concepts Automatic Ajax Direct-to-DOM Rendering Single Submit Ajax Push - Overview Core Framework Ajax Push - APIs Core Tags Annotations JavaScript Client API Handling Exceptions Configuration ICEpush Configuration JSF Configuration Components ICEfaces Components ICEfaces 2.0 Advanced Components - Animation 2.0 - CheckboxButton 2.0 - DateTimeEntry 2.0 - FileEntry 2.0 - LinkButton 2.0 - PushButton 2.0 - SliderEntry 2.0 - TabSet 2.0 ICEfaces Advanced Components - Accordion - AccordionPane - Ajax - Animation - CellEditor - CheckboxButton - ConfirmationDialog - ContextMenu - Column - ColumnGroup - DataTable - Data Model Lifecycle - DataExporter - DateTimeEntry - Dialog - Draggable - Droppable - ExcludeFromExport - FileEntry - LinkButton - MaskedEntry - Menu and Menubar - MenuButton - MenuItem - NotificationPanel
Page 37
Panel Printer ProgressBar PushButton Row RowEditor RowExpander RowPanelExpander SliderEntry Submenu TabSet Tooltip ICEfaces Advanced Components Environment - ACE ThemeRoller support - ACE Source Artefacts and Generated Outputs - ACE Meta Class - ACE Component and Renderer Classes - ACE Adding Resources to Meta Class - ACE Skinning - ACE Sprite Image Generation - ACE CSS URL Mapping - ACE Disabled Styling Standard Portlet Development ICEfaces 1.x Compatibility API Documentation
-
Page 38
ICEfaces 2 Features
This page last changed on Feb 11, 2011 by steve.maryka.
New Features
ICEfaces 2 provides some key feature enhancements over JSF 2, while inheriting all the new features available in JSF 2.
JSF 2
JSF 2 brings many beneficial features over JSF 1.2. There is a wealth of JSF 2 documentation available on-line, but for a concise overview of new features in JSF 2, look here. The high points are enumerate below. Facelets is now a first-class citizen of the JSF spec, and is the principle view declaration language in JSF 2. A comprehensive composite component model enables easy development of components using only markup. Ajax request processing and partial page updates have been incorporated into the JSF lifecycle. Partial State Saving drastically reduces state saving overhead. Broader support for system events is available. Improved navigation support includes implicit, conditional and preemptive navigation. HTTP GET now fully supported in the JSF lifecycle. New scopes, and support for custom scopes (see ICEfaces Window Scope). Annotations simplify configuration. Standardized resource loading is provided. Exception handling has been improved.
ICEfaces 2
ICEfaces 2 extends and simplifies JSF development in several key ways.
Framework Enhancements
The following framework enhancements extend the capabilities of the standard JSF 2 framework. Automatic Ajax ICEfaces 2 includes several innovative features that cumulatively result in Automatic Ajax, completely eliminating the need for developers to wire page updates together using standard JSF <f:ajax> tags. Direct-to-DOM Rendering (D2D) renders component markup to a server-side DOM that reflects the current client view. Each time the JSF lifecycle runs, a DOM comparison is done, and if there are any changes, a concise set of page updates are sent back to the client to be applied to the page. Simply adding the ICEfaces 2 library to an existing JSF 2 application will provide dynamic partial-page-updates for all compliant components, without the need to specify the JSF <f:ajax> component in your pages. Single Submit enables all components to automatically submit themselves based on user interaction. The JSF lifecycle executes on just that single component, and then the entire render phase is executed. From there the D2D mechanism determines the exact set of incremental page changes required in response to the Single Submit. Ajax Push Ajax Push enables real-time, multi-user collaboration in your JSF application. Any state change in the application can instantaneously push updates to other users of the application that need to be informed. New Ajax Push APIs make it simpler than ever to add collaborative features to your application.
Page 39
Window Scope The custom Window scope is designed to fill a gap in the existing scopes available for JSF 2.0, as it exists for the life of a browser window or tab, including surviving reloads and refreshes. Bean Management Annotations are provided that adjust the behavior of View-scoped beans. While View scope is a welcome addition for managing the lifecycle of beans, the behavior of View scope may not be intuitive in certain scenarios. Specifically, the annotations allow you to control the behavior of view-scoped beans across repeated navigation to the same view, and during view disposal. Scoped Resource Registry The ResourceRegistry allows an application to register javax.faces.application.Resource instances at run time. Each Resource is registered in a specified scope (Application, Session, View, Flash, or Window) so that the resource can be garbage collected when the scope expires. Portlet Development Portlet support in ICEfaces 2 is provided by the PortletFaces Bridge, an implementation of the JSR 329: Portlet 2.0 Bridge for JSF. The portlet bridge spec technically applies to JSF 1.2, but the PortletFaces version has been adapted to support JSF 2. The PortletFaces Bridge is tested and shipped with the ICEfaces 2 distribution and can be used to develop portlet applications with ICEfaces. Client APIs In addition to enhancing the basic Ajax features provided by JSF 2, ICEfaces extends a client-side API for monitoring interesting events that occur on the client, such as form submission, event callbacks, and Ajax Push connection monitoring. Streamlined Configuration While JSF 2 simplifies configuration by leveraging annotations, ICEfaces also streamlines configuration in several areas. The ICEfaces-specific servlets and many of the configuration parameters in ICEfaces 1.x are no longer necessary with ICEfaces 2. This makes it even quicker and easier to add ICEfaces to your JSF application, and greatly reduces the possibility of lost productivity due to minor configuration errors. Minimized Dependencies ICEfaces 2 core has no 3rd-party library dependencies outside of those libraries specified in the JEE 6 "Web Profile". This further streamlines integration and software change management. Note that the ICEfaces 2 Compatibility Libraries do require additional 3rd-party libraries when used (same as those required by ICEfaces 1.8).
Rich Components
All components used under ICEfaces 2 inherit the benefits of Automatic Ajax, including the standard JSF components. ICEfaces 2 offers a vast array of rich components beyond the standard ones available in JSF 2. The ICEfaces Components include all components from ICEfaces 1.8 and use a compatibility layer that enables them to function with JSF 2.0, and ICEfaces 2. These components provide a smooth migration path from ICEfaces 1.8. The ICEfaces Advanced Components leverage all the features of the JSF 2.0 component architecture, and are based on the all-new Advanced Component Environment (ACE). The YUI JavaScript library provides rich, client-side web controls, but packaged as JSF components, so you don't need to know or use any JavaScript to include them in your application. Important features of the Advanced Components include flexible form definition, UI theming/skinning, and W3C ARIA accessibility. The ICEfaces Enterprise Components are derived from the ICEfaces 1.8 Composite Component, but ported to the new JSF 2.0 Facelet architecture. Originally created by the ICEfaces application
Page 40
development team, these components can greatly reduce development time for a host of common application use cases. These components are available only in ICEfaces 2 Enterprise Edition.
Page 41
Getting Started
This page last changed on Dec 09, 2010 by steve.maryka.
Getting Started
This section describes where to get ICEfaces 2, how to run the examples, and how to get started using ICEfaces 2 to develop your own applications. Downloading ICEfaces Supported Platforms Adding ICEfaces to Your Application Building and Running ICEfaces Examples with Maven Building and Running ICEfaces with Ant
Page 42
Downloading ICEfaces
This page last changed on Dec 09, 2010 by steve.maryka.
Downloading ICEfaces
Download Bundles
The latest official release of all ICEfaces products, including ICEfaces 2, can be found on the ICEfaces Downloads page. These download bundles are available in both binary and source form and include all the libraries and examples for each release.
Maven Repository
For Maven users, the ICEfaces 2 pre-release libraries are available via the ICEfaces Maven2 Snapshot repository. Note that the download bundles also contain Maven .pom and archetype files to enable easy import of the ICEfaces libraries and example applications into a local Maven repository.
Subversion
ICEfaces releases may be exported in source-code form from the public SVN Repository.
Page 43
Supported Platforms
This page last changed on Dec 09, 2010 by steve.maryka.
Supported Platforms
ICEfaces 2 has been tested to run on the following:
Application Servers
Glassfish 3 JBoss 6 Tomcat 6 & 7 (by including the JSF 2.0 runtime libraries in the project) ICEfaces 2.0 should be deployable on any JEE 6 Web Profile compliant platform. Additional testing and support of Application Servers is available in ICEfaces EE.
Portal Containers
Liferay 6
Page 44
Configuration
The ICEfaces 2 core framework (icefaces.jar), ICEpush (icepush.jar), and ICEfaces Advanced Components (icefaces-ace.jar) do not require any additional configuration beyond what JSF 2 requires. Simply ensure you have the FacesServlet is declared appropriately in your web.xml file:
<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>*.jsf</url-pattern> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping> <!-- More efficient, in an AJAX environment, to have server side state saving -->
Page 45
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <!-- HTML comments become components unless they're stripped --> <context-param> <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name> <param-value>true</param-value> </context-param>
If you are using the ICEfaces Components (icefaces-compat.jar) in your application, the following additional configuration steps are required: Required web.xml entries
<!-- If you're using ice:gmap component, you'll need your own key here --> <context-param> <param-name>com.icesoft.faces.gmapKey</param-name> <paramvalue>ABQIAAAADlu0ZiSTam64EKaCQr9eTRTOTuQNzJNXRlYRLknj4cQ89tFfpxTEqxQnVWL4k55OPICgF5_SOZE06A </param-value> </context-param> <!-- Many of the ICEfaces Components make use of the Resource Servlet --> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- These specific mappings are necessary for the Resource Servlet to function properly --> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping> </web-app>
3rd Party Dependencies If you are using the ICEfaces Components you will also require additional 3rd party libraries. Libraries servlet-profile : Tomcat web-profile : JBoss 6, Glassfish 3 ? ?
? ? ? ? ?
Page 46
krysalis-jCharts-1.0.0alpha-1.jar
Optional Configuration
With ICEfaces 2 there is no need for a faces-config.xml file, but if you are using one in your application or for your own components, remember to use the new schema for JSF 2:
And if you are specifying your own components, use the new Facelets Taglib schema as well:
Advanced Configuration
ICEfaces 2.0 provides a number of configuration parameters that need not be adjusted for typical applications, but may be useful for diagnostic purposes or in special cases. These parameters are fully documented in the Configuration section.
Page 47
Building ICEfaces
ICEfaces source jars can only be built by ant at this time. If you have downloaded the Source distribution bundle of ICEfaces 2, you will need to compile and build the ICEfaces libraries before using them. The ICEfaces 2 Binary distribution bundle comes with prebuilt ICEfaces libraries so building is not necessary. To build ICEfaces, open a console or shell and navigate to the "icefaces" directory where you unzipped the ICEfaces distribution. Then, in the console, type the following and press Enter:
This builds all of the ICEfaces libraries and sample applications suitable for deployment to any JEE 6 Web Profile platform, such as Glassfish 3. There is currently no requirement or support for a maven build of the actual ICEfaces jars. The maven support in this distribution is for the building of applications which use ICEfaces, and uses maven2.
Simply add this repository to your application pom.xml. If you are unable to download them for any reason, they can be installed in your local maven repository, which is specified in [icefaces2.install.dir]/icefaces/core/build.properties. If you have not already done so, be sure to get the maven library that allows ant to perform this task:
ant get-maven
The [icefaces2.install.dir]/icefaces/maven2 folder contains a build script, as well as the poms to install all the required icefaces jars in your local mvn repository. The ant script commands are:
ant install
Page 48
and press Enter. This will build the example and place the packaged war into the /target folder of that example. There are currently two profiles for each of these examples. One is servlet-profile and the other is web-profile. Basically servlet-profile means that the jsf jars are packaged within the war for deployment to a server that does not contain these jars already (e.g. Tomcat 6). The web-profile target indicates that the jsf jars will not be packaged with the war for deployment to a JEE6 Web Profile platform which already provides the libraries. Review each pom to see what the default profile is, but designating profiles is as simple as
Component Suite Example The examples under the [icefaces2.install.dir]/icefaces/compat/samples/compat directory use the ICEfaces Component Suite for ICEfaces 2. The main example is the Component Showcase - a version of the original ICEfaces 1.8 Component Showcase ported to run on ICEfaces 2. To run any of the compatibility examples, open a console or shell and navigate to the directory (e.g. [icefaces2.install.dir]/icefaces/compat/samples/compat/componentshowcase), and type:
And press Enter. This will build this example for Tomcat or any other container requiring JSF 2 jars with the war. OR
Page 49
And press Enter. This will build the example for Glassfish V3.x or any other container not requiring JSF 2 jars with the war.
AuctionMonitor with the Component Suite components
The example under the [icefaces2.install.dir]/icefaces/compat/samples/auctionMonitor directory use the ICEfaces Component Suite for ICEfaces 2. The AuctionMonitor example builds exactly the same way as the Component Suite example. Advanced Component Example There is a showcase example of the Advanced Components available under:
icefaces/ace/samples/showcase/ace
Each example is the same to build with Maven as noted in the previous examples. Portlet examples There are portlet versions of several of the sample applications. They exist in the same directory as the non-portlet example but are named by appending "-portlet" to the directory name. These include:
Each example is the same to build with Maven as noted in the previous examples. You can find more information on Portlets and the examples under Portlet Development. Auction example Located at [icefaces2.install.dir]/icefaces/samples/core/auction, this is an example of icepush used in conjunction with ICEfaces 2 with standard h:components. Again there are two profiles and the build commands are the same.
Depending on your IDE, you can just add it to your list of subversion repositories in your IDE. If you are not using an IDE, then please see the following article on using maven archetypes:http://maven.apache.org/guides/introduction/introduction-to-archetypes.html
Maven Archetypes
Three maven archetypes are now available for ICEfaces2.0. Templates, backing beans, configuration and two profiles for lighter application servers like Tomcat (requiring jsf jars included in the war deployment),
Page 50
or an ee application server (which already contains the jsf-2.0 jars). All three archetypes are all currently available on the snapshots repository (which is already listed above).
ICEfaces2.0 Classic Components Webapp
Archetype used to generate a basic ICEfaces2.0 example with navigation pane and 2 contents pages with compat components. The following information is required:-
Used to generate an example application which contains a navigation pane as well as content pages showing ace component usage.
This archetype creates sample applications which also includes the navigation pane, but shows the use of both ACE and compat components as well as the configuration required to run both.
Netbeans:-
Steps: Choose File -> New Project. Select Maven then Maven Project, Click Next. Click Add and enter in the following values: 1. 2. 3. 4. 5. 6. Group ID: org.icefaces Artifact ID: icefaces-compat-webapp-archetype Version: 2.0.0 Repository: http://anonsvn.icefaces.org/repo/maven2/snapshots/ Click OK, then Next. Enter in Project Name and other information.
Click Finish.
Page 51
Building ICEfaces
If you have downloaded the Source distribution bundle of ICEfaces 2, you will need to compile and build the ICEfaces libraries before using them. The ICEfaces 2 Binary distribution bundle comes with prebuilt ICEfaces libraries so building is not necessary. To build ICEfaces, open a console or shell and navigate to the "icefaces" directory where you unzipped the ICEfaces distribution. Then, in the console, type the following and press Enter:
This builds all of the ICEfaces libraries and sample applications suitable for deployment to any JEE 6 Servlet Profile platform, such as Tomcat 6/7 and Jetty 7. If you'd like to build specific pieces of the distribution, type:
ant -p
to get a list of the available targets (e.g. ant core). It's recommended that you build everything the first time to ensure all the required libraries are created.
ant servlet-profile
ant web-profile
This includes icefaces.jar and icepush.jar. Properties can also be used with the ant command to exclude the related .jar files from the .war file:
Page 52
The "no-icefaces" property excludes all ICEfaces and ICEpush related .jar files where the "no-icepush" property only excludes the ICEpush related .jar file. JSF 2 Examples The examples under [icefaces2.install.dir]/icefaces/samples/core do not use the ICEfaces Component Suite. These applications use only standard JSF 2 components enhanced with the core ICEfaces framework. As such, they require far fewer library dependencies. The main example is Auction - a version of the original ICEfaces 1.8 Auction Monitor application ported to run on ICEfaces 2 but modified to use only JSF standard components and ICEpush. To run any of the pure JSF 2 examples, open a console or shell and navigate to the directory (e.g. [icefaces2.install.dir]/ icefaces/samples/core/auction), type:
ant -p
And press Enter. This displays a list of build targets for various platforms.
Component Suite Example
The examples under the [icefaces2.install.dir]/icefaces/samples/compat directory use the ICEfaces Component Suite for ICEfaces 2. The main example is the Component Showcase - a version of the original ICEfaces 1.8 Component Showcase ported to run on ICEfaces 2. To run any of the compatibility examples, open a console or shell and navigate to the directory (e.g. [icefaces2.install.dir]/icefaces/samples/compat/component-showcase), and type:
ant -p
And press Enter. This displays a list of build targets for various platforms. The resulting .war files of the Compat samples includes the icefaces-compat.jar as an ICEfaces related .jar file. Using the "no-icefaces" property additionally excludes the icefaces-compat.jar.
Advanced Component Example
icefaces/samples/ace/showcase
To see a list of the available build targets, navigate to the directory in your shell or console and type:
ant -p
then press Enter. This displays a list of build targets for various platforms.
Page 53
The resulting .war files of the ACE samples includes the icefaces-ace.jar as an ICEfaces related .jar file. Using the "no-icefaces" property additionally excludes the icefaces-ace.jar.
Page 54
Key Concepts
This page last changed on Oct 29, 2010 by ken.fyten.
Page 55
Automatic Ajax
This page last changed on Jan 18, 2012 by ted.goddard.
Definition
Automatic Ajax is a mechanism in the ICEfaces framework that calculates precise/minimal page updates from one JSF lifecyle to the next, eliminating the need for standard JSF <f:ajax> tags in the page.
<h:form> <h:panelGrid columns="1"> <h:inputText id="myinput" value="#{myBean.value}"> <f:ajax execute="@this" event="blur" render="myoutput"/> </h:inputText> <h:outputText id="myoutput" value="#{myBean.value}"/> </panelGrid> </h:form>
The sequence of events resulting in a page update based on this markup is illustrated below.
1. 2. 3. 4.
User interacts with the input field and tabs out of it. onBlur event causes <f:ajax> tag to execute. Ajax Request is generated back to application. JSF lifecycle executes on the inputText component only, updating the model.
Page 56
5. JSF render phase runs on outputText component only. 6. Response is generated with page update containing markup associated with outputText. 7. DOM update is applied to the outputText text field in the DOM. The application of <f:ajax> is simple in a trivial use case such as this, but as page complexity increases so does the complexity of defining appropriate <f:ajax> tags, and if you get it wrong, your application can become ill behaved.
In the final analysis, it proves unreasonable to wire <f:ajax> tags into a complex page to achieve optimal/minimal page updates. It becomes necessary to wire together broader regions of a page that may need updating based on some event, resulting in larger page updates than actually required.
but does not update the entire page, as the D2D mechanism intercepts the page update and calculates the precise, minimal set of updates required. In the ICEfaces Advanced Components, Single Submit is controlled through the singleSubmit attribute. For other components, the <icecore:singleSubmit> tag can wrap any number of components and enable them for single submission. Returning now to our trivial example, the JSF markup in an ICEfaces page would look like:
<h:form> <icecore:singleSubmit> <h:panelGrid columns="1"> <h:inputText id="myinput" value="#{myBean.value}"/> <h:outputText id="myoutput" value="#{myBean.value}"/> </panelGrid>
Page 57
</icecore:singleSubmit> </h:form>
The sequence of events resulting in a page update based on this markup is illustrated below.
1. 2. 3. 4. 5. 6. 7.
User interacts with the input field and tabs out of it. onBlur event cause singleSubmit to occur on inputText. Ajax Request is generated from singleSubmit. JSF lifecycle executes on the inputText component only, and model is updated. JSF render phase runs on entire component tree producing a server-side DOM. DOM differences are calculated and page update to outputText is generated in the response. DOM update is applied to the outputText text field in the DOM.
The beauty of this solution is that regardless of how complex the page becomes, minimal additional markup is required to ensure it behaves properly. You only needs to define what components are enabled with singleSubmit, and the ICEfaces framework does the rest.
<h:form> <icecore:singleSubmit> <h:panelGrid columns="1"> <h:inputText id="myinput" value="#{myBean.value}"> <f:ajax execute="@this" event="blur" render="myoutput"/> </h:inputText> <h:outputText id="myoutput" value="#{myBean.value}"/> </panelGrid> </icecore:singleSubmit>
Page 58
</h:form>
Of course, this sort of optimization is unnecessary in such a trivial example, but could prove useful in more complex pages. Most importantly, it is an optimization, not a necessity. Optimizations can be applied near the end of the development cycle, when the characteristics of the application are well understood, and proper behavior has been well established.
Page 59
Direct-to-DOM Rendering
This page last changed on Feb 16, 2011 by steve.maryka.
Definition
Direct-to-DOM (D2D) rendering is a mechanism that renders a JSF component tree into a W3C standard DOM. When the rendered DOM is cached between JSF lifecyles, it can be used to compute the difference between 2 successive page views, to determine a precise set of DOM changes required to update the page from one view to the next. D2D rendering is core to the Automatic Ajax feature of the ICEfaces 2.0 framework.
D2D Fundamentals
Rendering
D2D rending does just what it says, it renders a JSF component tree directly into a DOM, as illustrated in the following diagram:
Page 60
When the ICEfaces 2.0 Jar is added to a JSF application, the standard RenderKit is overridden with the ICEfaces RenderKit, and specifically, the ICEfaces RenderKit provides a DomResponseWriter instead of the standard JSF ResponseWriter. The DomResponseWriter diverts the output of any component renderer into a server-side DOM data structure.
DOM Differencing
A newly produced DOM from the D2D rendering process represents the page that will be replicated in the client browser DOM. The cached previous DOM is a replica of the DOM currently in the client browser, so the difference between the two DOMs defines the page updates that need to occur at the client browser. The differencing mechanism performs the basic task of calculating the set of updates to transform one DOM into the next, but the implementation in ICEfaces 2.0 has been highly optimized.
Page Updating
Given the set of page updates from the differencing algorithm, the standard JSF Ajax mechanism is used to deliver and insert those updates into the client DOM, thus completing the JSF lifecyle with D2D rendering. The whole process is illustrated below:
Page 61
1. 2. 3. 4.
User interacts with some browser control in the page. Ajax Event generated for singleSubmit. Ajax Request sent to the application. The JSF lifecycle executes on a single component in the component tree, updating the model appropriately. 5. Render phase traverses entire component tree, and D2D calculates necessary page updates. 6. Page updates are returned in the Ajax Response. 7. Standard JSF mechanism updates the client-side DOM with page updates.
Page 62
Single Submit
This page last changed on Jan 18, 2012 by ted.goddard.
Definition
Single Submit provides the ability to submit one component to execute in the JSF lifecycle, and is integral to the Automatic Ajax mechanism in ICEfaces 2. This means that only the specified component will decode, validate, update its bean model state, and trigger events, but a full render phase will occur. Direct-to-DOM Rendering is then used to determine the set of incremental page updates that must occur in the client browser DOM.
singleSubmit Attribute
On each of the ICEfaces Advanced Components, the feature is controlled via a singleSubmit attribute. In general, components can be classified by three categories: input, command, and container. Complex components may have aspects of functionality from more than one category. For the singleSubmit attribute, it has two distinct meanings, one if the component is primarily an input component, and one if it is primarily a command component. What is similar between the two, is that when singleSubmit="true", the component deviates from its default behavior such that only that component will submit and execute. The default value is false. Input components usually have javax.faces.component.UIInput as a superclass. Examples of input components are: h:inputText, h:selectOneMenu and ice:checkboxButton. With an input component, when singleSubmit="true", changing the value of this component will submit and execute this component only. This is equivalent to having <f:ajax execute="@this" render="@all"> set inside the standard h: components. When singleSubmit="false", no submit occurs. Command components usually have javax.faces.component.UICommand as a superclass. Examples of input components are: h:commandButon, h:commandLink and ice:pushButton. With a command component, when singleSubmit="true", triggering an action on this component will submit and execute this component only. This is equivalent to having <f:ajax execute="@this" render="@all"> set inside the standard h: components. When singleSubmit="false", triggering an action on this component will submit and execute the full form that this component is contained within.
<icecore:singleSubmit/> Tag
The <icecore:singleSubmit/> tag is a convenient and easy way to Single Submit enable standard h: components without having to litter the page with <f:ajax> tags. It allows an entire page region to be enabled at once. The behavior can be configured via the attribute submitOnBlur="true", such as <icecore:singleSubmit submitOnBlur="true" /> to cause form submission to occur on "blur" events as well as "change" events. (For example, this is necessary if "required" validation is expected to run each time a user visits a field.)
Page 63
FacesMessage Caching
When JSF completes a lifecycle, it discards all of the FacesMessage objects that have been added to the FacesContext. This means that next lifecycle, any pertinent FacesMessage objects have to be recreated and re-added to the FacesContext, for h:message components to be able to display them. When doing full form submits, where every component in the form is executed, this is not a problem, as every component will get its chance to add whatever FacesMessage objects are appropriate. When doing partial executes, either because of Single Submit, or because of <f:ajax> tags, then certain portions of the view will not execute, and any FacesMessage objects they had previously added to the FacesContext will be lost. This might mislead the user to thinking that the fields they had previously interacted with, and misentered data in, are now valid. ICEfaces 2 carries forward these FacesMessages, until either a full form submit and execute occurs, or until those specific components are executed again.
Page 64
Definition
Ajax Push allows the application to incrementally update any part of the page at any time, for any group of clients. This is a small change in terms of the technical capabilities of Ajax applications, but it is a revolutionary change in terms of what applications can actually provide to users. Ajax Push is the key to building collaborative multi-user applications for the web.
1. 2. 3. 4.
Some state change in the application triggers an Ajax Push event. ICEpush notification is delivered to the browser client over a dedicated ICEpush connection. Notification at client browser causes a JSF Ajax request with an empty execute phase. Render phase captures new state of client, and Direct to DOM Rendering delivers incremental page updates to client.
The diagram shows a single client recipient of a push, but the mechanism supports named groups of clients that all receive notifications. ICEpush handles all aspects of the asynchronous blocking connections involved, including connection management/sharing, heartbeating, and ARP integration.
Programming Model
Ajax Push can be added to an application with just two lines of code. The org.icefaces.application.PushRenderer pushes page updates to groups of pages. To cause all pages in "someGroup" to be updated with the current server state, call
Page 65
PushRenderer.render("someGroup");
The easiest way to assemble push groups is to push updates to all pages in a user's session using
PushRenderer.addCurrentSession("someGroup");
PushRenderer.addCurrentView("someGroup");
It really is as simple as that to add real-time collaboration to your JSF application. Checkout the full API for more details.
Deployment
Because of the underlying asynchronous blocking connections used by the ICEpush notifications, there are a couple of deployment considerations for Ajax Push-enabled applications.
ARP
ICEpush relies on Servlet 3.0 standard ARP APIs. If they are not present in the deployment environment, normal thread blocking connections are used.
Page 66
Core Framework
This page last changed on Dec 09, 2010 by steve.maryka.
Page 67
Overview
Ajax Push enables real-time collaborative applications, based on a mechanism call ICEpush. Check out the Ajax Push overview before delving into the API.
API
PushRenderer
ICEfaces 2 provides a new API for using Ajax Push from within your application. The main class of relevance is org.icefaces.application.PushRenderer, which contains the methods to support Ajax Push in your application. The PushRenderer API is similar to the SessionRenderer API from ICEfaces 1.8.x, and revolves around establishing named groups of pages, and asking them to update themselves in response to an Ajax Push trigger.
Group Management
Group naming is performed in some application-specific manner using the following APIs: Add a session and all associated pages (views) to a group using,
PushRenderer.addCurrentSession(String groupName);
PushRenderer.addCurrentView(String groupName);
The PushRenderer automatically manages the removal of unused group members, so programmatic removal is not strictly necessary.
Push Rendering
When something of note changes in the application, you can push to a group using,
Page 68
PushRenderer.render(groupName);
PortableRenderer PushRenderer.getPortableRenderer();
PortableRenderer.render(String groupName);
Porting
API changes
In ICEfaces 1.8.x, there were two distinct APIs available for using Ajax Push.
SessionRenderer
There is a compatible version of the com.icesoft.faces.async.render.SessionRenderer based on the org.icefaces.application.PushRenderer. The SessionRenderer exposes an API that is compatible with ICEfaces 1.8.x, so applications that used the SessionRenderer API in ICEfaces 1.8.x should be transparently mapped to use the new PushRenderer.
Page 69
ICEpush Configuration
The ICEpush library supports specific configuration parameters that can be used to optimize performance and reliability as required. Details on ICEpush configuration can be found in the ICEpush Configuration Parameters topic in the ICEpush product Wiki.
Page 70
Core Tags
This page last changed on Dec 04, 2011 by mark.collette.
Core Tags
To use any of the core tags, first declare the core namespace:
The ICEfaces 2 core framework supports the following tags in your Facelets markup:
<icecore:singleSubmit>
The <icecore:singleSubmit> tag is designed to allow submission from just the component generating the event and then update the page with any changes from all components. It's used in the following way:
<icecore:config>
You can use the ICEfaces configuration tag to adjust behaviour on a per-page basis. These settings take precedence over corresponding application global settings specified via context-param entries in the web.xml. To do so, add the <ice:config/> tag to the page and then set one or more of the following attributes:
ariaEnabled
<icecore:config ariaEnabled="true"/>
Allows control of DOM rendering on a per-page basis. By default, when ICEfaces is available, ARIA support is enabled. By using this setting in in conjunction with the application-scoped org.icefaces.aria.enabled context parameter, you can control whether or not ARIA support is active on an individual page.
mandatoryResource
A space-delimited list of components that will have their requisite resources pre-loaded on this page. The pre-loading allows the components to function correctly even if they are later added to the page dynamically. The values "none" (which is the default) and "all" are also valid. The value of this attribute on a page takes precedence over the values specified by the context parameter org.icefaces.mandatoryResourceConfiguration. See Configuration#mandatoryResourceConfiguration for additional details.
Page 71
messagePersistence
<icecore:config messagePersistence="true"/>
Allows control of message persistence on a per-page basis. By default, when ICEfaces is available, FacesMessages are persisted across different partial submits from the same page. This setting can be used to disable this behavior on a per-page basis.
render
<icecore:config render="true"/>
Allows control of DOM rendering on a per-page basis. By default, when ICEfaces is available, DOM rendering and partial page updates are enabled for stock JSF components. By using this setting in in conjunction with the application-scoped org.icefaces.render.auto context parameter, you can control whether or not ICEfaces is active on an individual page. See Configuration for additional details.
<icecore:push>
[As of ICEfaces 3.0] You can use the ICEfaces push tag to configure push behavior on a per-view basis. To do so, add the <ice:push/> tag to the page and then set one or more attributes. A view can be added to one or more push groups by adding one or more occurrences of this tag.
group
<icecore:push group="groupName"/>
Allows control of the current view being added to a push group. This is a mandatory attribute specifying the group the view must be added to.
Page 72
Annotations
This page last changed on Mar 03, 2011 by deryk.sinotte.
Annotations
@org.icefaces.bean.ViewRetained
During postback navigation, where the result of a navigation event returns the same view id, the default behaviour for JavaServer Faces is to create a new view instance. This also means a new map of viewscoped beans where all the previous view-scoped beans are disposed and new instances created. By adding the @ViewRetained annotation to a bean in View scope, that bean instance is propagated across the navigation to the new view map. This only occurs during postback, where the id of the original view and the new view are the same. The benefit is that view-scoped beans can have consistent state during postback, and not appear to reset themselves. To use the annotation, simply import it and add it to the class of the view-scoped bean that you'd like to retain:
package org.icefaces.demo; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import java.io.Serializable; import org.icefaces.bean.ViewRetained; @ManagedBean(name = "myViewScopedBean") @ViewScoped @ViewRetained public class MyViewScopedBean implements Serializable { ...
@org.icefaces.bean.WindowDisposed
A view-scoped bean annotated with @WindowDisposed is removed from the View map when the browser window associated with that view is closed. With stock JavaServer Faces, view-scoped beans are disposed when the session expires. By using ICEfaces and the @WindowDisposed annotation, view-scoped beans can be disposed in a more timely fashion resulting in more efficient use of resources.
package org.icefaces.demo; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import java.io.Serializable; import org.icefaces.bean.WindowDisposed; @ManagedBean(name = "myViewScopedBean") @ViewScoped @WindowDisposed public class MyViewScopedBean implements Serializable { ...
Page 73
Namespace
The namespace used for the ICEfaces client API is 'ice'. It is defined in the bridge.js file, a link to which is automatically rendered out to each page that uses ICEfaces.
ice.submit(myEvent, theSubmittingElement);
Parameters: event The event captured by the event handler. element The element owning the event handler. ice.se(event, element) and ice.ser(event, element) These functions submit a single element rather than all the elements of the form. This kind of submission reduces the elements serialization overhead and also increases the communication efficiency with the server. Usage: ice.se sends javax.faces.partial.execute=@this and javax.faces.partial.render=@all along with the serialized element and event.
ice.se(myEvent, theSubmittingElement);
ice.ser sends javax.faces.partial.execute=@this and javax.faces.partial.render=@this along with the serialized element and event.
Page 74
ice.ser(myEvent, theSubmittingElement);
Parameters: event The event captured by the event handler. element The element owning the event handler.
Parameters: updates A set of <update> elements as defined in the JSF 2.0 JavaScript API documentation (see jsf.ajax.response in http://java.sun.com/javaee/javaserverfaces/2.0/docs/js-api/symbols/ jsf.ajax.html). ice.onBeforeUpdate(callback) Accepts a reference to a callback function. The callback function will be invoked before the updates are applied to the DOM. Usage:
Parameters:
Page 75
updates A set of <update> elements as defined in the JSF 2.0 JavaScript API documentation (see jsf.ajax.response in http://java.sun.com/javaee/javaserverfaces/2.0/docs/js-api/symbols/ jsf.ajax.html). ice.onServerError(callback) Accepts a reference to a callback function. The callback function will be invoked when a server error is received by the browser from a JSF form submit. Usage:
Parameters: statusCode The HTTP status code. responseText The body of the HTTP response in text format. responseDOM The parsed body of the HTTP response as XML. This parameter is present only when response is in XML/HTML format. ice.onSessionExpiry(callback) Accepts a reference to a callback function. The callback function will be invoked when the HTTP session has been invalidated or expired. Usage:
ice.onNetworkError(callback) Accepts a reference to a callback function. The callback function will be invoked when a network error is detected by the browser during a request-response. Usage:
Page 76
};
Parameters: statusCode The HTTP status code. errorDescription The description of the network error. ice.onBeforeSubmit(callback) Accepts a reference to a callback function. The callback function will be invoked just before the form submit request is issued. Usage:
Parameters: source The element that triggered the form submission. ice.onElementRemove(elementID, callback) Accepts the ID of the element to be monitored for removal and a reference to a callback function. The callback function will be invoked when the element with the specified ID is removed from the document. Usage:
Parameters: elementID The ID of the element to be monitored for removal. callback The callback function invoked when the identified element is removed. ice.onLoad(callback) Accepts a reference to a callback function. The callback function will be invoked when the DOM document finished loading. This registration function allows the registration of multiple callbacks without the danger of callback overwriting (unlike the native windown.onload property).
Page 77
ICEfaces inserts the JS resource defining the ice.onLoad function right before the 'head' ending tag to make sure the scripts are loaded in a deterministic order. Any inline or referenced Javascript code that uses this function needs to be loaded later, preferably right after the 'body' starting tag. Usage:
Parameters: callback The callback function invoked when the document has been loaded. ice.onUnload(callback) Accepts a reference to a callback function. The callback function will be invoked when the DOM document is unloaded. This registration function allows the registration of multiple callbacks without the danger of callback overwriting (unlike the native windown.onunload property). ICEfaces inserts the JS resource defining the ice.onUnload function right before the 'head' ending tag to make sure the scripts are loaded in a deterministic order. Any inline or referenced Javascript code that uses this function needs to be loaded later, preferably right after the 'body' starting tag. Usage:
Parameters: callback The callback function invoked when the document has been unloaded.
Page 78
ice.setFocus(id);
Parameters: id The ID of the element. ice.applyFocus(id) or ice.af(id) Accepts an element ID. By calling this function the client will move the focus on the specified element and also call ice.setFocus so that the server will be informed about the focus change. Usage:
ice.applyFocus(id);
Parameters: none ice.onBlockingConnectionLost(callback) Accepts a reference to a callback function. The callback function will be invoked when the blocking connection to the server has been lost and is considered unrecoverable. Usage:
ice.onBlockingConnectionLost(connectionLostHandler); ...
Page 79
Parameters: reconnectionAttempts The number of reconnect attempts made by the bridge to re-establish the connection before considering the connection unrecoverable. ice.onBlockingConnectionServerError(callback) Accepts a reference to a callback function. The callback function will be invoked when a server error is received by the browser on the blocking connection. Usage:
Parameters: statusCode The HTTP status code. responseText The body of the HTTP response in text format. responseDOM The parsed body of the HTTP response as XML. This parameter is present only when response is in XML/HTML format.
Configuration API
The following parameters are used to configure certain functional parts of the client. ice.disableDefaultErrorPopups This parameter can be used to disable the popups rendered by default when a network error, session expiry or server error occurs. The parameter is usually set when an application or component developer wants to have rendered only the defined custom indicators. Usage:
ice.disableDefaultErrorPopups = true;
Page 80
Logging API
ice.log.debug(logger, message, exception) Logs a DEBUG level message to the console or log window. ice.log.info(logger, message, exception) Logs a INFO level message to the console or log window. ice.log.warn(logger, message, exception) Logs a WARN level message to the console or log window. ice.log.error(logger, message, exception) Logs a ERROR level message to the console or log window. Usage:
ice.log.debug(ice.log, 'Debug message'); ice.log.info(ice.log, 'Info message'); ice.log.warn(ice.log, 'Warning message'); try { ... } catch (e) { ice.log.error(ice.log, 'Error occurred', e); }
Parameters: logger The logger. message The message to be logged. responseDOM The captured exception. This is an optional parameter. ice.log.childLogger(parentLogger, categoryName) Creates an new child logger that logs its messages into the defined category. Usage:
var a = ice.log.childLogger(ice.log, 'A'); ice.log.debug(a, 'message in category A'); //outputs -- [window.A] debug: message in category A var aa = ice.log.childLogger(a, 'AA'); ice.log.warn(aa, 'message in category AA');
Page 81
Parameters: logger The parent logger. categoryName The name of the category.
Page 82
Handling Exceptions
This page last changed on Mar 04, 2011 by ken.fyten.
Handling Exceptions
The standard Servlet mechanism for handling exceptions that occur on the server is to specify an error-page entry in the deployment descriptor (web.xml file) and allow the container to redirect to the configured resource. For example:
This mechanism works fine as long as the exception makes it up to the servlet container. If the exception is handled in some other way and doesn't bubble up to the container, it renders the error-page strategy ineffective. With JSF 2 and ICEfaces 2, you can decide how you want to handle exceptions both on the server and the client. Server-side - ExceptionHandlers With JSF 2, there is now a facility for hooking into the lifecycle and customizing how exceptions are handled. This is done using an ExceptionHandlerFactory and one or more custom ExceptionHandlers. By default, Mojarra provides implementations of both a standard ExceptionHandler for normal requests as well as an Ajax implementation for Ajax requests Exceptions for non-Ajax requests can be handled using the error-page facility. If no error page is specified then a default page is created JSF and sent back to the client. Exceptions for Ajax requests are contained within Ajax responses and do not trickle up to the container so the error-page strategy is not used. If you'd like to change this behavior in some way, you can write your own ExceptionHandler and deal with the exceptions on the server as you see fit. It's relatively simple to do. ICEfaces currently uses the technique described here to emit SessionExpired exceptions instead of ViewExpiredExceptions when appropriate. Ed Burns has a blog about this specifically.
1) Create one or more implementations of ExceptionHandlers
ExceptionHandlers are request-scoped resources - that is, there is a new one for each request. Exceptions that occur during a JSF lifecycle are generally queued to be handled by one or more of the ExceptionHandlers. Normally, you'd create an ExceptionHandler that extends ExceptionHandlerWrapper. The interesting work of finding the exceptions you're interested in and then processing those might look like this:
public class MyExceptionHandler extends ExceptionHandlerWrapper { private ExceptionHandler wrapped; public MyExceptionHandler(ExceptionHandler wrapped) { this.wrapped = wrapped; } public javax.faces.context.ExceptionHandler getWrapped() { return wrapped;
Page 83
} public void handle() throws FacesException { Iterator events = getUnhandledExceptionQueuedEvents().iterator(); //Iterate through the queued exceptions while (events.hasNext()) { ExceptionQueuedEvent event = (ExceptionQueuedEvent) events.next(); ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); Throwable t = context.getException(); //See if it's an exception I'm interested in if (t instanceof MyCustomException) { try { //do something exciting with the exception } finally { //remove it if you processed it events.remove(); } } //Let the next ExceptionHandler(s) deal with the others getWrapped().handle(); } } }
ExceptionHandlers are created by ExceptionHandlerFactories. The basic mechanism is to create an ExceptionHandlerFactory that links into the chain of existing ExceptionHandlerFactories. Your factory is used to create the appropriate ExceptionHandler for the request. Because it's a wrapper, we can chain them together by passing in the delegate when we create the instance. For example:
public class MyExceptionHandlerFactory extends ExceptionHandlerFactory { ExceptionHandlerFactory delegateFactory; public MyExceptionHandlerFactory(ExceptionHandlerFactory delegateFactory) { this.delegateFactory = delegateFactory; } public ExceptionHandler getExceptionHandler() { return new MyExceptionHandler(delegateFactory.getExceptionHandler()); } }
3) Then you need to register your factory with JSF. You can add an entry into the faces-config.xml of the .war that includes your custom ExceptionHandler(s):
Page 84
FacesContext fc = FacesContext.getCurrentInstance(); ExceptionQueuedEventContext ctxt = new ExceptionQueuedEventContext(fc, new MyCustomException("my bad") ); Application app = fc.getApplication(); app.publishEvent(fc, ExceptionQueuedEvent.class, ctxt);
Client-side - JavaScript Callbacks When an exception does occur during an Ajax request, JSF will process those exceptions and send them back as Ajax responses. With stock JSF, you can register a callback and handle these errors as you see fit. This is done using the JavaScript API provided by JSF:
//Assign your error handling function to a variable var jsfErrorCallback = function handleError(error) { //Handle all errors by simply redirecting to an error page window.location.href = "./generalError.xhtml"; } //Register your error handler as a callback jsf.ajax.addOnError(jsfErrorCallback);
ICEfaces uses this same technique. By default, when ICEfaces is active on the page and an error comes back as an Ajax response, a small popop is displayed with a short description of the error. For example, if a session times out and you attempt to interact with the page it will cause a ViewExpiredException when JSF attempts to restore the view:
If you would like to do something else with these errors, you can use much the same technique as described above:
//Assign your error handling function to a variable var iceErrorCallback = function iceHandleError(statusCode, responseTxt, responseDOM) {
Page 85
//Handle all errors by simply redirecting to an error page window.location.href = "./generalError.xhtml"; } //Safely check if ICEfaces is available if (ice) { //Turn off the popups as we plan to handle this ourselves ice.configuration.disableDefaultIndicators = true; //Register your error handler as a callback ice.onServerError(iceErrorCallback); }
Page 86
Configuration
This page last changed on Dec 04, 2011 by mark.collette.
Configuration
ICEfaces 2 provides a number of configuration parameters that need not be adjusted for typical applications, but may be useful for diagnostic purposes or in special cases. Context Parameters The following parameters are set as context parameters in the web.xml file of your application. Several of them may be overridden on a page by page basis via the icecore:config tag.
aria.enabled
default is true Setting aria.enabled to true indicates that all views in the the application are ARIA (Accessible Rich Internet Applications) enabled. This context parameter is application-wide and works together with the ariaEnabled attribute of the ICEfaces <icecore:config> tag so that ARIA support can be turned on and off selectively on a per page basis.
autoid
default is true Setting autoid to true causes the majority of standard JSF components to write their IDs to the page. This allows ICEfaces to apply page updates at a fine granularity. With this parameter set to false, page updates can only be applied for components that have manually specified IDs. This parameter is provided for fallback to completely standard behavior; it is not generally intended to be set to false for application use.
compressDOM
default is false Setting compressDOM to true indicates to the ICEfaces core framework that the server-side DOM representation of the current view should be serialized and compressed between requests. The default value of false leaves the DOM representation intact between requests.
Page 87
compressResources
default is true By default, ICEfaces will gzip compress most static resource responses. Setting compressedResources to false instructs ICEfaces not to compress any resource responses.
deltaSubmit
default is false Setting deltaSubmit to true tells ICEfaces that form submission should be handled in a special way to minimize what is sent across the wire. The parameters of a form post are compared to the previous submission and only those that have changed are sent to the server. The rest of the form parameters are reconstructed on the server from the cached DOM and then processed normally.
Known Issue The Delta-submit function does not support cases where an Ajax DOM update in the browser dynamically introduces new form elements into the DOM that were not part of the form when the page was originally loaded. In order to use Delta-Submit successfully all form elements / components must be present on the page at the time the page is loaded.
lazyPush
default is true By default, when using Ajax Push, the feature is activated in a lazy fashion. This means that the blocking connection used for doing Ajax Push is not activated until the first push is requested. Setting lazyPush to false tells ICEfaces to automatically activate ICEpush for each session and each page. This context parameter is application-wide and works together with the lazyPush attribute of the ICEfaces configuration tag <ice:config> so that ICEpush can be set to activate lazily on a per-page basis.
To apply lazy push activation to select pages only, set this parameter to false and add:
<ice:config lazyPush="true">
Page 88
lazyWindowScope
default is true By default, when using the window scoped beans, the window management is activated in a lazy fashion. This means that if the window scope map doesn't contain any window scoped beans no dispose-window request is sent upon window closure. Setting lazyWindowScope to false tells ICEfaces to always send a dispose-window request upon window closure regardless of the window scope map being empty or not. This context parameter is application-wide. Please note that if the view scope map contains any view scoped beans, lazyWindowScope is not enabled by default.
mandatoryResourceConfiguration
default is 'all' in ICEfaces 2.0, and 'none' in ICEfaces 3.0+ The mandatoryResouceConfiguration may be set to one of three values: none, all, or a space delimited list of components. When none is specified, then only when a component is actually on the page will its Javascript and CSS resources be rendered into the head of the page. This can cause problems when a component is initially not in the page, but then on a postback it is dynamically added to the page. In that case, it's necessary to have pre-loaded the resources into the head, for the eventuality of the component being later dynamically added to the view. A simple yet blunt method of accomplishing this is to set it to all, so that every componnt which participates in the MandatoryResourceComponent mechanism may have their resources pre-loaded into the head. There is a performance cost to pre-loading every component's resources, especially when this might apply to components that your application may not even use at all. For this reason, applications may specifically list the components by name, space delimited, that they wish to pre-load. [ICEfaces 2.0] The component's full class name must be specified. For example, to specify sliderEntry, org.icefaces.component.sliderentry.SliderEntry would be given. [ICEfaces 3.0+] The component's tag name may be specified, or for backwards compatibility, the component class name may still be specified. For example, to specify sliderEntry, either of sliderEntry or the longer org.icefaces.component.sliderentry.SliderEntry may be given. For instance, to pre-load resources for sliderEntry and dateTimeEntry:
render.auto
default is true
Page 89
Setting render.auto to true causes ICEfaces to automatically apply DOM rendering to each page. If this is set to false, then DOM rendering and updating is turned off for the entire application.
This context parameter is application-wide and works together with the render attribute of the ICEfaces <icecore:config> tag so that ICEfaces rendering can be turned on and off selectively on a per page basis. To apply ICEfaces DOM rendering to select pages only, set this parameter to false and add:
<icecore:config render="true">
default is false By default, ICEfaces does optimized serialization and submission of form elements based on the element that triggered the submission. Setting standardFormSerialization to true indicates that ICEfaces should do a normal, standard, full form submission.
strictSessionTimeout
default is false The default value of false for strictSessionTimeout indicates that ICEfaces should not interfere with container-managed control of session timeout. In this case, each user request and each Ajax Push request will extend the session. Setting strictSessionTimeout to true indicates that ICEfaces should attempt to enforce the configured session timeout by ignoring any Ajax Push activity so that only usertriggered requests will extend the session.
subtreeDiff
[As of ICEfaces 3.0] default is true By default, when using ICEfaces, Ajax-specified subtree diffing is always done. Setting subtreeDiff to false indicates that ICEfaces will not perform a DOM diff on the rendered subtrees. Instead the rendered output of subtrees is sent directly to the browser, thus not updating the server-side DOM.
Page 90
uniqueResourceURLs
default is true The default value of "true" will cause ICEfaces to append random numbers to certain resource URLs, thereby preventing caching. This is useful for development, but can interfere with Portlet URL generation.
windowScopeExpiration
default is 1000 A value, in milliseconds, indicating how long window-scoped values should remain valid in the session after a reload or redirect occurs. This allows for postbacks that might occur quickly after a reload or redirect to successfully retrieve the relevant window-scoped values.
disableDefaultErrorPopups default is false This parameter can be used to disable the popups rendered by default when a network error, session expiry or server error occurs. The parameter is usually set when an application or component developer wants to have rendered only the defined custom indicators. Usage:
Page 91
This parameter can be used to replay the navigation rules when the page is reloaded. The parameter is usually set in applications where it is desirable to avoid the content being reset to the first page (before non-redirect navigation was triggered) when reloading. Usage:
Compatible Context Parameters The following parameters are set as context parameters in the web.xml file of your application, but only apply if you are using the compatibility component suite:
blockUIOnSubmit
default is false Setting blockUIOnSubmit to true tells ICEfaces that the user interface (UI) should block any subsequent requests until the current request has been processed. This is provided to help prevent double-submits in applications that require this feature.
connectionLostRedirectURI
default is "null" Setting connectionLostRedirectURI to a valid URI tells ICEfaces that when the Ajax Push connection is lost, that the client is to be redirected to the specified page.
sessionExpiredRedirectURI
default is "null" Setting sessionExpiredRedirectURI to a valid URI tells ICEfaces that when the user session expires, that the client is to be redirected to the specified page.
Page 92
ICEpush Configuration
This page last changed on Nov 25, 2011 by ken.fyten.
ICEpush Configuration
The ICEpush library supports specific configuration parameters that can be used to optimize performance and reliability as required. Details on ICEpush configuration can be found in the ICEpush Configuration Parameters topic in the ICEpush product Wiki.
Page 93
JSF Configuration
This page last changed on Jun 07, 2011 by mark.collette.
JSF Configuration
JSF has it's own configuration context parameters, which may optionally be specified, to further tune or configure applications. These context parameters are set in the web.xml file of your application. Various JSF implementations, such as Mojarra, also have their own configuration context parameters. Caching Context Parameters These context parameters affect how resources will be cached. JSF pages use components which themselves register resources either programmatically or statically via @ResourceDependency annotations. These resources typically consist of Javascript and CSS files, but can be any other files that the page contains.
javax.faces.PROJECT_STAGE
Default is Production When the PROJECT_STAGE is set to Production, and a resource is within its cached duration, then the web browser can avoid going to the server at all for the resource. If it's beyond the duration, or the user has pressed the Refresh button, then the browser may request if the resource has been updated, which can either return an HTTP 304 code saying that the resource is still valid in the browser's cache, or it will return an HTTP 200 code and serve out the resource, if it has been updated. When the PROJECT_STAGE is set to Development, the cache duration is ignored, so the browser will always request if the resource has been updated, and use the HTTP 304 and 200 accordingly. So, caching is not completely disabled, as it can still avoid downloading the resource, but it will still communicate with the server.
com.sun.faces.defaultResourceMaxAge
Default is 604800 This parameter is specific to Mojarra's JSF implementation. The default is about 10 minutes, which is not really that long. It's recommended that production applications specify a longer caching duration, for example 2 weeks. Again, this only applies when the PRJECT_STAGE has been set to Production, and allows the browser to avoid any communication with the server, in regards to cached resources. There is no means for setting different cache durations for different resources, this globally applies to all resources.
Page 94
Components
This page last changed on Nov 04, 2010 by ken.fyten.
ICEfaces Components ICEfaces 2.0 Advanced Components Animation 2.0 CheckboxButton 2.0 DateTimeEntry 2.0 FileEntry 2.0 LinkButton 2.0 PushButton 2.0 SliderEntry 2.0 TabSet 2.0 ICEfaces Advanced Components Accordion AccordionPane Ajax Animation CellEditor CheckboxButton ConfirmationDialog ContextMenu Column ColumnGroup DataTable - Data Model Lifecycle DataExporter DateTimeEntry Dialog Draggable Droppable ExcludeFromExport FileEntry LinkButton MaskedEntry Menu and Menubar MenuButton MenuItem NotificationPanel Panel Printer ProgressBar PushButton Row RowEditor RowExpander RowPanelExpander SliderEntry Submenu TabSet Tooltip ICEfaces Advanced Components Environment ACE ThemeRoller support ACE Source Artefacts and Generated Outputs ACE Meta Class ACE Component and Renderer Classes ACE Adding Resources to Meta Class ACE Skinning - ACE Sprite Image Generation - ACE CSS URL Mapping ACE Disabled Styling Standard
Page 95
ICEfaces Components
This page last changed on Oct 20, 2011 by robert.lepack.
Configurations Details
Required web.xml entries
<?xml version='1.0' encoding='UTF-8'?> <!-- Have the proper schema version --> <web-app version="2.5" 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_2_5.xsd"> <!-- More efficient, in an AJAX environment, to have server side state saving --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <!-- HTML comments become components unless they're stripped --> <context-param> <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name> <param-value>true</param-value> </context-param> <!-- If you're using ice:gmap component, you'll need your own key here --> <context-param> <param-name>com.icesoft.faces.gmapKey</param-name> <paramvalue>ABQIAAAADlu0ZiSTam64EKaCQr9eTRTOTuQNzJNXRlYRLknj4cQ89tFfpxTEqxQnVWL4k55OPICgF5_SOZE06A </param-value> </context-param> <!-- The JSF servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <!-- Many of the ICEfaces Components make use of the Resource Servlet --> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
Page 96
<!-- The standard mapping. Can use other extensions, or path mappings --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <!-- These specific mappings are necessary for the Resource Servlet to function properly --> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping> </web-app>
[icefaces2.dir]/icefaces/lib/icefaces-compat.jar
3rd Party Dependencies If you are using the ICEfaces Components you will also require additional 3rd party libraries. Libraries servlet-profile : Tomcat web-profile : JBoss 6, Glassfish 3 Y Y
Y Y Y Y Y Y
Y Y
Component List
checkbox
checkbox for a selectManyCheckbox component when its layout is "spread" single column of data within a parent UIData component used to create multiple dataTable headers or footers with allowable colspan and rowspan used to render multiple table columns
column
columnGroup
columns
Page 97
commandButton commandLink
submit or reset button HTML "a" anchor element that acts like a form submit button when clicked clickable column header allowing user to toggle the sort order of data in table export the data contents of an table component into a variety of formats used to render a set of page navigation controls for a table HTML table tied to underlying data model add effects to parent component HTML form width added features Google map adds control to the gMap direction from point A to point B supports the KML and GeoRSS data formats for displaying geographic information wrapper for google map's GLatLng API list of gMapLatLng components uses google map's GMarker API to display points on the map HTML "img" element header row for a table HTML "input" element of "type" "hidden" JSF based rich text component HTML "input" element of "type" "password" HTML "input" element of "type" "text" HTML "textarea" element used to capture javascript events and optionally send a notification to server and fire an action event similar to f:loadBundle but allows change to messages dynamically provides a robust menu system menu items contained by a menuBar dynamic heirarchy of menu items
commandSortHeader
dataExporter
dataPaginator
loadBundle
Page 98
menuItemSeparator menuPopup
separates groups of menu items context sensitive popup menu providing popup nested child menus single message for a specific component all the messages for a specific component charts of various types displays information about the status of the network connection renders parameterized text HTML "label" element HTML "a" anchor element plays a media object report progress to users in cases where a long running server-side task is necessary expose resources for opening or downloading link desired ICEfaces theme CSS stylesheets span element for displaying text. container component with five regions: north, south, east, west, and center clickable header to hide or show contents popup confirmation dialog splitable panel HTML "table" element container for a group of child components placement of components in absolute or relative position modal or non-modal popups series of repeating child-components which can be dragged and repositioned dynamically generates a series of repeating childcomponents within a panel multiple panel groups with one group visible at a time a tab within a tab set a set of tabs with one table active at a time tooltip popup
panelPopup panelPositioned
panelSeries
panelStack
Page 99
portlet radio
container for a portlet in a portal radio button for a selectOneRadio component when its layout is "spread" mechanism for dynamically generating a series of repeating child-components enables single and multiple row selection for a data table HTML "input" element of type "checkbox" input field, inline calendar or popup calendar for entering date and time input text component enhanced with autocomplete functionality a list of checkboxes list box allowing multiple selections list box with only one item visible at a time allowing multiple selections list box with single selection list box with only one item visible at a time allowing single selection set of radio buttons specifies the phase that certain events will be broadcast in sets listener class for tab change in tabset displays hierarchical data as a tree of branches and leaf nodes a node in a tree
repeat
rowSelector
selectBooleanCheckbox selectInputDate
selectInputText
selectOneListbox selectOneMenu
selectOneRadio setEventPhase
tabChangeListener tree
treeNode
Examples
Compat Components Showcase The Compat Components Showcase example provides a high-level demonstration of the ICEfaces Compat Components and is located in:
[icefaces2.dir]/icefaces/samples/compat/component-showcase
From that directory, you can use ant to build the Component Showcase. The strategy is to build a .war file for the platform you are running on. All of the content-related files are located in:
Page 100
[icefaces2.dir]/icefaces/samples/compat/component-showcase/src
So to build a component-showcase.war file for Tomcat 6.0 or 7.0 (non-JEE6 container), you would run the following ant command from the component-showcase directory:
Alternatively, to build a component-showcase.war file for a JEE6 container, which includes the JSF libraries, you would run the following ant command from the component-showcase directory:
[icefaces2.dir]/icefaces/samples/dist/component-showcase.war
Compat Auction Monitor The Auction Monitor simulates the tracking of live auctions and illustrates the following dynamic web application features; ticking clocks, real-time bid updates, dynamically rendered buttons, the ability to hide and show table rows on demand, and an integrated chat section. It is located in:
[icefaces2.dir]/icefaces/samples/compat/auctionMonitor
From that directory, you can use ant to build the Auction Monitor. The strategy is to build a .war file for the platform you are running on. All of the content-related files are located in:
[icefaces2.dir]/icefaces/samples/compat/auctionMonitor/src
So to build an auctionMonitor.war file for Tomcat 6.0 or 7.0 (non-JEE6 container), you would run the following ant command from the auctionMonitor directory:
Alternatively, to build an auctionMonitor.war file for a JEE6 container, which includes the JSF libraries, you would run the following ant command from the auctionMonitor directory:
Page 101
[icefaces2.dir]/icefaces/samples/dist/auctionMonitor.war
Page 102
Components
The following Advanced Components are included in the ICEfaces 2 distribution: Animation 2.0 CheckboxButton 2.0 DateTimeEntry 2.0 FileEntry 2.0 LinkButton 2.0 PushButton 2.0 SliderEntry 2.0 TabSet 2.0
Examples
The following example is included in the ICEfaces 2 distribution:
Advanced Components Showcase (ace-showcase) The Advanced Components Showcase example provides a high-level demonstration of the ICEfaces Advanced Components and is located in:
[icefaces2.dir]/icefaces/samples/ace/showcase/
From that directory, you can use ant to build the Component Showcase. The strategy is to build a .war file for the platform you are running on. All of the content-related files are located in:
Page 103
[icefaces2.dir]/icefaces/samples/ace/showcase/src
So to build an ace-showcase.war file for Tomcat 6.0 or 7.0 (non-JEE6 container), you would run the following ant command from the showcase directory:
Alternatively, to build an ace-showcase.war file for a JEE6 container, which includes the JSF libraries, you would run the following ant command from the showcase directory:
[icefaces2.dir]/icefaces/samples/dist/ace-showcase.war
[icefaces2.dir]/icefaces/lib/icefaces-ace.jar
b. Select your desired theme, by adding the appropriate styleClass to the body, or wherever in the page within which you want the theme to apply to
c. Add the CSS file for that particular theme to the bottom of the page. This will allow the contents of the CSS file to take precedence over everything else. If you have application CSS
Page 104
files, where you override theme style classes, add them to the bottom of the .xhtml page as well, after the theme
</h:body> <h:outputStylesheet library="org.icefaces.component.skins" name="rime.css" /> <!-- or --> <h:outputStylesheet library="org.icefaces.component.skins" name="sam.css" /> </f:view> </html>
mandatoryResourceConfiguration When using the Advanced Components in your project, it may be necessary to pre-load certain component resources in order to ensure proper execution in cases where the component is not present on the initial page load, but added later dynamically (ex. such as rendered due to a tab being selected that wasn't rendered initially). To facilitate the resource pre-loading, ICEfaces uses a mandatoryResourceConfiguration scheme. By default, mandatoryResourceConfiguration will preload the resources for all ACE components in your project, which can result in unnecessary pre-processing and longer page load times. It is recommended that you tune the mandatoryResourceConfiguration to ensure optimum page load times. See the Configuration topic for details on mandatoryResourceConfiguration.
Page 105
Animation 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. ICEFaces provides animation system using ice:animation attachable behavior, that allows to attach animation(s) to the JSF standard and custom components which are type of ClientBehaviorHolder. - There are two different type of animations: Predefined Free form
* Predefined: - When using predefine animations, developers don't need to define any properties, defaults are provided in css classes. "fade" is an example of a predefined animation which has the following corresponding CSS classes defined in animation.css:
In order to use predefined animations a developer needs to define an animation "name" as well as a type of "event". For example:
The developer can override properties of animation by defining application or page level css. For example:
.fade_to{ opacity:0.2 }
Currently, supported predefined animations are fade (disappear from sight) highlight (visually emphasize), and appear (appear from nothing) * Free form: When using free form animation developers are allowed to define "to" and "from" properties on animation tag such as:
Page 106
</h:inputText>
or:
<h:inputTextarea> <ace:animation event="mouseover" from="{height:20, color:'#222'}" to="{height:100, color:'#CCC'}" /> <ace:animation event="mouseout" to="{height:20, color:'#222'}" from="{height:100, color:'#CCC'}" /> </h:inputTextarea>
When using free form animation the name of an animation is not required, but it can be defined as "anim". - With the current implementation "to" and "from" will only be applied when using "anim (free form)" type of animation, and if using predefine animation such as "fade" or "highlight" then "to" and "from" can be changed using the style classas shown above. * Chaining: Chaining can be achieved by registering animation on same event type (e.g.)
In above case chaining will be start on transition by running the last defined animation first, in that case highlight and rest of animation after that. * Synchronize execution of animations: The predefine animations are based on the style class, they only look for specific properties so synchronization is not posible with more then one animations. However Synchronize execution of an animation can be achieved using free form animation by defining more then one properties on it(e.g.)
The above snippet will give blind up/down effect in parallel to fade in/out * Default animation By default components don't have any animation. But by defining the following style classes into page or theme.css default animation can be set on theme level or by application level. The style classes need to follow the following pattern: .default_[facesDev:eventType]_[facesDev:animationName] (e.g.)
Page 107
Other Animation Attributes: In addition to that the following attributes can be used on both type of animations "predefined" and "free form". Some of these easing animations are more applicable to certain components than others.
easing Specifies an additional type of behaviour for the animation. The values exposed are supported by the underlying YUI components and are: - backIn:Backtracks slightly, then reverses direction and moves to end. - backOut: Overshoots and then reverses and comes back to end. - backBoth: Backtracks slightly then reverses direction, overshoots, and then reverses and comes back to end. - bounceIn: Bounces off start value. - bounceOut: Bounces off end value. - bounceBoth: Bounces off start and end values. - easeIn: Begins slowly and accelerates towards end. - easeInStrong: Begin slowly and accelerate quickly towards end. - easeNone: Equivalent to no easing argument. - easeBoth: Begin slowly, accelerate, then decelerate at end. - easeBothStrong: Begins slowly and decelerates towards end, with vigor. - easeOut: Begins quickly and decelerates towards end. - easeOutStrong: Begins quickly and decelerates towards end, with vigor. - elasticIn: Snap in elastic effect. - elasticOut:Snap out elastic effect. - elasticBoth:Snap both elastic effects.
Page 108
CheckboxButton 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The ace:checkboxButton component is a simple true/false selection used to toggle a value that is bound to the button. When singleSubmit="true" the value will be submitted to the server. When singleSubmit="false", the value is maintained by the client until some other component submits the form the checkboxButton occurs in. NOTE that rendering with class="ice-skin-sam" renders this component as a checkbutton (use label attr with labelPosition="on") with class="ice-skin-rime" it is rendered as a checked box (use labelPosition="left")
Usage
<html ... xmlns:ace="http://www.icefaces.org/icefaces/components"> <!-- can use either ice-skin-sam or ice-skin-rime --> <h:body class="ice-skin-rime"> <h:form> <ace:checkboxButton value="{button.checkedRime}" label="checkedRime" singleSubmit="true"/> </h:form> </h:body> </html>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.
value the value binding (bean) tied to the value of the checkboxButton-usually to a backing bean through el.
Page 109
label The label of the button-what the user sees that relates to that particular button. For example, "Remember Me"
singleSubmit When singleSubmit attribute is true, the checkbox only submits an event request to the server representing an ajax call with execute=@this and render=@all, if false then only the hidden field is updated on the client and some other component must submit the form for the server model side to be updated. Default is "true"
<icecore:config ariaEnabled="true"/>
To enable/disable ARIA at application level, the following param can be set in web.xml.
the space key will toggle the checkbox/checkbutton Aria role="button", aria-describedby and aria-disabled properties supported as well as aria-checked. The ARIA implementation is based on the specification at check box aria practices. Currently only the basic ARIA attributes and single-key keyboard shortcuts have been implemented. Storyboard
Action
focus
hover
checked
disabled
onkeypress
aria
Page 110
yui-class
yui-buttonfocus
yui-buttonhover
yui-buttonchecked
yui-buttondisabled
Submit
submit button &update component stay on client/ update hidden field description description
none
Single Submit
none
Screen Reader
Page 111
DateTimeEntry 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The dateTimeEntry component allows you to enter a date and optionally a time. You can enter the date/ time as text or pick the date/time from an inline or popup calendar. When entering as text, the format is as specified in the pattern attribute of the <f:convertDateTime> tag. The month, week and am/pm labels in the calendar are localized according to the locale of ViewRoot.
Usage
<html ... xmlns:ice="http://www.icefaces.org/icefaces/components"> ...... <ice:dateTimeEntry id="calendar3" value="#{calendarBean.selectedDate}" renderAsPopup="#{calendarBean.renderAsPopup}" renderInputField="#{calendarBean.renderInputField}" singleSubmit="#{calendarBean.singleSubmit}"> <f:convertDateTime pattern="MMM/dd/yyyy hh:mm a" timeZone="Canada/Mountain"/> </ice:dateTimeEntry>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.
value is value of the component as a java.util.Date object. Default is current date and time.
renderAsPopup and renderInputField determine how the calendar is displayed for input:
Page 112
singleSubmit triggers the submit of the date/time value (and the date/time value only) as soon as it is selected. In an inline calendar, any date/time select will trigger a submit. In a popup calendar, the submit is done when the OK button is clicked. When entering date/time as text, the input is submitted when focus leaves the input field and there is a change in the input value. Note that pressing Enter in the input field will always perform a full form submit. Default is "false".
The pattern attribute (in the nested <f:convertDateTime> tag) is used to specify the date/time format of the text input field. It also affects whether and how the time select fields appear in the calendar. The pattern characters are as detailed in the java.text.SimpleDateFormat javadoc. When an hour field is present in the pattern, the hour and minute select fields will appear. If the hour is in am/pm format, then the am/pm select field will also appear. Note that the hour itself can also be 0-based or 1-based, affecting the values of the hour dropdown list.
ARIA support
To enable/disable ARIA at page level, the <icecore:config> tag can used:
<icecore:config ariaEnabled="true"/>
To enable/disable ARIA at application level, the following param can be set in web.xml.
<context-param>
Page 113
The ARIA implementation is based on the specification at datepicker aria practices. Currently only the basic ARIA attributes and single-key keyboard shortcuts have been implemented.
Known Issues
The following issues are known to exist: No support for disabling selection of dates outside a valid range, or other date-selection prevention mechanism. No support for entering only a time, and not a date. No support for custom styling individual dates in the popup calendar via a component attribute.
Page 114
FileEntry 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The ace:fileEntry components allows end users to upload files to the server, for processing and storage by the application. It uses a special AJAX technique for allowing ICEfaces incremental page updates within HTML 4 compliant browsers. Files and other form elements are all uploaded and processed together in a single JSF lifecycle. Upload progress is shown by fileEntry itself, in the browser, with no need for application involvement or server coding. An indeterminate progress bar will be shown initially, and if ICEpush is enabled in the application, then an incrementing progress bar will be shown, when progress notifications are received. The fileEntry component requires that a non-AJAX full form submit occur to upload the file contents. This is an HTML 4 requirement. It then intercepts this submit and employs it's own AJAX techniques to allow for a partial page update, instead of the typical full page update. It does not use XmlHttpRequest at any point. Because of this, no component may upload the files by doing an AJAX submit, and so only h:commandButton, without any f:param(s), can currently be used to upload files. Other AJAX components may still do form submits, for their own processing, but the file contents will not be uploaded, as per the HTML 4 specification.
Usage
<html ... xmlns:ace="http://www.icefaces.org/icefaces/components"> ...... <ace:fileEntry id="fileEntryComp" label="File Entry" relativePath="uploaded" fileEntryListener="#{fileEntryController.listener}"/>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.
results contains the results of the most recent file upload operation. If the form was submitted, and no files were selected, than the previous results would remain. The results are an instance of FileEntryResults, which encapsulates a list of FileInfo objects, each corresponding to an individual file that was attempted to be uploaded in the one form submit.
fileEntryListener is the mechanism by which application are notified that a file upload attempt has been made. Files may have failed uploading, due to restrictions set on uploads, or they may have succeeded. For both cases, the attempt triggers this listener. This is an example of a prototypical fileEntryListener:
Page 115
import org.icefaces.component.fileentry.*; public void listener(FileEntryEvent event) { FileEntry fileEntry = (FileEntry) event.getSource(); FileEntryResults results = fileEntry.getResults(); for (FileEntryResults.FileInfo fileInfo : results.getFiles()) { if (fileInfo.isSaved()) { // Process the file. Only save cloned copies of results or fileInfo } } }
immediate controls when in the JSF lifecycle the fileEntryListener will get invoked: true: fileEntryListener invoked at end of ApplyRequestValues phase If the upload attempt failed, or a file succeeded uploading, but processing of it deemed the file invalid, then the form submission can be made invalid, and UpdateModel phase skipped, by calling FacesContext.validationFailed() in the fileEntryListener method. If other input components need to be validated using the details or contents of the uploaded files, having immediate="true" would make the fileEntryListener be invoked earlier than the ProcessValidations phase for the input components. If the form submit button's action or actionListener method needs make use of the details of contents of the uploaded files, having immediate="true" would make the fileEntryListener be invoked earlier than the InvokeApplication phase for the command component. false: fileEntryListener invoked before RenderResponse phase If the fileEntryListener depends on the validation of input components, or the action or actionListener methods of command components, having immediate="false" would make the fileEntryListener be invoked later than everything else. But, unlike action and actionListener methods, which are invoked during InvokeApplication, and so will not execute if the form submission is invalid, fileEntryListener will always be invoked, as it is invoked in the before part of RenderResponse phase. Default is "false".
absolutePath, relativePath, useSessionSubdir and useOriginalFilename together determine where the uploaded files will be stored on the server's file-system. absolutePath, or alternatively relativePath, determine the root directory into which files will be stored. If absolutePath is specified, then it is interpreted as an absolute path into the file-system. As well, it takes precedence if relativePath is also specified, erroneously. If relativePath is specified, it is interpreted as a path within the application deployment directory. The default is for, the root in which files are saved, to be the application deployment directory.
useSessionSubdir and useOriginalFilename are used to keep different files, from different users, from colliding with each other, in the save root. When useSessionSubdir="false", files uploaded from different sessions will all be jumbled together. The default, of useSessionSubdir="true", separated files of different sessions, each user's file remain separate, and each time a given user logs back in, their files are kept separate from their previous logins' files. This simplified application processing and cleanup of each session's files. When useOriginalFilename="true", files are saved on the server's file-system using their file name from the user's file-system. This might simplify processing, but could also be a security risk. As well, collisions may occur, where if different versions of the same file are uploaded over time, or different files from
Page 116
different directories, but which share the same file name, are uploaded, then the last one uploaded will overwrite earlier uploaded ones. The default, of useOriginalFilename="false", saves the uploaded files onto the server's file-system using uniquely generated file names.
maxTotalSize, maxFileSize and maxFileCount allow for setting quota constraints on upload operations. They are evaluated and enforced for each individual form submit and upload. Subsequent form submit and uploads do not take into account previous ones.There are no default values, as there are no default constraints. If any of these constraints are not met, then the form will be marked invalid, UpdateModel and InvokeApplication phases will not run, and none of the form fields will be set into the application's beans. When a fileEntry component is configured to allow uploading of multiple files in a single form submit, maxTotalSize and maxFileCount become more relevant. Individual files may have their sizes constrained by maxFileSize. If a file's size is greater than maxFilesSize, then it will fail uploading. If an application is concerned with the total size of all uploaded files in the aggregate, then maxTotalSize may be used to constrain the total size of all the files together. As each file is processed in sequence, when the maxTotalSize has been exceeded, the current file, and all subsequent files, will fail uploading. The previously processed files, which met the constraint, will have succeeded uploading. The maxFileCount constrains the number of files which may be uploaded in a single form submit by the one fileEntry component. As each file is processed in sequence, when the maxFileCount has been exceeded, the current file, and all subsequent files, will fail uploading. The previously processed files, which met the constraint, will have succeeded uploading.
required is used to specify that at least one file must be uploaded as part of the current form submit, for the form to be valid. If no file was uploaded, then the form will be marked invalid, UpdateModel and InvokeApplication phases will not run, and none of the form fields will be set into the application's beans. The required property does not look into whether the uploaded files succeeded or not, just that any files were attempted to be uploaded. The other constraints, which can fail uploads, will themselves invalidate the form. The criteria for required to invalidate the form is: A full form submit, not using AJAX, occured No files were uploaded by this fileEntry component The required property is true, for this fileEntry component This fileEntry component is executing in the lifecycle. For example: The submitting component did not do a single submit The submitting component did not have an f:ajax tag, which excluded the fileEntry component from executing The submitting component did not do a partial submit. That disables required processing
ARIA support
Not applicable. The ARIA specification does not cover file upload components.
Known Issues
The following known issues exist, and are coming soon: Only h:commandButton may be used to upload files. A greater range of options is being worked on. The user interface for selecting multiple files to all upload at once is not complete, so only single file uploading per fileEntry component is enabled for now. To upload multiple files in a single upload operation, simply use multiple fileEntry components in the same form.
Page 117
LinkButton 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The ace:linkButton component acts as an Html anchor, a source for Ajax ActionEvents, or a hybrid of both. Occasionally, it's convenient to have an anchor tag that POSTs an event to the server, but which you can also right click and open in a new tab. This functionality is not present in the JSF form of the commandLink.
Usage
<html ... xmlns:ace="http://www.icefaces.org/icefaces/components"> 1) Standard HTML Anchor tag behaviour <ace:linkButton value="Right click to open www.yahoo.com in new tab" href="http://www.yahoo.com" /> 2) Standard JSF Ajax link behaviour <ace:linkButton value="Click link to fire action event on actionListener" actionListener="#{linkBean.buttonPressHandler}" /> 3) Hybrid Ajax and HTML anchor behaviour. Clicking on this link will fire actionListener, but not navigate to www.yahoo.com, however, right clicking on link allows www.yahoo.com to be opened in new tab or window. <ace:linkButton value="Right click to open www.yahoo.com in new tab" actionListener="#{linkBean.buttonPressHandler}" href="http://www.yahoo.com" />
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.
styleClass Append this name to the existing YUI classes (namely: "yui-button yui-link-button") to be used with CSS selectors.
Page 118
tabindex Passes the page tabindex value to the underlying anchor, default=0.
disabled Passes a disabled flag to the underlying YUI component. A 'true' value indicates the component is visible but disabled.
singleSubmit When singleSubmit is true, triggering an action on this component will submit and execute this component only (equivalent to <f:ajax execute="@this" render="@all">). When singleSubmit is false, triggering an action on this component will submit and execute the full form that this component is contained within. The default value is false.
href If no action or action listener is defined, the href is a standard anchor href. If an actionListener or action attribute are present the href parameter is available for opening in a new tab or window via right click.
hrefLang The hreflang attribute specifies the language of a linked document. For completeness only, as hreflang is not supported by any of the major browsers.
target Standard anchor target attribute. Available only on anchors with no action or action listener attributes.
ARIA support
LinkButton component supports keyboard short-cuts and ARIA. Aria support can be enabled at page level or at application level. By default ARIA is enabled at application level. To enable/disable ARIA at page level, the <icecore:config> tag can used:
<icecore:config ariaEnabled="true"/>
To enable/disable ARIA at application level, the following param can be set in web.xml.
Storyboard
Action yui-class
focus yui-buttonfocus
hover yui-buttonhover
disabled yui-buttondisabled
Page 119
none none
role
Page 120
PushButton 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The ace:pushButton component allows submission of a form in it's entirety or also the submission of itself only. This component supports an action attribute as well as an actionListener attribute similar to a h:commandButton.
Usage
<html ... xmlns:ace="http://www.icefaces.org/icefaces/components"> <!-- can use either class of ice-skin-sam or ice-skin-rime --> <h:body class="ice-skin-sam"> <h:form > <h:panelGroup id="push1"> <ace:pushButton id="pushId" value="submit" label="this button submits the entire form" actionListener="#{button.actionListenerMethod}" /> </h:panelGroup> </h:form> </h:body>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.
value refers to the text written on the button, similar to that of jsf commandButton.
label If no value present, the label will be used for the pushButton. Otherwise if both are used, the label will be used to define the aria-role, described-by.
Page 121
singleSubmit When singleSubmit attribute is true, the pushbutton only submits an event request via submit call with execute=@this and render=@all, in other words, only the button is submitted with any action/actionListener attributes. If false then full form submit happens where execute being set to @all. Default valid is false.
<icecore:config ariaEnabled="true"/>
To enable/disable ARIA at application level, the following param can be set in web.xml.
space or enter key will fire the button's onclick event Aria role="button", aria-describedby and aria-disabled properties supported The ARIA implementation is based on the specification at button aria practices. Currently only the basic ARIA attributes and single-key keyboard shortcuts have been implemented.
Storyboard
Action yui-class
focus yui-buttonfocus
hover yui-buttonhover
active yui-buttonactive
disabled yui-buttondisabled
onkeypress space or enter will submit submit form/queue event submit form/queue event
Submit
submit form & queus event submit button only & queue event
none
Single Submit
none
Action
Page 122
Page 123
SliderEntry 2.0
This page last changed on Oct 27, 2011 by ken.fyten.
Getting Started
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The sliderEntry component enables the user to adjust values in a finite range along a horizontal or vertical axis. It can be used as a visual replacement for an input box that takes a number as input. To use the slider component, first the ace component name-space has to be added in your page.
The second step is to apply a skin name on a parent element of slider component.
<h:form styleClass="ice-skin-rime">
Now you ready to use slider component, here is the basic example:
<ice:sliderEntry/>
<html ... xmlns:ice="http://www.icefaces.org/icefaces/components"> <body> <h:form styleClass="ice-skin-rime"> <ice:sliderEntry /> </h:form> </body> </html>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here .
Page 124
Define the value of slider: The value attribute of slider represents the current value. The default is 0.
Minimum value of slider: The min attribute specify value at the far left ot top of the rail. Default is 0.
<ice:sliderEntry min="10"/>
Maximum value of slider: The max attribute specify value at the far right or bottom of the rail. Default is 100.
<ice:sliderEntry max="60"/>
Changing the axis: This attribute specifies horizontal or vertical slider, "y" is for vertical. The default value is "x".
<ice:sliderEntry axis="y"/>
Defining the length of the slider: The length attribute defines the height of vertical Slider rail and width of horizontal slider rail. Default value is 150px.
<ice:sliderEntry length="300px"/>
Defining the thumb image: The thumbUrl attribute takes the path to an image to use as the <img> for the thumb. Default is / skins/sam/thumb-x.png
Page 125
Additional attributes
Defining style: The is a pass through to the root element of the slider. Defining style class: The is a pass through to the root element of the slider. Defining tabindex: The is a pass through to the root element of the slider. Defining the submission behaviour: When singleSubmit attribute is true, the slider value change event request a submit call with execute=@this and render=@all, if false then full submit happens where execute being set to @all. default valid is false. Capture value change event: The slider component fires a valueChange event, which can be captured using a valueChangeListener attribute on slider component.
<ice:sliderEntry valueChangeListener="#{bean.sliderChanged}"/>
Making the rail clickable: Clicking on the rail moves the thumb to that point. Default is true.
<icecore:config ariaEnabled="true"/>
To enable/disable ARIA at application level, the following param can be set in web.xml.
Page 126
ice.component.slider.getInstance(clientId, callback);
For example:
<h:form id="myform"> <ice:sliderEntry id="myslider" value="#{bean.value}"/> <input type="button" value="get slider value" onclick="ice.component.slider.getInstance( 'myform:myslider', function(slider) { alert(slider.get('value')); })"/> </h:form>
Page 127
TabSet 2.0
This page last changed on Nov 12, 2011 by mark.collette.
Overview
ICEfaces 2.0 Only This section is for the ICEfaces 2.0 Advanced Components only, and is not applicable to later releases (2.1+). For the latest ICEfaces Advanced Components documentation, see the ICEfaces Advanced Components topic. The ace:tabSet component is a container for its TabPane children, where the contents of only one TabPane may be visible at a given time. The TabSet may operate in a server-side mode where only the current TabPane's contents exist in the browser; or in client-side mode, where every TabPane's contents exist in the browser, and no server round-trip is necessary to change the current TabPane. The TabSet may be configured so that it need not itself be within a form, so that each TabPane may contain its own form.
Usage
1. To use the TabSet component, first the ICEfaces Advanced Components tag-lib name-space has to be added in your page.
2. Next, select your desired theme, by adding the appropriate styleClass to the body, or wherever in the page within which you want the theme to apply to
3. Finally, ensure that the CSS file for that particular theme to the bottom of the page. This will allow the contents of the CSS file to take precedence over everything else. If you have application CSS files, where you override theme style classes, add them to the bottom of the .xhtml page as well, after the theme
</h:body> <h:outputStylesheet library="org.icefaces.component.skins" name="rime.css" /> <!-- or --> <h:outputStylesheet library="org.icefaces.component.skins" name="sam.css" /> </f:view> </html>
Now you ready to use TabSet component, here is the basic example:
<ace:tabSet> <ace:tabPane label="Tab One"> <h:outputText value="Contents of tab one"/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:outputText value="Contents of tab one"/>
Page 128
</ace:tabPane> </ace:tabSet>
Attributes
TagLib Documentation This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here . clientSide The TabSet can be all client side, by just setting "clientSide" attribute to true.
<ace:tabSet clientSide="true"> <ace:tabPane label="Tab One"> <h:outputText value="Contents of tab one"/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:outputText value="Contents of tab one"/> </ace:tabPane> </ace:tabSet>
tabSetProxy The TabSet requires a form component to send its information to the server. So either it could be enclosed within a form component, or if you don't want to put TabSet inside a form component, then you could couple the TabSet component with the TabSetProxy component that is enclosed inside a form (e.g.)
<ace:tabSet id="myTabSet"> <ace:tabPane label="Tab One"> <h:outputText value="Contents of tab one"/> <br/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:outputText value="Contents of tab one" /> </ace:tabPane> </ace:tabSet> <h:form> <ace:tabSetProxy for="myTabSet" /> </h:form>
Note : In above example on tab change the form of the tabSetProxy will get submitted. singleSubmit When you change the tab it performs a full submit, which means it submits the form which its belongs to. That makes all fields with validators to be validated on tab change. You can turned this off by just setting "singleSubmit" attribute to true on the tabset component (e.g.)
<!-- This will cause a validation error, and not let you change the tab until you enter a value in the inpuText --> <h:messages/> <h:form> <ace:tabSet> <ace:tabPane label="Tab One"> <h:inputText required="true"/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:inputText required="true"/> </ace:tabPane>
Page 129
</ace:tabSet> </h:form> <!-- This will make it so only the TabSet will get executed --> <h:messages/> <h:form> <ace:tabSet singleSubmit="true"> <ace:tabPane label="Tab One"> <h:inputText required="true"/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:inputText required="true"/> </ace:tabPane> </ace:tabSet> </h:form>
cancelOnInvalid If you want to use full submit and still ignore validation error, then you can set cancelOnInvalid attribute to true.
<h:messages/> <h:form> <ace:tabSet cancelOnInvalid="true"> <ace:tabPane label="Tab One"> <h:inputText required="true"/> </ace:tabPane> <ace:tabPane label="Tab Two"> <h:inputText required="true"/> </ace:tabPane> </ace:tabSet> </h:form>
label facet Instead of using string based label on tab, the "label" facet allows you to put components inside the tab. For example:
<ace:tabSet> <ace:tabPane> <f:facet name="label"> <h:panelGrid columns="3"> <h:graphicImage url="images/icon.gif"/> <h:outputText value="Tab One"/> <h:commandButton value="close" actionListener="#{tabBean.closeTab}"> <f:ajax execute="closeTab" render="@all" /> </h:commandButton> </h:panelGrid> </f:facet> <h:outputText value="#{tabBean.tabContents}"/> </ace:tabPane> ..... </ace:tabSet>
Page 130
Overview
ACE provides a comprehensive mechanism for producing JSF components. It employs code generation to eliminate source redundancies, moving beyond xml files to instead use Java classes with annotations, called Meta classes. This allows for Java's strong typing, and IDE code completion to assist in efficiently authoring correct component definitions.
Sub-topics
ACE ACE ACE ACE ACE ACE ACE ThemeRoller support Source Artefacts and Generated Outputs Meta Class Component and Renderer Classes Adding Resources to Meta Class Skinning Disabled Styling Standard
Page 131
3. Deploy the theme in your application. 3.1 Put this .jar file inside the /WEB-INF/lib directory of your application. 3.2 In your web.xml file, add or set the org.icefaces.ace.theme context parameter to the name of your theme as the value.
Page 132
e.g.
Page 133
- Java Source ace\component\src\org\icefaces\component\[componentname] ace\component\src\org\icefaces\component\[componentname]\ComponentName.java ace\component\src\org\icefaces\component\[componentname]\ComponentNameMeta.java ace\component\src\org\icefaces\component\[componentname]\ComponentNameRenderer.java - Javascript and CSS Intrinsic Functionality Source ace\component\resources\org.icefaces.component.[componentname] ace\component\resources\org.icefaces.component.[componentname]\componentname.js - Javascript and CSS Skin Source ace\component\src\org\icefaces\component\[componentname]\skins\rime ace\component\src\org\icefaces\component\[componentname]\skins\rime\componentname.css ace\component\src\org\icefaces\component\[componentname]\skins\sam ace\component\src\org\icefaces\component\[componentname]\skins\sam\componentname.css - Generated Output Source ace\component\build\generated\base\org\icefaces\component\[componentname]\ComponentNameBase.java ace\component\build\generated\support\org\icefaces\component \[componentname]\ComponentNameMetaHandler.java ace\component\build\generated\support\org\icefaces\component\[componentname]\ComponentNameTag.java - Compiled Meta Class Files ace\component\build\meta\org\icefaces\component\[componentname]\ComponentNameMeta.class - Compiled Class Files ace\component\build\exploded\org\icefaces\component\[componentname] ace\component\build\exploded\org\icefaces\component\[componentname]\ComponentName.class ace\component\build\exploded\org\icefaces\component\[componentname]\ComponentNameBase.class ace\component\build\exploded\org\icefaces\component\[componentname]\ComponentNameMetaHandler.class ace\component\build\exploded\org\icefaces\component\[componentname]\ComponentNameRenderer.class
Page 134
ace\component\build\exploded\org\icefaces\component\[componentname]\ComponentNameTag.class
Page 135
Meta Class
A Meta class is the single location for defining most aspects of the component. It specifies the tag name, properties, fields, and facets, along with their documentation. It references the other related classes, and resource files, and enables animation support. It does not include actual methods with code, as that is what the Component class is intended for.
@Component( tagName = "tabSet", componentClass = "org.icefaces.component.tab.TabSet", rendererClass = "org.icefaces.component.tab.TabSetRenderer", generatedClass = "org.icefaces.component.tab.TabSetBase", extendsClass = "javax.faces.component.UIComponentBase", componentType = "org.icefaces.TabSet", rendererType = "org.icefaces.TabSetRenderer", componentFamily = "org.icefaces.TabSet", tlddoc = "This is where the component is documented") @ResourceDependencies({ @ResourceDependency(name="file.js",library="third_party_library"), @ResourceDependency(name="tabset.js",library="org.icefaces.component.tab"), @ResourceDependency(name="tabset.css",library="org.icefaces.component.tab") }) @ClientBehaviorHolder public class TabSetMeta extends UIComponentBaseMeta { @Property( defaultValue="0",
Page 136
tlddoc="This attribute represents index of the current selected tab") private int selectedIndex; @Property( expression=Expression.METHOD_EXPRESSION, methodExpressionArgument="javax.faces.event.ValueChangeEvent", tlddoc="On tab change, value change event can be captured using this") private MethodExpression tabChangeListener; @Facets class FacetsMeta{ @Facet UIComponent header; } }
Class Relationships
From the @Component Annotation, there are four classes referenced: generatedClass = "org.icefaces.component.tab.TabSetBase" Where all the properties, fields, and facets, declared in the Meta class, will be generated Refered to as the Base class extendsClass = "javax.faces.component.UIComponentBase" The class which the generated Base class will be made to extend componentClass = "org.icefaces.component.tab.TabSet" The end resulting component class Hand-coded class, where any custom methods and behaviours may be implemented Extends the Base class (generatedClass), so that it's methods have access to the generated properties rendererClass = "org.icefaces.component.tab.TabSetRenderer" Hand-coded class, which is an instance of Renderer, and is responsible for rendering the component Basically, the Component class (componentClass) extends the Base class (generatedClass) extends the Super-class (extendsClass). Implicitly, the generated Tag and MetaHandler classes will have their package and class names derived from the Component class. Given the example above, they would be: org.icefaces.component.tab.TabSetTag and org.icefaces.component.tab.TabSetMetaHandler. Another important class relationship is the baseMeta class that the Meta class itself extends. Just as @Component(extendsClass = "javax.faces.component.UIComponentBase"), there is the matching statement: public class TabSetMeta extends UIComponentBaseMeta. What this accomplishes, is it declares that this Meta class shall inherit the definitions from UIComponentBaseMeta, which contains the properties for UIComponentBase, when generating the TLD for the component. It is optional, since a component could potentially not want to expose it's super-class' properties as part of it's own public API. When used, it reduces a lot of boiler-plate property declarations, for standard properties such as: id, rendered, etc.
Common Annotations
The Meta class may contain the following annotations:
@Component Annotation
Used to describe the component as a whole, it mostly describes the class relationships, as well as some fields that the Base class and faces-config.xml need for wiring the component and renderer together. The tlddoc field is used for the TLD description of the component, which is useful for JSP and Facelets aware IDEs.
Page 137
A component may have a single @ResourceDependency annotation, or it may have a single @ResourceDependencies annotation, which itself may contain any number of @ResourceDependency annotations. Any of them specified on the Meta class are automatically duplicated in the generated Base class. The intention being that everything necessary for declaring the component may be placed within the Meta class, instead of being separately declared within the ending Component class. The purpose of a @ResourceDependency annotation is to declare which Javascript and CSS resources that the component relies upon, so that JSF may automatically include them on the page, when this component is on the page.
@ClientBehaviorHolder Annotation
Any component that integrates with the Animation API must have this specified. The generator uses it for outputting code that enables the animation integration.
@Property Annotation
The most frequently used, and most important annotation. When a property is specified, as a regular field within the Meta class, the field type specifies the property type, and the field name specifies the property name. The @Property annotation describes other details of the property, which a Java field declaration can not encapsulate. Properties fall into two basic categories: ValueExpression enabled properties, and MethodExpression properties. The default is a ValueExpression. To declare that a property is a Method Expression, which takes a ValueChangeEvent argument, one would put:
@Property(expression=Expression.METHOD_EXPRESSION, methodExpressionArgument="javax.faces.event.ValueChangeEvent")
A property has a default value. If none is specified, then it is null or 0 or 0.0 or false. In many cases the default value is a String literal, and in other cases it may be some sort of expression. Here are examples of both:
// Generates: String type = "Car"; @Property (value="Car") String type; // Generates: String manufacturer = Manufacturer.DEFAULT; @Property (value="Manufacturer.DEFAULT", defaultValueType=DefaultValueType.EXPRESSION) String manufacturer; // Generates: Integer count = 10; @Property (value="10", defaultValueType=DefaultValueType.EXPRESSION) Integer count;
In some specific circumstances, it's necessary to override the property name, because the name collides with a Java reserved word. The typical example is for. This is how one would specify a property named "for", even though one can't create a field named "for", as it's a Java reserved word:
The tlddoc field is used to specify the tag attribute description for this property.
Page 138
The javadocGet field is used to specify the contents of the javadoc that will be put above the generated getter method for this property, in the Base class. The javadocSet field is used to specify the contents of the javadoc that will be put above the generated setter method for this property, in the Base class. If javadocGet or javadocSet are not specified, then they will default to the value given for the tlddoc field. The required field specifies that this property is required, and must be specified when the component's tag is used. The default value is no, the property is not required. Properties either already exist in the component class' super-class, or they are new and must be generated within the Base class. But sometimes an inherited property can benefit from documentation that is more specific to this component. For example a component extending from UIOutput would inherit the value property. But each sub-class may render or represent that value differently, and so, wish to override the documentation. With the inherited property, it might make sense to not generate any getter or setter methods, since they already exist in the super-class. Or, it might make sense to override those getter and setter methods with generated ones, since ACE code generation better handles when components are within a UIData container, like a dataTable. To provide guidance, the @Property annotation may specify implementation=Implementation.EXISTS_IN_SUPERCLASS, meaning that the property and code already exist in the super-class, and not to generate anything, and to only allow the property to be redocumented, if tlddoc, javadocGet or javadocSet have been specified. Otherwise, if code should be generated, specify: implementation=Implementation.GENERATE, which is the default.
@Field Annotation
A field is similar to a property, but is essentially non-public. When a component needs to maintain some private internal state, which should not appear in the TLD, and that does not have a corresponding tag attribute, then a field is appropriate.
@Facet and @Facets Annotations
A Meta class field may have a @Facet annotation on it. Since JSF component facets exist in a different namespace from properties, a means of separating Meta facets into a separate namespace was necessary. So, a Meta class may contain an inner class, with a @Facets annotation, and then within that class, fields may have a @Facet annotation on them. The purpose of a @Facet annotation is to explicitly declare a component's facet API, and provide a means for documenting each facet. Technically it's not necessary, as facets may be used by passing in their String name into the facets Map, without the need for generated getter or setter methods, or any other supporting code. But, such an implicit, un-typed, and undocumented coding style does not fit with the ACE methodology.
@ClientBehaviorHolder and @ClientEvent Annotations
The @ClientBehaviorHolder annotation is placed at the class level in the Meta class. This annotation causes the generated component to implement the javax.faces.component.behavior.ClientBehaviorHolder interface, so that it can support the <ace:ajax /> tag. Its events property specifies a list of @ClientEvent annotations, and the defaultEvent property specifies the default event to trigger when an <ace:ajax /> tag is used without the event attribute. With @ClientEvent annotations one can define the various events supported by the component, using the following properties:
name - The name of the event. We follow the convention of writing the names in camel case. defaultExecute - The default value for the execute attribute in the <ace:ajax /> tag. defaultRender - The default value for the render attribute in the <ace:ajax /> tag. javadoc - Javadoc documentation for this event. tlddoc - TLDdoc documentation for this event. This is an example of the usage of these annotations:
Page 139
@ClientBehaviorHolder(events = { @ClientEvent(name="slideStart", javadoc="...", tlddoc="...", defaultRender="@all", defaultExecute="@all"), @ClientEvent(name="slide", javadoc="...", tlddoc="...", defaultRender="@all", defaultExecute="@all"), @ClientEvent(name="slideEnd", javadoc="...", tlddoc="...", defaultRender="@all", defaultExecute="@all") }, defaultEvent="slideEnd")
@TagHandler Annotation
Some of the tags that developers can use when working with the ACE component suite are not components per se, but they enhance other components in customized ways. Examples of this are the <ace:ajax /> and the <ace:animation /> tags. For features like these, a @TagHandler annotation must be used instead of the @Component annotation in the Meta class. Some of the properties are the same as those of the @Component annotation. The following properties are NOT applicable to tag handlers: componentClass, rendererClass, componentType, rendererType, and componentFamily. The following properties apply to this annotation:
tagHandlerType - Must have a value of the org.icefaces.ace.meta.annotation.TagHandlerType enum type, depending on which class of the javax.faces.view.facelets package is being extended. tagHandlerClass - Specifies the fully qualified class name of the tag handler (which will extend the generated base class). behaviorClass - If this tag handler is a JSF behavior, this property specifies the fully qualified class name of the behavior class (which extends javax.faces.component.behavior.ClientBehaviorBase in some way). behaviorId - The id for this behavior in the faces-config.xml file.
Page 140
Page 141
Directions
1. The intrinsic resources should be placed in the appropriate location
2. @ResourceDependency annotations, corresponding to the resources, should be added to the Meta class
3. The build process places the resources in the META-INF directory of the JAR
Page 142
ACE Skinning
This page last changed on Feb 01, 2011 by mark.collette.
Skinning
This article describes the two different ways of skinning a component and explains how the various skin-related resources are prepared at build time to be served by JSF. It also explains how to add more components and skins to this process. Finally, it describes how all CSS files of a skin are merged into one file.
Motivation
JSF 2 has its own resource handling mechanism. It is explained in detail in section 2.6 of the JSF 2.0 specification. The relevant points to this article are the following: Resources are contained in resource libraries. There is a well-defined URL format that must be used to access resources through this mechanism. Therefore, in ICEfaces, all resources used for skinning components (i.e. CSS and image files) are prepared at build time for JSF 2's resource handling mechanism. Optionally, these resources will undergo an optimization that consists of generating sprite images. In any case, the resulting resources (i.e. modified CSS files and generated images) will ultimately be prepared in the same way for JSF's resource handling mechanism.
Original Files
It is important to first clarify what is meant by original files in this context. These are all the raw, unprocessed skin-related files (i.e. CSS and image files). They are placed, by convention, in a directory named 'skins' inside the component's source directory. However, it is possible to place these files in any location. Inside this directory, there should be a subdirectory for every skin that the component supports. The name of this subdirectory should match the name of the skin across the entire project. For example, at the moment of this writing, the only supported skins are 'sam' and 'rime', so all components that support these skins have subdirectories inside 'skins' named exactly 'sam' and 'rime'. The CSS files inside these skin directories can reference image files in the usual way (i.e. with relative paths to the image files inside url() expressions). It is important not to reference images that are outside of the skin subdirectory. Even if two components use the same image, they must have their own copy. The purpose of this is to ease the job of customizing the look of specific components, without affecting others. If sprites are enabled, SmartSprites will automatically detect duplicate images and only include one copy of it in the generated sprite image.
Page 143
| +-- icon.png | +-- /rime | +-- mycomponent.css | +-- icon.png MyComponent.java MyComponentMeta.java MyComponentRenderer.java
At the end of the process, the files would be placed in the org.icefaces.component.skins resource library directory, as illustrated below.
ace/component/resources/org.icefaces.component.skins | +-- /rime | | | +-- /my_component | | | +-- calendar.css | | | +-- icon.png | +-- /sam | +-- /my_component | +-- calendar.css | +-- icon.png
The generated sprite images will always be placed directly under a org.icefaces.component.skins/<skinname> directory. Here is the concrete example for the sam skin:
This process will be carried out when building the main sparkle project (i.e. by just typing 'ant'). If one only wishes to perform the skins processing, one can just run the 'skins' target (i.e. by typing 'ant skins'). Likewise, one can clean only the skins by running the 'clean-skins' target. The 'skins' target depends on the 'cssurlmapper' target, which builds the tool that carries out the URL mapping.
Sprites and No-Sprites One can choose to use sprite images or not by setting/unsetting the 'use.sprites' property in the 'build.properties' file. Using sprites is only a performance optimization. The components should look exactly the same whether sprites are used or not. If 'use.sprites' is set, then, at build time, sprite images will be generated using the source images explained above, and the source CSS files will be modified to reference these generated images at the right offsets. More information on sprite generation can be found here. If 'use.sprites' is not set, then all images will be accessed individually.
Page 144
URL Mapping The 'cssurlmapper' tool will parse all CSS files (the original ones or the ones generated by SmartSprites) and will map all URLs contained in it to the format required by the JSF2 resource handling mechanism. The build script is configured to place the output files in a specified resource library directory. For example, the following URL appears in an original CSS file.
url(images/background.png)
url(#{resource['org.site.lib/images/background.png']})
More specific information about the CSS URL mapper can be found here.
If we are creating a completely new skin, then we must also call the task 'generatesprites', specifying its name in the 'skin' attribute. This is done only once per skin. An example of this would be the following.
Page 145
Where 'name' refers to the name of the skin. The skin names have to be the same that are used throughout the build script. The resulting files are placed in the 'org.icefaces.component.skins' resource library.They have the exact same name as the skin name specified and have the extenstion .css (e.g. '/ resources/org.icefaces.component.skins/rime.css').
Page 146
SmartSprites Tool
This section describes the basics of the SmartSprites tool per se and not how it is integrated into ICEfaces. Introduction SmartSprites is an open-source tool, written in Java, that generates sprite images based on individual source images and annotated CSS files. It is advanced enough to handle repeating background images and other issues. Annotating a CSS file for SmartSprites A CSS file meant to be processed by SmartSprites must have some special annotations and conventions. These are the four main requirements: 1. Annotations consist of CSS comments, similar to JavaDoc comments, containing semi-colon delimited entries, which are key/value pairs which are themselves colon delimited. 2. A sprite image declaration at the beginning of the file, specifying its identifier. 3. Use of the 'background-image' CSS property to indicate source image locations (Do not use the more general 'background' property). 4. An annotation next to the 'background-image' property to associate it with a declared sprite image. The next example illustrates the basic usage.
/** sprite: mysprite; sprite-image: url('../out/mysprite.png'); sprite-layout: vertical */ #header-box { background-image: url(logo.gif); /** sprite-ref: mysprite; */ }
In the declaration, the 'sprite' property specifies an identifier to be used within the file. The 'sprite-image' property specifies the location and format of the output image. The 'sprite-layout' property specifies whether the source images are to be placed below the previous ones (vertical) or just after them at the same height (horizontal). The 'background-image' property specifies a location of a source image, relative to the location of this CSS file. The 'sprite-ref' annotation next to 'background-image' associates this source image with a declared sprite image to be included in it. There can be more than one declarations in a single CSS file, resulting in the same number of output sprite images. Also, source images can be included in sprites declared in another CSS file as long as they use the correct identifier and both CSS files are processed in the same invocation of SmartSprites. The next example illustrates how to declare an image to be repeat along the x-axis.
#main-box {
Page 147
This will make SmartSprites to repeat the source image throughout the entire width of the output image, so that web browsers do not display blank space. If there is more than one image repeating along the x-axis in the same sprite, then the width of the output image will be the common denominator of the widths of all repeating images along the x-axis. Thus, web browsers will always show complete repetitions of the images. For images repeating along the y-axis, the value of the 'sprite-alignment' annotation must be the same, just 'repeat'. However, the referenced sprite must have a horizontal layout. Furthermore, it is not possible to include images repeating along the x-axis and images repeating along the y-axis in the same sprite image. Separate sprite images for each type of repetition must be created. This implies that any image meant to be repeated along both axes cannot be included in a sprite. The following table specifies the type of layout needed for the different types of image repetition.
Along the x axis -> Vertical layout Along the y axis -> Horizontal layout Over both axes -> Not to be included in sprite
Basic Command Syntax Once the CSS files are correctly annotated and the source images are in the right locations, it's time to run SmartSprites from the command line. There are a few ways to run SmartSprites. The easiest and most convenient way is by using the '--root-dir-path' parameter. Here is an example:
SmartSprites takes the directory specified and searches for CSS files to process in that directory and all subdirectories. SmartSprites outputs one CSS file for every source CSS file. This output file has the same name of the source CSS file plus a suffix (default is '-sprite'). This file is created in the same directory as the source CSS file. Also, All image locations specified in CSS files are relative to the CSS file location, as one would expect. It is also possible to specify a different output directory. If this directory does not exist, it will be created. This directory will keep the same structure as the root directory. Here is an example:
References More information can be found at the SmartSprites web site: http://csssprites.org/
Page 148
Annotation conventions First of all, all CSS files meant to be integrated into the sprite generation utility must be correctly annotated, as described above. However, in the ICEfaces approach there are two important points to keep in mind for these CSS files: It is not necessary to make new sprite declarations in the file. The sprite references to be used should be either 'sprite' (for non-repeating images), 'sprite-x' (for images repeating along the x-axis) or 'sprite-y' (for images repeating along the y-axis). While it is still possible to declare new sprites, there is no need to do so. The three sprite references in use cover all cases. These declarations are included in a file called 'base.css', which is added at build time to every skin. A typical CSS file would look like this:
#container { background-image: url(background.png); /** sprite-ref: sprite-x; sprite-alignment: repeat; */ background-repeat: repeat-x; }
Note that if an image is meant to be repeated over both x and y axes, then it shouldn't be incorporated into a sprite. It should simply stand alone and be placed somewhere in the directory of the skin it belongs to, or directly under the /resources directory if it's not related to a skin in particular. Naming and directory conventions Since many different skins can be supported, all the source image and CSS files related to a particular skin, for a particular component, should be inside the same directory, which should have the name of the skin, by convention. Moreover, it is recommended, but not necessary, that all skin directories for a particular component be inside the same directory. At the time of this writing, ICEfaces Advanced Components have a subdirectory named 'skins' which contains all their skins. The following figure illustrates the recommended directory hierarchy.
src/org/icefaces/component/my_component | +-- /skins | | | +-- /sam | | | | | +-- mycomponent.css | | | | | +-- icon.png | | | +-- /rime | | | +-- mycomponent.css | | | +-- icon.png | +-- MyComponent.java | +-- MyComponentMeta.java | +-- MyComponentRenderer.java
How to include source images and CSS files into the generated sprites Once the source images and CSS files are placed in the correct locations, it is necessary to declare them in the component build script. Inside the 'skins' target, each set of files should be included by adding a line like the following:
<includeresources dir="path/to/skin/directory" name="component_name" skin="skin_name" />
Page 149
The 'dir' attribute specifies the directory that contains the resources to be added. The 'name' directory specifies the output name of the directory that will contain the parsed CSS files within a skin directory. This name is usually the name of the component, but it can be anything. The 'skin' attribute specifies the name of the skin these resources are part of. This same name will be used as the name of the output directory that will contain all images and parsed CSS files for a the skin. A concrete example of this declaration would be the following:
<includeresources dir="src/org/icefaces/component/selectinputdate/skins/sam" name="calendar" skin="sam" />
These lines have to be added on a per-component, per-skin basis. All paths are relative to the directory that contains the build script. As one might have guessed, source images and CSS files to be included in the sprite generation can be placed anywhere, even outside the main 'src/org/icefaces/component' branch, and the directory that contains the skins does not necessarily have to be named '/skins'. If a completely new skin is added, it will also be necessary to add a line like the following, at the end of the 'sprites' task:
<generatesprites skin="skin_name" />
The generated sprite images and parsed CSS files will be written to the 'resources/ org.icefaces.component.skins' directory. It will contain a subdirectory for each skin, with the name declared for it. This directory will contain subdirectories for each component (i.e. for every <includeresources /> declaration for that skin). These subdirectories will have the names specified in the 'name' attribute of the <includeresources /> tag. These subdirectories will contain the parsed CSS files, while the generated sprite images (sprite.png, sprite-x.png, sprite-y.png) will be directly under the skin directory. The following figure illustrates this hierarchy.
resources/org.icefaces.component.skins | +-- /rime | | | +-- /calendar | | | | | +-- calendar.css | | | +-- sprite-x.png | +-- /sam | +-- /calendar | | | +-- calendar.css | +-- sprite-x.png
Image duplication Sometimes two or more different components might use the exact same image file for similar or different purposes. One might think that, for performance reasons, that file should be included for only one component and have the other component access it as well. It is actually recommended to do the opposite: to include a copy of the same file for each component. The motivation of having separate image and CSS files for each component, even if those images and CSS are the same or similar, is to ease the job of overriding the appearance of specific components. For example, if an application developer only wants to change the appearance of checkbox buttons, they would only have to modify the checkbox button skin files. If all button types used the exact same image and CSS files, it would be more difficult to decouple and then customize them. Fortunately, SmartSprites is smart enough to detect duplicate images and only include them once in the final sprite image.
Page 150
Format
The JSF resource handling format is explained in detail in section 2.6 of the JSF 2.0 specification. Only the most important points are explained here. It is best to start by illustrating the format with a typical example. A background image located in a different directory than the CSS file in question might be declared as follows:
url(../images/background.png)
url(#{resource['org.site.lib/images/background.png']})
This format can be broken down into three logical parts. The first part is the resource declaration format, which is constant:
url(#{resource['']})
The second part is the name of the resource library in which the image will be located in a production environment.
org.site.lib
The third part is the full path to the resource starting from the root directory of the resource library.
Page 151
/images/background.png
This is an important point, since the JSF resource handling system needs to work with canonical paths. It does not recognize relative paths containing of '/../' Therefore, this tool also does the job of determining the canonical path from the resource library root directory. It is also important to note that the JSF specification also allows some other URL formats, but this tool only uses the format described above (i.e. libraryName/path/to/resource). URLs starting with 'http://' or '#{resource' will not be modified since they reference external resources or are already in the correct format.
Usage
Again, it is better to start by illustrating a typical example. This tool might be invoked as follows:
The --library-name parameter is required and specifies the name of the resource library where the resource will be located in the production environment. The --root-dir parameter specifies the directory name where this tool should start looking for files with css extension to parse. Alternatively, a single file to parse can be specified with the --file parameter. It is required to specify one of these two parameters. The --root-dir parameter takes precedence. The --output-dir parameter is required and specifies the directory where the output files will be written. This directory will have the same structure as the directory specified with the --root-dir parameter. All output files will have the same name as the original files. The --reference-dir parameter is optional and allows to specify a different starting point to build the full canonical path for the resources. If this parameter is not specified, the reference directory will be the same as the one specified with --root-dir, or the same directory containing the file specified with --file. The --help parameter will print a brief description of the tool itself and of all parameters.
Page 152
Disabling a component
This varies from component to component. If the YUI component has the capability built in, we need only set a disabled property. Or in some cases where the component is created from markup, set a disabled style class in the markup. For components that don't have a built-in disabled property, we have to disable all the constituent interactive elements ourselves. For a simple component, we need only set the disabled attribute of the underlying element. For example, a button component only requires setting the disabled attribute of the underlying button element. (This is actually done by YUI already, because the YUI Button class has a disabled property built in.) However, according to the HTML spec., the disabled attribtute is not applicable to a link element. Therefore, for a link element, we need to replace the rendered anchor tag with text/label. Other cases may require disabling certain listeners. The most difficult task should be locating the constituent elements, and disabling them at the right stage of the rendering process. This may require modifying YUI source code. Modifying YUI source in place should be avoided. A better way is make a copy of functions, modify them, and use YUI's class extension mechanism to override the original functions. Still, when the functions are many and complex, they will still require tedious maintenance work when upgrading to a new YUI version.
The disabled class name is usually formed by appending "-disabled" to the enabled class name, but sometimes it is just the general name of "disabled", esp. when there is no enabled class name in the first place. For example, for a disabled tab, it looks like this:
We should do the same when setting our or user's style classes in the root div. It is probably clearer to use the first pattern. But the second pattern makes for more elegant CSS rules:
Looks like even in YUI 3 the first pattern is still used. Therefore, for clearer understanding and crossbrowser compatibility, we should use the first pattern when setting style classes in our component root div.
Page 153
Portlet Development
This page last changed on Apr 20, 2011 by deryk.sinotte.
Portlet Development
Portlet support in ICEfaces is now provided by the PortletFaces Bridge, an implementation of the JSR 329: Portlet 2.0 Bridge for JavaServer Faces. The portlet bridge specification technically applies to JSF 1.2 but the PortletFaces version been adapted to support JSF 2. The PortletFaces Bridge is tested and shipped with the ICEfaces 2 distribution and can be used to develop portlet applications with ICEfaces. Liferay 6 The current versions of ICEfaces 2 and the PortletFaces Bridge currently support Liferay 5 and 6 at this time. Additional portal platforms will be added in future releases.
Examples
The following sample portlets are included in the ICEfaces 2 distribution. The examples are useful for getting a quick start on how to build a portlet using ICEfaces and the PortletFaces Bridge. This includes what the markup should look like, what files need to be included, and how they should be configured. For each portlet example, there is a corresponding non-portlet example. Looking under the icefaces.dir/ samples, you'll find:
Each portlet example is built by using the content from the non-portlet sample and adding in the portletspecific files required. Details for each sample are provide below. Chat The Chat example is a demonstration portlet that uses only stock JSF components and ICEpush. You can drop multiple instances on a single portal page and chat between the instances and between different browsers. The sample code is located under:
[icefaces2.dir]/icefaces/samples/core/chat-portlet
To build a portlet .war file for Liferay 6 running on Tomcat 6.0, you execute the following ant command from the chat directory:
Page 154
This .war file can be deployed directly to the Liferay deploy directory. Once deployed, it will show up in the list of available portlets under the ICEfaces2 -> ICEpush category. Component Showcase The Component Showcase portlets are examples based on the ICEfaces Component Suite configured to run in a portal. It uses the same Component Showcase markup and code as the non-portlet demo, but with each component example delivered as an individual portlet. The sample is located under:
[icefaces2.dir]/icefaces/samples/compat/component-showcase-portlets
To build a portlet .war file for Liferay 6 running on Tomcat 6.0, you execute the following ant command from the chat directory:
This .war file can be deployed directly to the Liferay deploy directory. Once deployed, it will show up in the list of available portlets under the ICEfaces2 category. Below ICEfaces2, the various components are grouped under a number of sub-categories (e.g. Input, Output, Datatable, etc.). ACE File Entry ACE Portlets With the exception of the File Entry component, ACE components do not currently run on Liferay due to a YUI library conflict. This will be rectified in a later release. See ICEfaces 2.0.0 Release Notes for a full list of issues pertaining to portlets and ICEfaces 2. The ACE Showcase can be built and deployed as a portlet to demonstrate the File Entry component. It uses the same ACE Showcase markup and code as the non-portlet demo, but with the File Entry component delivered as an individual portlet. The sample is located under:
[icefaces2.dir]/icefaces/samples/ace/showcase-portlets
To build a portlet .war file for Liferay 6 running on Tomcat 6.0, you execute the following ant command from the chat directory:
Page 155
This .war file can be deployed directly to the Liferay deploy directory. Once deployed, it will show up in the list of available portlets under the ICEfaces2 -> ACE category.
portlet.xml ICEfaces 2 makes use of the PortletFaces Bridge to handle the mapping of the portlet lifecycle onto the JSF lifecycle. This has many advantages like enabling proper resource handling and cleaner integration with the portal container. To define your portlet, take a look at the portlet definition of the chat portlet example:
<portlet> <portlet-name>chat-ice2-portlet</portlet-name> <display-name>Chat</display-name> <portlet-class>org.portletfaces.bridge.GenericFacesPortlet</portlet-class> <init-param> <name>javax.portlet.faces.defaultViewId.view</name> <value>/chat.xhtml</value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>ICEfaces 2 Chat</title> <short-title>ICEfaces 2 Chat</short-title> <keywords>icefaces portlet chat icepush</keywords> </portlet-info> </portlet>
The important parts are: The portlet-class, which needs to be defined as org.portletfaces.bridge.GenericFacesPortlet. The javax.portlet.faces.defaultViewId.view which should identify the page that is the initial view of the portlet. web.xml To prevent the processing of portlet resource URLs to avoid caching of things like bridge.js, the following parameter should be set to false.
Using the fileEntry component on Liferay 6 requires that the mandatoryResourceConfiguration configuration parameter be set in the web.xml as follows:
Page 156
Library Dependencies The ICEfaces 2 distribution includes a tested release version of the PortletFaces Bridge and is located in:
[icefaces2.dir]/icefaces/lib/portlets
portletfaces-bridge-2.0.0.jar
Page 157
New applications must be developed in Facelets. Existing applications that use Facelets can be migrated with little or no modifications to the pages.
JSP
In ICEfaces 2, JSP is no longer supported for creating pages. All development should be done in Facelets.
Porting
Here are some of the things you may need to adjust as you move your applications from ICEfaces 1.8.x to ICEfaces 2: The <f:view> tag is not strictly required. However, if you do have it in your page, then it should be nested within the <html> tag and not outside of it. The <ice:outputDeclaration> tag and component are no longer required. When using JSTL with Facelets in JSF 2, use the following namespace in your .xhtml pages:
xmlns:c="http://java.sun.com/jsp/jstl/core"
Configuration
JSF 2 provides a number of annotations to make configuration easier with JSF 2 applications. In fact it's possible to have an application that has no faces-config.xml file at all. Additionally, ICEfaces 2 takes advantage or the various extension points and features provided by JSF 2 for better and more compatible integration.
Porting
In ICEfaces 1.8.x, it was necessary, when using Facelets, to specify a custom ViewHandler in your faces-config.xml file. This is no longer required and should be removed from your configuration.:
Page 158
The custom servlets and mappings specified in ICEfaces 1.8.x applications are no longer required:
<servlet> <servlet-name>Persistent Faces Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet> <servlet-name>Blocking Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet-mapping> <servlet-name>Persistent Faces Servlet</servlet-name> <url-pattern>*.iface</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Persistent Faces Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Blocking Servlet</servlet-name> <url-pattern>/block/*</url-pattern> </servlet-mapping>
If your application runs in compatibility mode and uses the ICEfaces 1.8 dynamic resource API directly or uses components that use the dynamic resource API (OutputResource, DataExporter, HtmlGraphicImage, InputRichText), you must configure the CompatResourceServlet and servlet mapping to ensure that the resources are properly handled for JSF 2. Add the following to the web.xml of you application:
<servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping>
Page 159
When using compatibility mode the following configuration is recommended (in the web.xml file) to emulate expected behavior that was included in the ICEfaces 1.8 Facelets implementation:
When using compatibility mode the following configuration is recommended (in the web.xml file) to ensure consistent behaviour when using partialSubmit and validation tags (e.g. f:validateLength) when the Bean Validation library is involved:
Scopes
By default, ICEfaces 1.x operated under what was referred to as extended request scope. In a nutshell, extended request scope refers to the behavior that a new request is only associated with a change in view. This means that Ajax requests that occur within an existing view are not treated by ICEfaces as new requests. A request is not considered a new request unless it results in a new view so requestscoped beans would not be recreated until a new view was created. This behavior was configurable to allow for the more standard definition of request scope but was considered necessary at the time because the existing standard scopes (request, session, application, none) were not sufficient for supporting ICEfaces features like partial submit and Ajax Push. ICEfaces 2 introduces a new custom scope called Window scope. This new scope is designed to fill a gap in the existing scopes available for JSF 2. A Window-scoped bean exists for the life of a browser window or tab but is also built to survive reloads and refreshes. This means it can last over the life of multiple ICEfaces views (Window Scope does not persist across non-ICEfaces views).
Porting
As of ICEfaces 2, extended request scope is no longer supported so if your application was relying specifically on this behaviour, you may need to adjust the scope of your beans. The options are: Request: This scope is provided by JSF 2 and lasts briefly for the duration a single user event or render. It is useful for transient communication between components or beans on the same page. View: This scope is provided by JSF 2 and lasts the duration of a view. This would typically be the closest match for the old extended request scope behaviour. Flash: This scope is provided by JSF 2 and is a short, conversation-style scope that exists for a single view transition, including reloads. Window: This scope is provided by ICEfaces and lasts for the duration of a browser window. It is a good replacement for Extended Request Scope for state that is expected to survive a browser reload. As there is a mechanism for providing and using custom scopes in JSF 2, you can specify that your bean use Window scope by simply adding the correct annotation. For example:
@ManagedBean(name = "windowBean") @CustomScoped(value = "#{window}") public class MyBean implements Serializable { ...
Page 160
Both View Scope and Window Scope allow beans to be associated with individual views, thereby allowing the application to handle multi-tab/multi-window use. The choice of which one to use depends mainly on the expected behavior under the browser reload button. If "reload" should be a "reset" (clearing state in the current view) then View Scope should be used. If "reload" should be a "refresh" (having little or no impact on the application) then Window Scope should be used.
Components
ICEfaces 2 includes a version of the ICEfaces 1.x component suite that has been modified and tested to work with the ICEfaces 2 core framework. This provides developers with a couple of benefits. First, the standard JSF components that come with the JSF implementation are fully supported by ICEfaces so you can start building ICEfaces-enabled applications immediately using those components. However, the basic set of components is typically not sophisticated enough for most applications. They require a richer set of components like those found in the ICEfaces 1.8.x framework. By including a library of compatible ICEfaces 1.8.x components, developers have immediate access to a large, mature, well-tested component suite. Additionally, for those existing ICEfaces 1.8.x applications that are being considered for migration to ICEfaces 2, the compatible component library allows full support for all the components that developers are currently using, making it much simpler to port the application. The compatibility layer for components comes in one library: icefaces-compat.jar: This library is the full set of custom and extended components from ICEfaces 1.x, updated to run on the ICEfaces 2/JSF 2 frameworks. Simply by including this library with your application provides access to the components previously available in ICEfaces 1.x. The following ICEfaces 1.8.2 Component Suite components are no longer present in ICEfaces 2.0:
Porting
ice:inputFile (use ace:fileEntry instead) ice:outputDeclaration (use Facelets standard approach / "<DOCTYPE ...>" instead) ice:outputBody (use h:body instead) ice:outputHead (use h:head instead) ice:outputHtml (use <HTML> tag instead)
Using the compatible component library means that there are no changes or adjustments to components, either in the page markup or in the backing beans, when porting an ICEfaces 1.8 applications to ICEfaces 2. One exception is the ice:portlet tag. With ICEfaces 1.8, the ice:portlet component was used to namespace and uniquely identify each portlet on a page. With ICEfaces 2 and the portlet bridge, this component is no longer required or supported and should be removed from the page markup. The ICEfaces 2 compatible component library contains additional protection against cross-sitescripting attacks. It is possible that existing applications have been relying on the ability to render HTML markup into text labels. If so, the application will need to be modified to make use of outputText with "escape" set to false.
JavaScript API
The client-side JavaScript API for ICEfaces 2 has changed from the ICEfaces 1.8.x version. The new API is described in detail in the JavaScript Client API section. For compatibility and porting purposes, the original API from ICEfaces 1.8.x is still available in the compatibility library. For the most part, these are now just wrapper methods that call into the ICEfaces 2 API.
Porting
Usage of the client-side JavaScript API is mostly transparent. The components that use the ICEfaces 1.8.x API will now simply use the wrapper versions of the older methods which end up calling through to the ICEfaces 2 APIs. If your application is calling the older API directly, you should see the same benefit.
Page 161
Server-side API
Although we've made every attempt to make ICEfaces 2 as compatible as possible, there are some APIs that have changed or been dropped since 1.8.
Porting
The com.icesoft.faces.context.DisposableBean class is no longer available. Instead, use the JSF2 @PostConstruct and @PreDestroy annotations on methods that you would like called after your bean has been constructed and before it goes out of scope.
Ajax Push
ICEfaces 2 now uses the ICEpush product for Ajax Push. For information on porting to or using Ajax Push in ICEfaces 2, see the documentation on Ajax Push - APIs.
Portlets
You can now build and run your portlets under ICEfaces 2 using the PortletFaces Bridge. You can find more details about running the examples and building your own porlets in the Portlet Development section.
Porting
To port your existing portlets to use ICEfaces 2 and the PortletFaces Bridge you should Modify your portlet.xml file to use the PortletFaces Bridge servlet. See the section on the portlet.xml file for more information. Ensure you are using all the proper libraries. See the section on Portlet Library Dependencies for more information. Remove the <ice:portlet> tag from your markup. This component is no longer required or supported.
External Scripts
Certain components may rely on external 3rd-party scripts that will not work correctly unless the script is loaded and made available in the <head> on the initial GET request for the page. This can be difficult for components that might get added or rendered out dynamically after the initial page render. ICEfaces includes a feature for annotating the components that need this type of support for external scripts.
The annotation specifies the location of the script as well as the context parameter required to be set. If the component with the annotation is detected and the context parameter is set, then the script link will automatically be rendered out to the <head> of the document on the initial render.
Page 162
GMap
This situation applies specifically For the GMap component. The GMapRenderer is annotated with the ExternalScript annotation so if the icefaces-compat.jar is present in your application and the context parameter 'com.icesoft.faces.gmapKey' is set in the web.xml file, then ICEfaces will automatically render out the necessary script link to the <head> of the document.
Page 163
API Documentation
This page last changed on Mar 30, 2011 by ken.fyten.
ICEfaces Core
ICEfaces Core API JavaDoc ICEfaces Compatibility API JavaDoc ICEfaces JavaScript Client API
ICEfaces Components
The complete API documentation set is also included in the ICEfaces download bundles.
Page 164
Tutorials
This page last changed on Nov 15, 2010 by ken.fyten.
Introductory Tutorials Creating ICEfaces 2.1 Applications with Eclipse Getting Started with ICEfaces 2 Creating ICEfaces Applications with Eclipse Converting ICEfaces 1.8 Applications to ICEfaces 2 Converting ICEfaces 1.8 Components to ICEfaces 2 ICEfaces Feature Tutorial Easy Ajax Push Using Single Submit Using Window Scope ICEfaces Component Tutorials Auto-Complete Calendar Chart Columns Connection Status Data Table Drag & Drop Effects Menu Bar Panel Series Popup Progress Bar Tree ICEfaces Advanced Component Tutorials Incremental Upload Processing Using FileEntryCallback General Tutorials Creating Your First Hibernate-Enabled Application Using ICEfaces with CDI Using ICEfaces with Spring - Spring Web Flow 2 - Spring Security Converters Creating a Composite Component Internationalization in ICEfaces Validators
Page 165
Introductory Tutorials
This page last changed on Dec 10, 2010 by steve.maryka.
Creating ICEfaces 2.1 Applications with Eclipse Getting Started with ICEfaces 2 Creating ICEfaces Applications with Eclipse Converting ICEfaces 1.8 Applications to ICEfaces 2 Converting ICEfaces 1.8 Components to ICEfaces 2
Page 166
List of topics covered in this tutorial: 1. 2. 3. 4. ICEfaces 2.1 Eclipse Plugin Creating an ICEfaces 2.1 Project Running an ICEfaces 2.1 Project Adding an ICEfaces 2.1 Advanced (ACE) Component
Page 167
Start Eclipse. From the Eclipse main menu bar, select Help -> Install New Software... -> Add --> Archive... Select the plugin (zip file) from your local directory, give it a name and click Ok.
Select the checkbox beside ICEfaces Update Site, click Next, accept Licenses and click Finish.
Page 168
Page 169
Type in the Project name and select a Target runtime. For Configuration, select 'ICEfaces 2 Default Project Configuration' and click Next>
Page 170
In the JSF Capabilities dialog, there is a download button (with the arrow pointing down) available to download the required JSF and ICEfaces jars. Click on the button to launch the Download Library dialog.
Page 171
Once you click the button you will see a list of selections similar to those in the image below. Libraries have to be downloaded one at a time. To download a library, highlight it and click Next> to accept the license. Finally, click Finish. The JSF 2 (Mojarra 2.1.3) jars are required.
Page 172
After the libraries have been downloaded select the libraries you want to include in your project by checking the checkbox beside each library. Click Next>
Page 173
The next dialog is related to ICEfaces configurations. Accept the defaults and Click Finish:
Page 174
Page 175
Page 176
If you have downloaded and extracted Tomcat 7 locally, in the Run On Server dialog choose Tomcat 7. The first time you do this, you will be asked to browse to the location of Tomcat 7 on your file system:
Page 177
After clicking on the Finish button, Eclipse will launch the application in the browser you have selected under Window -> Web Browser:
Page 178
Page 179
You can select ICEfaces Advanced Components and/or ICEfaces components from the Palette. In this case we select a dateTimeEntry component from the ICEfaces Advanced components:
Page 180
Page 181
Page 182
Create a new Java class file called YourBean in the package org.icefaces.view and paste the code below:
package org.icefaces.view; import java.io.Serializable; import java.util.Date; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import org.icefaces.ace.event.DateSelectEvent;
Page 183
@ManagedBean(name= "yourBean") @ViewScoped public class YourBean implements Serializable { private Date selectDateProperty = new Date(System.currentTimeMillis()); public Date getSelectDateProperty() { return selectDateProperty; } public void setSelectDateProperty(Date selectDateProperty) { this.selectDateProperty = selectDateProperty; } public void dateSelectListener(DateSelectEvent event) { setSelectDateProperty(event.getDate()); } }
This bean model has an instance variable to back the field on our page. The dateSelectListener method will set the instance variable to the value what was submitted, but otherwise the class is simple. We can now run the application and see the added component rendered out to the browser:
Page 184
Page 185
This tutorial will discuss the following topics related to ICEfaces 2: Adding ICEfaces 2 to a JSF 2 Project Direct-to-DOM (D2D) Rendering Single Submit Window Scope Adding ICEfaces ACE Components Adding ICEfaces Components Adding AJAX Push Tutorial Source Code Download
Direct-to-DOM Rendering
This tutorial makes use of a JSF 2 application. The application consists of a page to add a new Job Applicant:
Page 186
Page 187
<h:commandButton id="clearButton" value="Clear"> <f:ajax event="click" render="@form" listener="#{applicantController.clearForm}" immediate="true" /> </h:commandButton>
Here we see the use of stock JSF tags including the new f:ajax tag. The render="@form" attribute on the f:ajax tag informs JSF that only the form should be rendered after the lifecycle is executed. Pressing the "Clear" button under these circumstances will generate the following response, which includes the entire form:
<?xml version="1.0" encoding="utf-8"?> <partial-response><changes><update id="form"><![CDATA[ <form id="form" name="form" method="post" action="/jobApplication/job-applicant.jsf" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="form" value="form" /> <div class="header"> <img src="/jobApplication/javax.faces.resource/icefaces.png.jsf?ln=images" alt="" /></div> <div class="content"> <div class="menu">
Page 188
<input type="button" onclick="window.location.href='/jobApplication/applicants.jsf'; return false;" value="Listing Page" /> </div> <div class="contentBody"> <div id="form:table" style="background-color:;"> <table> <tr> <td><label for="form:title">Title</label></td> <td> <table id="form:title"> <tr> <td> <input type="radio" name="form:title" id="form:title:0" value="1" <label for="form:title:0"> Dr.</label> </td> <td> <input type="radio" name="form:title" id="form:title:1" value="2" <label for="form:title:1"> Ms.</label> </td> <td> <input type="radio" name="form:title" id="form:title:2" value="3" <label for="form:title:2"> Mrs.</label> </td> <td> <input type="radio" name="form:title" id="form:title:3" value="4" <label for="form:title:3"> Miss</label> </td> <td> <input type="radio" name="form:title" id="form:title:4" value="5" <label for="form:title:4"> Mr.</label> </td> </tr> </table> </td> <td></td> </tr> <tr> <td> <label for="form:firstName:input" style="float:left;">First Name</label> </td> <td> <input id="form:firstName:input" type="text" name="form:firstName:input" value="" style="float:left;" /> </td> <td> <span id="form:firstName:msg"></span> </td> </tr> <tr> <td> <label for="form:lastName:input" style="float:left;">Last Name</label> </td> <td> <input id="form:lastName:input" type="text" name="form:lastName:input" value="" style="float:left;" /> </td> <td> <span id="form:lastName:msg"></span> </td> </tr>
/>
/>
/>
/>
/>
Page 189
<tr> <td> <label for="form:email:input" style="float:left;">Email </label> </td> <td> <input id="form:email:input" type="text" name="form:email:input" value="" style="float:left;" onblur="mojarra.ab(this,event,'blur',0,'form:email:msg')" /> </td> <td> <span id="form:email:msg"></span> </td> </tr> <tr> <td> <input type="submit" name="form:j_idt50" value="Submit Applicant" /> </td> <td> <input id="form:clearButton" type="submit" name="form:clearButton" value="Clear" onclick="mojarra.ab(this,event,'click',0,'@form');return false" /> </td> <td> <input id="form:cancelButton" type="submit" name="form:cancelButton" value="Cancel" /> </td> </tr> </table> </div> </div> <div style="clear:both;"></div> </div> </form>]]></update> <update id="javax.faces.ViewState"> <![CDATA[6613003036389132071:131205412038135456]]> </update></changes></partial-response>
ICEfaces 2 renders component markup to a server-side DOM (Document Object Model) that reflects the current client view. Each time the JSF lifecycle runs a DOM comparison is done and, if there are any changes, a concise set of page updates are sent back to the client to be applied to the page. We call this Direct-to-DOM or D2D rendering. Adding the ICEfaces 2 library to an existing JSF 2 application will provide dynamic partial-page-updates for all compliant components, without the need to specify the "f:ajax" component in your pages. Simply add the icefaces.jar to the application and we have Direct-to-Dom (D2D) rendering applied to the page. Now, when we press the "Clear" button, we get the following response which only updates two hidden fields:
<?xml version="1.0" encoding="utf-8"?> <partial-response><changes><update id="v3wbj72"><![CDATA[ <form action="/jobApplication/job-applicant.jsf" id="v3wbj72" method="post" name="v3wbj72"> <input name="v3wbj72" type="hidden" value="v3wbj72" /> <input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState" type="hidden" value="-6647367167940831220:-1927413051417630450" /> </form>]]> </update>
Page 190
With Direct-to-DOM rendering, we no longer need the f:ajax tag nested in our "Clear" button:
Notice the difference in the amount of markup sent back in the response - and this is for a small form with only four fields. Direct-to-DOM rendering is powerful stuff. The beauty is that from a developer point of view, it takes place automatically under the covers. This is what we call Automatic Ajax. The AJAX is built in to the framework and you do not have to concern yourself with how updates are applied, Directto-DOM rendering takes care of it for you.
Single Submit
The Single Submit feature is basically the ability to specify that only one component will execute in the JSF lifecycle. ICEfaces 2 Single Submit is similar in intent to ICEfaces Partial Submit, but is an improvement which leverages JSF 2 expanded capabilities. The <icecore:singleSubmit> tag is a convenient and easy way to Single Submit enable standard h: components, without having to litter the page with <f:ajax> tags. It allows an entire page region to be enabled at once. Simply add the namespace to your page. In job-applicant.xhtml add the following:
xmlns:icecore="http://www.icefaces.org/icefaces/core"
<icecore:singleSubmit />
All the form fields will now behave as if they have a nested f:ajax tag with the execute="@this" attribute. As the user tabs through fields in the form, the individual fields are executed in the JSF lifecycle and immediate feedback is provided, enhancing the user experience:
Page 191
In this case, we have tabbed through the first three fields and those components have been executed on the server. They all have the required="true" attribute and because nothing was input in the field, a FacesMessage was automatically generated and output in the page via the h:message tag. We have arrived at the email field without performing a full form submit, but have been able to generate feedback on fields we have already visited.
Window Scope
ICEfaces 2 also introduces a new custom scope called "Window" scope. This custom scope is designed to fill in a gap in the existing scopes available for JSF 2, as it exists for the life of a browser window or tab including surviving reloads and refreshes.
Page 192
Provide support for W3C ARIA accessibility features in all applicable components, including keyboard navigation. The following Advanced Components are included in the ICEfaces 2 distribution: Animation CheckboxButton DateTimeEntry FileEntry LinkButton PushButton SliderEntry TabSet
Page 193
outputConnectionStatus outputDeclaration outputFormat outputHead outputHtml outputLabel outputLink outputMedia outputProgress outputResource outputStyle outputText panelBorder panelCollapsible panelConfirmation panelDivider panelGrid panelGroup panelLayout panelPopup panelPositioned panelSeries panelStack panelTab panelTabSet panelTooltip portlet radio rowSelector selectBooleanCheckbox selectInputDate selectInputText selectManyCheckbox selectManyListbox selectManyMenu selectOneListbox selectOneMenu selectOneRadio setEventPhase tabChangeListener tree treeNode
To use the components, add the icefaces-compat.jar to your application. NOTE: If you are using the ICEfaces Components you will also require additional 3rd party libraries. See Appendix A - ICEfaces Library/App. Server Dependencies in the ICEfaces 1.8 Developer's Guide for details.
PushRenderer.addCurrentSession(String groupName);
Page 194
When something of note changes in the application, you can request the client get a notification to get the updates by calling:
PushRenderer.render(groupName);
In our tutorial application, we can take advantage of AJAX Push by updating the applicants list after a new job applicant has been added. First, we will add a PushManager class:
@ManagedBean @ViewScoped public class PushManager implements Serializable { private static final String GROUP = "applicants"; public PushManager() { PushRenderer.addCurrentSession(GROUP); } public void push() { PushRenderer.render(GROUP); } public String getGroup() { return GROUP; } }
Any user viewing this page will have a view scope instance of PushManager in scope. The next step is to push an update out to everyone once a new job applicant has been added. In our ApplicantController.java class we add the following to the addApplicant() method:
If we open a browser window in Internet Explorer and one in FireFox we will have two separate sessions running in our tutorial application. In FireFox, we have already added a job applicant to our applicants list:
Page 195
Page 196
After the "Submit Applicant" button has been pressed, the Firefox window immediately receives an update via AJAX push:
Page 197
With AJAX Push added to the application, users receive real-time updates from the server without needing to initiate a request to the server. Adding icefaces.jar, icefaces-ace.jar and icepush.jar to your JSF 2 applications will equip you with all the tools necessary to create AJAX enabled Rich Internet Applications.
Example getting-started-tutorial
Page 198
List of topics covered in this tutorial: 1. 2. 3. 4. ICEfaces 2 Eclipse Plugin Creating an ICEfaces 2 Project Running an ICEfaces 2 Project Adding an ICEfaces 2 Advanced (ACE) Component
Page 199
Start Eclipse. From the Eclipse main menu bar, select Help -> Install New Software... -> Add --> Archive... Select the plugin (zip file) from your local directory, give it a name and click Ok.
Select the checkbox beside ICEfaces Update Site, click Next, accept Licenses and click Finish.
Page 200
Page 201
Type in the Project name and select a Target runtime. For Configuration, select 'ICEfaces 2 Project' and click Next>
Page 202
In the JSF Capabilities dialog, there is a download button (with the arrow pointing down) available to download the required JSF and ICEfaces jars. Click on the button to launch the Download Library dialog.
Page 203
Once you click the button you will see a list of selections similar to those in the image below. Libraries have to be downloaded one at a time. To download a library, highlight it and click Next> to accept the license. Finally, click Finish. The JSF jars (we recommend Mojarra) and the ICEfaces Core Library are required. Optionally, you can download ICEPush (for AJAX push), ICEfaces Advanced Components(ICEfaces 2 components) and/or the ICEfaces Components Libraries (ICEfaces 1.8.2 components compatible with ICEfaces 2).
Page 204
After the libraries have been downloaded select the libraries you want to include in your project by checking the checkbox beside each library. Click Next>
Page 205
The next dialog is related to ICEfaces configurations. Accept the defaults and Click Finish:
Page 206
Page 207
If you have downloaded and extracted Tomcat 7 locally, in the Run On Server dialog choose Tomcat 7. The first time you do this, you will be asked to browse to the location of Tomcat 7 on your file system:
Page 208
After clicking on the Finish button, Eclipse will launch the application in the browser you have selected under Window -> Web Browser:
Page 209
Page 210
You can select ICEfaces Advanced Components and/or ICEfaces components from the Palette. In this case we select a dateTimeEntry component from the ICEfaces Advanced components:
Page 211
Page 212
Page 213
Component attributes can be modified in property view and the changes will automatically be updated in the Design Time Canvas. In this case, we add the renderAsPopup=true attribute and the Design Time Canvas automatically renders a button to launch the calendar popup:
Page 214
With the ICEfaces Advanced Components, we need to add a styleClass to the h:body tag and an h:outputStylesheet after the h:body tag as follows:
Page 215
We can now run the application and see the added component rendered out to the browser:
Page 216
Here is the entire list of topics focused on throughout this tutorial: 1. jobApplication Introduction 2. Step 1 - Add and Update Libraries Step 1a - Remove Old Libraries Step 1b - Add Compat Jars Step 1c - Add JSF 2 Jars 3. Step 2 - Update faces-config.xml Step 2a - Update Header Step 2b - Remove View Handler Step 2c - Change Bean Scopes 4. Step 3 - Update web.xml Step 3a - Remove Old Servlets Step 3b - Add Resources Servlet Step 3c - Modify Faces Servlet Step 3d - Modify Context Parameters 5. Step 4 - Modify Page Markup Step 4a - Modify index.jsp Step 4b - Modify applicantForm.xhtml Step 4c - Modify thankYou.xhtml and noThanks.xhtml Step 4d - Replace ice:outputDeclaration 6. Step 5 - Build and Deploy the Application And available source code downloads: jobApplication 1.8 Source Code jobApplication ICEfaces 2 Source Code
Page 217
Notes The Eclipse workspace of the jobApplication project written in ICEfaces 1.8.
jobApplication Introduction
Download and extract the above source code bundle, and Import -> Existing Project into Workspace the folder into your Eclipse instance. Build and deploy the application to your Tomcat instance, and navigate to the deployed jobApplication. You will see a page similar to the following:
Now let's examine the page code, to get a better idea of what the application is doing. There are three main pages: applicantForm.xhtml** Main page that has a series of internationalized form fields with validation, partialSubmit, a ice:selectInputDate component, etc. noThanks.xhtml** Basic page redirected to when the first name equals "John". thankYou.xhtml** Similar page redirected to when the first name is anything else. The Java code is fairly standard for 1.8, focusing on two beans: bean.backing.ApplicantForm.java** Controller/backing bean for the applicantForm.xhtml page. This controls the submission and some of the rendering toggles on that page. bean.model.Applicant.java** Model object containing variables for the different Applicant fields, like First Name and Travel Percentage. No UI specific functionality. Supporting Beans The ProvinceSupport.java and Province.java classes are used to back the available items in the ice:selectOneMenu found on the main page. Other features: Internationalization The messages_en.properties and JSF-override_en.properties are used to internationalize the various form labels.
Page 218
The primary jars are icefaces.jar and icefaces-compat.jar. The former contains all the ICEfaces 2 code we need, while the latter has compat specific code around ice: components. Step 1c - Add JSF 2 Jars Now we will add JSF 2. There are two jars we need to reference in icefaces/lib/ called jsf-api.jar and jsf-impl.jar. The recommended approach is to create a custom User Library in your Eclipse project, but the jars could also be copied to the jobApplication/WEB-INF/lib/ folder. There will probably be a few errors within the project because of these changes. That's okay, we just need to modify the configuration and pages to be 2 specific to resolve this problem.
With:
Page 219
As you can see we changed the version and schema location to 2. Step 2b - Remove View Handler Now we can remove the old reference to the D2DFaceletViewHandler, as this customization is handled transparently in ICEfaces 2. Remove the following line inside the <application> node:
Step 2c - Change Bean Scopes Next we will modify the old <managed-bean-scope> nodes to conform to those available in ICEfaces 2. Previously ICEfaces 1.8.x used "extended request scope", which meant request was handled differently than it is now. The closest we can get to duplicating this functionality is using the new view scope. Change all 3 beans to have a scope of view:
Will become:
Page 220
</servlet> <servlet-mapping> <servlet-name>Persistent Faces Servlet</servlet-name> <url-pattern>*.iface</url-pattern> <url-pattern>*.jspx</url-pattern> <url-pattern>/xmlhttp/*</url-pattern> <url-pattern>*.faces</url-pattern> <url-pattern>*.jsf</url-pattern> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>Blocking Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Blocking Servlet</servlet-name> <url-pattern>/block/*</url-pattern> </servlet-mapping>
Step 3b - Add Resources Servlet As part of the compatibility requirements of porting a project, a new servlet will be added:
<servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping>
Step 3c - Modify Faces Servlet The purpose of the FacesServlet has changed between 1.8 and ICEfaces 2, and so the declaration and mapping must as well. Replace the old declaration:
Page 221
Step 3d - Modify Context Parameters The last change in web.xml is to change some of the context-param variables. Replace the old variables:
<context-param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</ description> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param>
With a pair of new context-param variables that help ICEfaces 2 act more like 1.8.x in regards to markup and validation:
...
Page 222
response.sendRedirect("applicantForm.jsf"); ...
Step 4b - Modify applicantForm.xhtml As mentioned the header, namespace, and body tags need to be modified to port 1.8 markup to ICEfaces 2. Replace the following tags near the top of the page:
... <f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:ice="http://www.icesoft.com/icefaces/component"> <html> <head> <title>Job Application</title> <ice:outputStyle href="./xmlhttp/css/xp/xp.css" /> </head> <body> ...
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ice="http://www.icesoft.com/icefaces/component"> <h:head> <title>Job Application</title> <ice:outputStyle href="./xmlhttp/css/xp/xp.css" /> </h:head> <h:body>
Remember to replace all closing tags for the above changes. This change was necessary because ICEfaces 2 uses html as the parent container tag of a page, instead of f:view. Also h:head and h:body are used instead of the old plain HTML head and body. Step 4c - Modify thankYou.xhtml and noThanks.xhtml Similary the headers of our other two pages will need to be changed. Replace the old header code in both pages:
Page 223
<h:body>
As before, remember to update the closing tags as well. Step 4d - Replace ice:outputDeclaration The ice:outputDeclaration tag has been deprecated for ICEfaces 2 and should be replaced with the DOCTYPE tag. Remove the following:
Replace it with:
Page 224
and
Page 225
Page 226
Here is the entire list of steps worked through during this tutorial: 1. 2. 3. 4. 5. 6. 7. 8. Make the easyAjaxPush Project Add ICEfaces and ICEpush Create color.xhtml Create MessageBean.java Create ColorBean.java Create TextModel.java Deploy the Application Adding Ajax Push ColorBean Setup PushRenderer.addCurrentSession PushRenderer.render 9. Re-Deploy the Application Tutorial Source Code Downloads
Page 227
3. Create color.xhtml
Create a new page called color.xhtml and paste the code below:
<!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" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Easy Ajax Push - Color</title> </h:head> <h:body> <h:dataTable value="#{messageBean.textList}" var="current"> <h:column> <h:outputText value="#{current.text}" style="color: #{current.color};"/> </h:column> </h:dataTable> <hr width="100%"/> <h:form> <h:panelGrid columns="4"> Choose a Color: <h:commandButton value="Red" action="#{colorBean.chooseColor}" style="color: white; background-color: red;"> <f:setPropertyActionListener target="#{colorBean.color}" value="red"/> </h:commandButton> <h:commandButton value="Blue" action="#{colorBean.chooseColor}" style="color: white; background-color: blue;"> <f:setPropertyActionListener target="#{colorBean.color}" value="blue"/> </h:commandButton> <h:commandButton value="Green" action="#{colorBean.chooseColor}" style="color: white; background-color: green;"> <f:setPropertyActionListener target="#{colorBean.color}" value="green"/> </h:commandButton> </h:panelGrid> </h:form> </h:body> </html>
The purpose of this page is very simple and will display a list of messages and a few buttons to choose a color. When you choose a color an associated message will be added and Ajax Push will send this change to any other client sessions viewing the page (because of how the push group will be setup).
4. Create MessageBean.java
Create a new Java class file called MessageBean in the package org.icefaces.tutorial.easyajaxpush.beans and paste the code below:
Page 228
import javax.faces.bean.ApplicationScoped; import javax.faces.bean.ManagedBean; import org.icefaces.tutorial.easyajaxpush.model.TextModel; @ManagedBean(name="messageBean") @ApplicationScoped public class MessageBean implements Serializable { private static final int MAX_SIZE = 25; private List<TextModel> textList = new ArrayList<TextModel>(0); public MessageBean() { } public List<TextModel> getTextList() { return textList; } public void setTextList(List<TextModel> textList) { this.textList = textList; } public void addToList(String sessionId, String color) { textList.add(makeTextModel(sessionId, color)); if (textList.size() > MAX_SIZE) { textList.clear(); } } private TextModel makeTextModel(String sessionId, String color) { return new TextModel("User with session ID of " + sessionId + " selected color \"" + color + "\".", color); } }
This class is ApplicationScoped (using annotations) and will store a list of TextModel objects. As you've seen above, the list will be displayed in the view (color.xhtml) using an h:dataTable. The actual text of each message is generated in this class based on the HTTP session ID and the selected color. The resulting message looks similar to:
Note that this class will stop the list from growing beyond MAX_SIZE (default 25), but otherwise is fairly basic.
5. Create ColorBean.java
Create a new Java class file called ColorBean in the package org.icefaces.tutorial.easyajaxpush.beans and paste the code below:
Page 229
@ManagedBean(name="colorBean") @ViewScoped public class ColorBean implements Serializable { private static final String PUSH_GROUP = "colorPage"; @ManagedProperty(value="#{messageBean}") private MessageBean messageBean; private String color = "black"; private String sessionId; public ColorBean() { FacesContext fcontext = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession)fcontext.getExternalContext().getSession(false); sessionId = session.getId(); } public void setMessageBean(MessageBean messageBean) { this.messageBean = messageBean; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String chooseColor() { messageBean.addToList(sessionId, color); return null; } }
This class is ViewScoped so one bean instance will be created for each client session. The current HTTP session ID for this client will be tracked. An instance of the MessageBean is injected so that text can be added as needed. Currently no Ajax Push is used in the above code, since we will add that further below.
6. Create TextModel.java
Create a new Java class file called TextModel in the package org.icefaces.tutorial.easyajaxpush.model and paste the code below:
package org.icefaces.tutorial.easyajaxpush.model; import java.io.Serializable; public class TextModel implements Serializable { private String text; private String color; public TextModel() { }
Page 230
public TextModel(String text, String color) { this.text = text; this.color = color; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String toString() { return text; } }
This is a very basic model class that maintains and associates text and color, and is used in the MessageBean to display a list of formatted messages.
public class ColorBean implements Serializable { ... private static final String PUSH_GROUP = "colorPage"; ...
Page 231
8b. PushRenderer.addCurrentSession The next step is to add our current client session to a push group, the name of which is based on the PUSH_GROUP variable added above. Then when Ajax Push requests are sent or received for this push group ICEpush will know to update the page. Add the following at the top of the constructor (around line 24):
PushRenderer.addCurrentSession(PUSH_GROUP);
public ColorBean() { PushRenderer.addCurrentSession(PUSH_GROUP); FacesContext fcontext = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession)fcontext.getExternalContext().getSession(false); sessionId = session.getId(); }
8c. PushRenderer.render Now when a color button is clicked and the message is added to the list an Ajax Push notification should be sent to any other client sessions in the push group "colorPage" (from our variable PUSH_GROUP). To do this add the following line of code to the ColorBean.java action method chooseColor, after the addToList call before the return (around line 46):
PushRenderer.render(PUSH_GROUP);
Now after a message is added to the list we request an ICEpush render (aka use Ajax Push) via the PushRenderer.
Page 232
In future projects that you wish to use ICEpush in, the core two step process explained in detail above of PushRenderer.addCurrentSession and PushRenderer.render is a simple and elegant way to tap into the power and features of Ajax Push!
Notes Basic example project demonstrating how to add Ajax Push to an ICEfaces 2 application.
Page 233
Steps in this tutorial: 1. 2. 3. 4. 5. 6. 7. Make the singleSubmit Project Add ICEfaces Create form.xhtml Create PersonBean.java Deploy the Application Add Single Submit Re-Deploy the Application
2. Add ICEfaces
Add the icefaces.jar to your project from the ICEfaces 2 bundle. This can be added to the project through a custom User Library or by putting it into singleSubmit/WEB-INF/lib/. The approach doesn't matter as long as the jar is included in the deployed war file.
3. Create form.xhtml
Create a new page called form.xhtml and paste the code below. Currently no Single Submit is used, but will be added below in Step 6.
Page 234
<!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" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Single Submit - Form</title> </h:head> <h:body> <h:form> <h:panelGrid columns="3"> <h:outputLabel for="name" value="Name:"/> <h:inputText id="name" value="#{personBean.name}" required="true" maxlength="50"/> <h:message for="name"/> <h:outputLabel for="age" value="Age:"/> <h:inputText id="age" value="#{personBean.age}" required="true" size="2" maxlength="2"> <f:validateLongRange minimum="1" maximum="99"/> </h:inputText> <h:message for="age"/> <h:outputLabel for="gender" value="Gender:"/> <h:selectOneMenu id="gender" value="#{personBean.gender}" required="true"> <f:selectItem noSelectionOption="true" itemValue="" itemLabel="--Select--"/> <f:selectItem itemValue="Male"/> <f:selectItem itemValue="Female"/> </h:selectOneMenu> <h:message for="gender"/> <h:outputLabel for="favorite" value="Favorite Food:"/> <h:inputText id="favorite" value="#{personBean.favorite}" maxlength="225"/> <h:message for="favorite"/> </h:panelGrid> <h:commandButton value="Submit" actionListener="#{personBean.submitButton}"/> </h:form> <br/> <h:panelGrid columns="2" border="1"> <f:facet name="header"> Person Information </f:facet> <h:outputLabel for="nameOut" value="Name:"/> <h:outputText id="nameOut" value="#{personBean.name}"/> <h:outputLabel for="ageOut" value="Age:"/> <h:outputText id="ageOut" value="#{personBean.age}"/> <h:outputLabel for="genderOut" value="Gender:"/> <h:outputText id="genderOut" value="#{personBean.gender}"/> <h:outputLabel for="favoriteOut" value="Favorite:"/> <h:outputText id="favoriteOut" value="#{personBean.favorite}"/> </h:panelGrid> </h:body> </html>
Page 235
Although slightly verbose, the form.xhtml page is a standard JSF form with a table for displaying what the user entered into each field. A variety of input types and validation are used to help demonstrate Single Submit. The table allows a user to enter Name, Age, Gender, and Favorite Food, and then submit those values to the server.
4. Create PersonBean.java
Create a new Java class file called PersonBean in the package org.icefaces.tutorial.singlesubmit.beans and paste the code below:
package org.icefaces.tutorial.singlesubmit.beans; import java.io.Serializable; import java.util.Date; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.event.ActionEvent; @ManagedBean(name="personBean") @ViewScoped public class PersonBean implements Serializable { private String name; private int age; private String gender; private String favorite; public PersonBean() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getFavorite() { return favorite; } public void setFavorite(String favorite) { this.favorite = favorite; } public void submitButton(ActionEvent event) { System.out.println("Submit Clicked: " + name + ", " + age + ", " + gender + ", " + favorite); } }
This bean model is a collection of variables to back the fields on our page. The submitButton method will output what was submitted, but otherwise the class is simple.
Page 236
The user experience with this form could be tedious because validation is not performed until they click the "Submit" button. The user will not know what the valid Age range is, if Name is required, and so on, until the entire form is submitted. Adding Single Submit will enrich the form with immediate feedback as a user visits each field.
This will grant us the ability to use Single Submit. To use Single Submit in a page we put the <icecore:singleSubmit> tag inside any form that requires rich submissions. Inside the opening <h:form> tag in form.xhtml, paste the <icecore:singleSubmit/> tag. Ensure the tag is self terminating and not used as a container for the rest of the components in the form:
Page 237
Now all of the fields inside that form (Name, Age, etc.) will be handled with ICEfaces Single Submit. This means when we leave a field (either by clicking out of it or by tabbing through the fields) only that field will be submitted and processed on the server. If a user leaves the Name field without entering a value, the required="true" validation will display a message immediately, instead of the user needing to click the "Submit" button first. This is achieved because each form field acts as if it had a nested <f:ajax> tag with the execute="@this" attribute.
Notes Basic example project demonstrating how Single Submit functions and can be integrated on an ICEfaces 2 page.
Page 238
Here is the entire list of steps worked through during this tutorial: 1. Make the windowScope Project 2. Add ICEfaces 3. Create 3 Beans with Different Scopes Create WindowBean.java Create ViewBean.java Create SessionBean.java 4. Create PageController.java 5. Create Two Pages Create page1.xhtml Create page2.xhtml 6. Deploy and Test the Application Tutorial Source Code Downloads
2. Add ICEfaces
Add the icefaces.jar to your project from the ICEfaces 2 bundle. This can be added to the project through a custom User Library or by putting it into windowScope/WEB-INF/lib/. The approach doesn't matter as long as the jar is included in the deployed war file.
Page 239
package org.icefaces.tutorial.windowscope.beans; import java.io.Serializable; import java.sql.Timestamp; import javax.faces.bean.CustomScoped; import javax.faces.bean.ManagedBean; @ManagedBean(name="windowBean") @CustomScoped(value = "#{window}") public class WindowBean implements Serializable { private Timestamp created; public WindowBean() { created = new Timestamp(System.currentTimeMillis()); } public Timestamp getCreated() { return created; } public void setCreated(Timestamp created) { this.created = created; } }
The custom ICEfaces 2 Window Scope is used by this class. As the scope is custom, the JSF annotation javax.faces.bean.CustomScoped is used, with a value of #{window}. This will declare the bean as Window Scope. 3b. Create ViewBean.java Create a new Java class file called ViewBean in the package org.icefaces.tutorial.windowscope.beans and paste the code below:
package org.icefaces.tutorial.windowscope.beans; import java.io.Serializable; import java.sql.Timestamp; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBean(name="viewBean") @ViewScoped public class ViewBean implements Serializable { private Timestamp created; public ViewBean() {
Page 240
created = new Timestamp(System.currentTimeMillis()); } public Timestamp getCreated() { return created; } public void setCreated(Timestamp created) { this.created = created; } }
3c. Create SessionBean.java Create a new Java class file called SessionBean in the package org.icefaces.tutorial.windowscope.beans and paste the code below:
package org.icefaces.tutorial.windowscope.beans; import java.io.Serializable; import java.sql.Timestamp; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean(name="sessionBean") @SessionScoped public class SessionBean implements Serializable { private Timestamp created; public SessionBean() { created = new Timestamp(System.currentTimeMillis()); } public Timestamp getCreated() { return created; } public void setCreated(Timestamp created) { this.created = created; } }
4. Create PageController.java
Create a new Java class file called PageController in the package org.icefaces.tutorial.windowscope.controller and paste the code below:
package org.icefaces.tutorial.windowscope.controller; import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import javax.faces.event.ActionEvent; @ManagedBean(name="pageController") @SessionScoped public class PageController implements Serializable {
Page 241
public String navigatePage1() { System.out.println("Redirect to Page 1"); return "page1"; } public String navigatePage2() { System.out.println("Redirect to Page 2"); return "page2"; } public String action() { System.out.println("Action Fired"); return null; } public void actionListener(ActionEvent event) { System.out.println("ActionListener Fired"); } }
This is a basic page backing bean that allows our tutorial application to simulate a few common use cases. The class provides two methods for navigation (between our two basic pages, which will be created next). The class also has a basic action and actionListener. By triggering each of these methods we will be able to see how Window Scope responds in comparison to ViewScoped and SessionScoped.
<!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" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Window Scope - Page 1</title> </h:head> <h:body> <h2>Page 1</h2> <h:panelGrid columns="2"> <h:outputLabel for="viewBean" value="View Bean:" style="font-weight: bold;"/> <h:outputText id="viewBean" value="#{viewBean} created #{viewBean.created}"/> <h:outputLabel for="windowBean" value="Window Bean:" style="font-weight: bold;"/> <h:outputText id="windowBean" value="#{windowBean} created #{windowBean.created}"/> <h:outputLabel for="sessionBean" value="Session Bean:" style="font-weight: bold;"/> <h:outputText id="sessionBean" value="#{sessionBean} created #{sessionBean.created}"/> </h:panelGrid> <h:form> <h:panelGrid columns="4">
Page 242
<h:commandButton value="Redirect to Page 2" action="#{pageController.navigatePage2}"/> <h:commandButton value="Refresh Page" action="#{pageController.navigatePage1}"/> <h:commandButton value="Use an Action" action="#{pageController.action}"/> <h:commandButton value="Use an Action Listener" actionListener="#{pageController.actionListener}"/> </h:panelGrid> </h:form> </h:body> </html>
5b. Create page2.xhtml Create a new page called page2.xhtml and paste the code below:
<!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" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Window Scope - Page 2</title> </h:head> <h:body> <h2>Page 2</h2> <h:panelGrid columns="2"> <h:outputLabel for="viewBean" value="View Bean:" style="font-weight: bold;"/> <h:outputText id="viewBean" value="#{viewBean} created #{viewBean.created}"/> <h:outputLabel for="windowBean" value="Window Bean:" style="font-weight: bold;"/> <h:outputText id="windowBean" value="#{windowBean} created #{windowBean.created}"/> <h:outputLabel for="sessionBean" value="Session Bean:" style="font-weight: bold;"/> <h:outputText id="sessionBean" value="#{sessionBean} created #{sessionBean.created}"/> </h:panelGrid> <h:form> <h:panelGrid columns="4"> <h:commandButton value="Redirect to Page 1" action="#{pageController.navigatePage1}"/> <h:commandButton value="Refresh Page" action="#{pageController.navigatePage2}"/> <h:commandButton value="Use an Action" action="#{pageController.action}"/> <h:commandButton value="Use an Action Listener" actionListener="#{pageController.actionListener}"/> </h:panelGrid> </h:form> </h:body> </html>
6. Deploy and Test the Application Now that the application is setup we can build and deploy it and begin testing. There are several use cases that demonstrate the difference between the custom Window Scope and the standard JSF 2 scopes. Open a web browser and try the following: Click "Redirect to Page 1". Notice the ViewScoped bean is re-created, but Window and Session scope maintain their state.
Page 243
Click "Refresh Page". Notice the ViewScoped bean is re-created, but Window and Session scope maintain their state. Manually refresh or reload the web browser. A similar outcome as the "Refresh Page" button occurs. Click "Use an Action" and "Use an Action Listener". All beans maintain their state through the processing of those buttons. Open a second tab or window in the web browser. Notice new ViewScope and Window Scope beans are created, but the Session scope bean is still in scope. As you can see, Window Scope lives longer than ViewScoped, but not quite as long as SessionScoped. Therefore this custom scope is a perfect candidate for page level backing beans. Using Window Scope instead of ViewScoped can help with user friendliness (as values aren't reset as often) without the memory footprint and overhead of SessionScoped.
Notes Basic example project demonstrating how to use the custom ICEfaces 2 Window Scope.
Page 244
Auto-Complete Calendar Chart Columns Connection Status Data Table Drag & Drop Effects Menu Bar Panel Series Popup Progress Bar Tree
Page 245
Auto-Complete
This page last changed on Nov 16, 2010 by brad.kroeger.
This tutorial will discuss the following topic related to the use of the auto-complete/selectInputText component: Adding the Component Create the Backing Beans Create the Dictionary Tutorial Source Code Download
Page 246
This will display a drop-down list of cities that match the text input. The 'rows' attribute defines how many results will be returned when text is entered. The 'width' attribute sets the width of the input text box and the drop-down list. The 'valueChangeListener' attribute binds to a backing bean method that determines the associated list when a value is changed. Nested in the ice:selectInputText component tag is an f:selectItems JSF tag. The 'value' binding in this tag provides the list of available options. The screen shot below shows the component in action:
Page 247
The following code sample shows an implementation with a list of arbitrarily complex child components:
<ice:selectInputText rows="6" width="300" listVar="city" valueChangeListener="#{autoCompleteBean.updateList}" listValue="#{autoCompleteBean.list}"> <f:facet name="selectInputText"> <ice:panelGrid columns="3" style="margin-bottom:-20px;" columnClasses="cityCol,stateCol,zipCol"> <ice:outputText value="#{city.city}"/> <ice:outputText value="#{city.state}"/> <ice:outputText value="#{city.zip}"/> </ice:panelGrid> </f:facet> </ice:selectInputText>
This will display values similar to the first way but adds more information to the drop down menu, such as state and zip, in addition to the city. The screen shot below shows this method in action:
Page 248
<java version="1.6.0_21" class="java.beans.XMLDecoder"> <object class="java.util.ArrayList"> <void method="add"> <object class="com.icesoft.icefaces.tutorial.component.autocomplete.City"> <void property="areaCode"> <string>631</string> </void> <void property="city"> <string>Holtsville</string> </void> <void property="country"> <string>Suffolk</string> </void> <void property="state"> <string>New York</string> </void> <void property="stateCode"> <string>NY</string> </void> <void property="zip"> <string>00501</string> </void> </object> </void> </object> </java>
In this case, we have encapsulated the options available to the user in a zipped xml file that is deployed with the applications. Options available to the user could also be retrieved from a database.
Page 249
Example autocomplete-tutorial
Page 250
Calendar
This page last changed on Nov 16, 2010 by brad.kroeger.
This tutorial will discuss the following topics related to the use of the ice:selectInputDate component: Creating a Simple Calendar Creating a Popup Calendar Use of Converters and Validators Customizing Calendar's CSS style Tutorial Source Code Download
The selected date is stored in the backing bean 'date1' property (type java.util.Date).
Page 251
In this example, we specify a common North American date presentation of MM/dd/yyyy. We also chose a time zone using the standard java TimeZone class. By default, a java.util.Date is in the GMT/UTC time zone. It is a best practice to keep them in this time zone in your back end. However, when the date is output to the GUI, you may want to apply time zones for different users in different regions of the world. At this point you can format the date appropriately using the 'timeZone' attribute. Often programmers need to place restrictions which dates can be selected. If it's a birthday it must be in the past, if this is a flight it must be in the future, and so on. Validators are used to restrict user input:
<ice:selectInputDate id="date1" value="#{dateSelect.date1}"> <f:convertDateTime pattern="MM/dd/yyyy" timeZone="#{dateSelect.timeZone}"/> <f:validator validatorId="dateRangeValidator" /> </ice:selectInputDate>
The following code is the 'validate' method called from the dateRangeValidator. The 'value' parameter of validate() is a Date object. This method constructs a JSF FacesMessage to be displayed when validation fails:
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { Date myDate = (Date)value; Date today = new Date(); if (myDate.before(today)) { FacesMessage message = new FacesMessage();
Page 252
message.setDetail("Date is in the past"); message.setSummary("Date is in the past"); message.setSeverity(FacesMessage.SEVERITY_ERROR); throw new ValidatorException(message); } }
Example calendar-tutorial
Page 253
Chart
This page last changed on Nov 17, 2010 by brad.kroeger.
This tutorial will discuss the following topics related to the use of the outputChart component: Axis OutputChart Component Pie OutputChart Component Combining with the OutputChart Component Tutorial Source Code Downloads
Page 254
Page 255
Page 256
Page 257
<ice:outputChart id="axisOutputChart" type="bar" chartTitle="Bar Chart" yaxisTitle="Problems" xaxisTitle="Years" xaxisLabels="#{axisChartBean.labels}" labels="#{axisChartBean.legendLabels}" colors="#{axisChartBean.paints}" data="#{axisChartBean.data}" />
The "colors" binding in the bean may return either a java.util.List of java.awt.Color, an array of java.awt.Color or a String array. You can also define the data statically in the jsf page:
The "data" binding in the bean may return either a java.util.List of double array for each pair value, or a double array. You can also define the data statically in the page: Defining the data for an axis type chart in the page for two data sets:
NOTE: the colon(":") is used as the identifier for a new data set. The axis charts use the same underlying data structure which can allow you to change the chart type dynamically:
Page 258
type="#{axisChartBean.type}"
The participation of the outputChart component with the jsf lifecycle allows developers to hook actionListeners to a clientSideImageMap. This feature can be harnessed to provide drill down behavior in all axis charts except area and areastacked. In the demo, when you click on a bar in the chart this will trigger the actionListener to display the value of that bar on the page.
actionListener="#{axisChartBean.imageClicked}"
By default the chart component renders only on the first render cycle and any further render requests will not cause it to be re-rendered unless specified. The rendering of a chart can be an expensive operation if it renders on every render phase. The renderOnSubmit attribute lets the developer decide when to render the chart.
renderOnSubmit="#{axisChartBean.newChart}"
Page 259
Page 260
Pie Charts require a different data model (one dimensional versus the two dimensional model with axis charts) so we have a different bean for the pie charts. The 2D demo shows a 2D Pie Chart with an actionListener that will show a further breakdown of the pie data. This shows the ability of any chart to pass the selected image map data into the bean for further processing. In this case, we have a separate ice:dataTable component showing a breakdown of the yearly sales selected from the 2D Pie Chart. The 3D demo shows how you can dynamically manipulate any chart through the UI. The data, label and paint properties can each be bound to Lists in a backing bean. This feature allows developers to easily manipulate chart properties in the backing bean.
The proper place for chart manipulation using the JCharts API is in the method binding which is bound to the renderOnSubmit attribute, which tells the component whether to render the chart:
Page 261
public boolean newChart(OutputChart component){ try { ............. ............. org.krysalis.jcharts.axisChart.AxisChart axisChart= new org.krysalis.jcharts.axisChart.AxisChart( ......); component.setChart(axisChart); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
Example outputChart-axis
Notes Simple example of how to use the outputChart component. Example of advanced use of ActionListener with the the outputChart component. Example showing the manipulation of chart properties in the backing bean. Example showing the combination of chart types through the use of the JCharts API in the backing bean.
outputChart-pie2D
outputChart-pie3D
outputChart-combined
Page 262
Columns
This page last changed on Nov 16, 2010 by brad.kroeger.
To use the full potential of the columns component, a DataModel for the rows and columns should be specified in a backing bean. Through the DataModels, the developer can specify the information that will be present in the table.
Page 263
Creating a Basic Columns table Creating a Cross Columns table Creating an Updating Columns table Creating a Dynamic Columns table Tutorial Source Code Downloads
String[] index = {"1.", "2.", "3.", "4."}; String[] heading = {"Odd", "Even"}; DataModel rowModel = new ArrayDataModel(index); DataModel columnsModel = new ArrayDataModel(heading);
Once the back end objects have been created, they must be bound to the page level dataTable and columns tags. This is done through the value attribute of the components, as shown below:
<ice:dataTable value="#{backing.rowModel}" var="row"> <ice:column> <ice:outputText value="#{row}"/> </ice:column> <ice:columns value="#{backing.columnsModel}" var="col"> <ice:outputText value="#{col}"/> </ice:columns> </ice:dataTable>
The row DataModel is assigned to the parent dataTable, and the columns DataModel as a value of the ice:columns component. By using a var declaration, we can output the current value of the DataModel as the component is iterated through during the rendering process. The example page uses the above data for the rows and columns, as well as some minor styling. When viewed, it appears similar to:
The DataModels used in the backing bean are simple to create, and the next tutorial will demonstrate calculating page level information from the status of the back end objects.
Page 264
The page level changes are minimal, the main addition is of the color coded value instead of a plain row / column output. This is achieved through a situational outputText, as shown below:
We apply either a red or green CSS font color depending on the status of the supportInfo variable in the backing bean. When we look at the backing bean for this example, the power of linking the columns component to a DataModel becomes apparent. The getSupportInfo method is the main change since the last example, and contains code similar to the following:
public Object getSupportInfo(){ DataModel rowDataModel = getRowModel(); if (rowDataModel.isRowAvailable()) { Object event = getRowModel().getRowData(); DataModel columnsDataModel = getColumnsModel(); if (columnsDataModel.isRowAvailable()) { Object browser = columnsDataModel.getRowData(); return eventSupport.get(event+browser.toString()); } } return null; }
The above method will use the current row and column DataModel to retrieve the support information for that index. Basically we get the current row, ensure it is available (which means the page has loaded it, the component is rendered, etc.), and then do the same for the column. With the combined row / column data, we can check the support info string and return a proper result to the page. So far the examples use static data that does not change once generated. The next tutorial will detail how columns data can be updated from the back end.
Page 265
Similar to the previous examples, an updating columns component uses the same initial approach to the setup of pages and beans. The only difference is we will add a commandButton that will cause variables in the backing bean to change. This is reflected on the page as:
Then the method called from this page level commandButton will need to be added to the backing bean. The goal of the button is to force the data in the columns component to update, and so the next() method will simply increase an integer (which will later be added to the page so the changes can be seen).
As you can see the created method is very simple, basically adding a small random number to the startFrom integer. To allow the user to see the changes when they press the 'Update' button, the startFrom value will be displayed inside a columns component in the page, as shown below:
<ice:columns value="#{backing.columnsModel}" var="headings"> <f:facet name="header"> <h:outputText value="#{headings}" /> </f:facet> <ice:outputText value="#{backing.startFrom}"/> </ice:columns>
The end result is that when the user presses the 'Update' button, the next() method is called, which updates an integer. The changed value is automatically displayed as the contents of a columns component. Using this basic understanding, it's possible for a developer to update statistics from a real time persistence layer, etc. When the above elements have been added, a page similar to the following is created:
As was shown, updating the data contents of a columns component was simple. But a developer may also wish to modify the attributes of the columns on the fly, which will be demonstrated in the next example.
Page 266
component. To demonstrate this, we will look in detail at allowing the user to increase or decrease the number of columns present on the page. The first step is to add a friendly message and input field for the new number of columns. Alternatively a select input component or similar element could be used on the page. In addition, standard JSF validators could be attached to the input, as compared to the rudimentary method of performing back end level checks. An example of the user prompt and input field used is given below:
<ice:outputText value="Enter the number of columns to display (between 1 to 8)"/> <ice:inputText value="#{backing.numberOfColumns}" valueChangeListener="#{backing.change}"/>
Next we will need to fill in the change() method that will be called when the value inside the inputText component is changed. The overall purpose of this method is to ensure a valid number of columns was entered, and if present then update the existing columns component to reflect the new count. This update will be done through modifying the back end DataModel, which will be shown in detail later. For now, an example of what the change() method would look like follows:
public void change(ValueChangeEvent event) { int columnValue = (event.getNewValue() != null ? Integer.parseInt(event.getNewValue().toString()) : 7); if ((columnValue >= 1) && (columnValue <= 8)) { numberOfColumns = columnValue; updateModel(); } }
The bean handles validation instead of the page (again, this is just for simplicity). If the new number of columns is valid, we store it in the session bean and update the DataModel, through the updateModel() method. The contents of this method would be similar to the following:
public void updateModel() { String[] array = new String[numberOfColumns]; for (int i = 0; i < numberOfColumns; i++) { array[i] = String.valueOf(i+1); } columnsModel = new ArrayDataModel(array); }
Basically, we take the newly updated numberOfColumns variable and recreate the columns DataModel, with numbers inserted for each line of header text. When the above steps have been implemented, an application similar in appearance to the following would be produced:
Page 267
You may have noticed a nice benefit of using the columns component this way - the back end is all that needs to be modified, the page level component itself hasn't changed much beyond the first example. This makes the many available changes to the DataModel a useful option to avoid having to update several pages.
Example columns-basic
Notes Simple example of how to setup a basic hard coded columns component. Example showing how to insert custom on the fly data into a columns component. Demonstration of how the size and number of columns can be dynamic modified. This example shows how the data inside a columns component can be updated to reflect user initiated changes.
columns-cross
columns-dynamic
columns-update
Page 268
Connection Status
This page last changed on Nov 16, 2010 by brad.kroeger.
The rest of this tutorial will cover the following topics: Creating a Basic outputConnectionStatus component with label Creating an outputConnectionStatus component with graphic representation How to custom style an outputConnectionStatus component Tutorial Source Code Downloads
<ice:outputConnectionStatus cautionLabel="Caution: Connection in danger." activeLabel="Active: Working." disconnectedLabel="Disconnected." inactiveLabel="Active: Idle." />
Page 269
The creation of the outputConnectionStatus component with graphical representation is also simple. The following example code shows how to display the outputConnectionStatus component in two different themes:
Page 270
<ice:outputConnectionStatus/>
or,
Page 271
You are able to customize the outputConnectionStatus component for different purposes. The example below shows how to customize styling the component so that the component can be use to display a full page overlay of a different translucent colour for each connection state. To customize the styling of the outputConnectionStatus component you only need to create your own css file and choose the background images. In this example, four transparent images of different colors are used as the outputConnectionStatus component's background image. The example css file is as follows:
.iceOutConStat { border:medium none; font-size:2em; height:25px; margin:10px; width:25px; } .iceOutConStatInactive { position: absolute; left: 0px; top: 0px; background-image: url( css-images/connect_idle.gif );
Page 272
background-position: 0px 0px; background-repeat: repeat; width: 100%; height: 100%; } .iceOutConStatActive { position: absolute; left: 0px; top: 0px; background-image: url( css-images/connect_active.gif ); background-position: 0px 0px; background-repeat: repeat; width: 100%; height: 100%; } .iceOutConStatCaution { position: absolute; left: 0px; top: 0px; background-image: url( css-images/connect_caution.gif ); background-position: 0px 0px; background-repeat: repeat; width: 100%; height: 100%; } .iceOutConStatDisconnect { position: absolute; left: 0px; top: 0px ; background-image: url( css-images/connect_disconnected.gif ); background-position: 0px 0px; background-repeat: repeat; width: 100%; height: 100%; }
Specify the css file for the customized outputConnectionStatus with the following line:
The screen shots below shows how the component switches background color as the connection state changes.
Page 273
Page 274
Example connectionStatus-label
Notes Simple example of how to setup a basic outputConnectionStatus component with label. Example showing how to setup an outputConnectionStatus component with XP style theme Example showing how to setup an outputConnectionStatus component with royale style theme
connectionStatus-xp
connectionStatus-royale
Page 275
connectionStatus-customize
Custom styling the outputConnectionStatus component that displays transparent background images in different color when the connection state changes
Page 276
Data Table
This page last changed on Nov 17, 2010 by brad.kroeger.
DataTable functionality can be greatly extended when combined with the commandSortHeader and dataPaginator components. The commandSortHeader component allows column based sorting by clicking on a column header. The dataPaginator component allows the display of only a small portion of a large dataset. The dataPaginator also provides methods for navigating through the dataset while maintaining the same view size. The dataTable renders an HTML table and the underlying DataTable model can define table header, body and footers which map to theader, tbody and tfooter HTML tags.
Page 277
This tutorial will discuss the following topics related to the use of the dataTable component: Creating a Simple Table Adding a Data Paginator Adding a Sortable Header Customizing the Data Table CSS style Tutorial Source Code Downloads
The backing bean in this example contains an array of nineteen InventoryItem objects. Each InventoryItem object represents one row in the rendered dataTable component. Each column in the rendered dataTable component represents an instance variable in the InventoryItem object. The following code shows the inventory array constructor in the Table bean class:
// List of sample inventory data. private InventoryItem[] carInventory = new InventoryItem[]{ new InventoryItem(58285, "Dodge Grand Caravan", " Sto&Go/Keyless", 43500, 21695), ... new InventoryItem(58275, "Dodge Dakota Q.C. SLT", "4x4/Loaded/Alloys", 22500, 27995),
Page 278
The dataTable components' value attribute is assigned to the carInventory Object. This is important as the assigned carInventory Array will be iterated by the variable defined by the var attribute in the dataTable component. The following JSF code shows how the inventory list is assigned to the dataTable:
Columns in a dataTable are defined by the column component. Each column can be bound to an instance variable defined by the var attribute in the dataTable declaration. The following JSF code shows how the first column of the table will be defined:
<!-- Stock number --> <h:column> <f:facet name="header"> <ice:outputText value="Stock #"/> </f:facet> <ice:outputText value="#{item.stock}"/> </h:column>
The column declaration in the above code block has an optional facet declaration. This facet can be named either footer or header and renders the child components in either a theader or tfooter in the rendered HTML table. Any column subcomponents that are not in the named facet will be rendered as row data for the particular column being rendered. In this example we saw how the dataTable component can be used to quickly display data collections. In the next section a dataPaginator component will be added to the dataTable.
Page 279
The first step in adding a dataPaginator control component to a dataTable is to ensure that the dataTable has a unique id attribute assigned to it and that the number of rows in a page view is set via the rows attribute. The dataPaginator components' for attribute is then set to the dataTable id value, this binds the dataPaginator to the dataTable's model. The next step in adding a dataPaginator is to set the attribute paginator to true, this insures that the control links around defined facet controls will be rendered. The following JSF code snippet is of a dataPaginator control where the fastforward and fastrewind facets will move ahead three pages and the maximum number of pages controls shown at the same time is set to four:
<ice:dataPaginator id="dataScroll_3" for="inventoryList" paginator="true" fastStep="3" paginatorMaxPages="4"> ... <ice:dataTable rows="5" id="inventoryList" value="#{inventoryList.carInventory}" var="item">
The next step in adding a dataPaginator is to define the facets which will add control links to their child components. There are are six facets which can be optionally implemented; first, last, previous, next, fastforward and fastrewind. The following is the JSF code needed add a first facet which will allow users to click on an image graphic to move to the first page of the dataTable model:
Page 280
The dataPaginator can also be used for displaying information about the dataTable's model by setting the paginator attribute to false (default value). There are several attributes on the dataPaginator component which allow a developer to bind user defined variable names to the dataTable model: rowsCountVar number of rows in the dataTable view model. displayedRowsCountVar number of rows shown in this dataTable view model. firstRowIndexVar index of first row displayed in this dataTable view model. lastRowIndexVar index of the last row displayed in this dataTable view model. pageCountVar number of pages that make up dataTable view model. pageIndexVar current page number in the dataTable view model.
The following code shows how bound user defined variables can be used to display the dataTable's model state:
<ice:dataPaginator id="dataScroll_2" for="inventoryList" rowsCountVar="rowsCount" displayedRowsCountVar="displayedRowsCount" firstRowIndexVar="firstRowIndex" lastRowIndexVar="lastRowIndex" pageCountVar="pageCount" pageIndexVar="pageIndex"> <ice:outputFormat styleClass="standard" value="{0} cars found, displaying {1} car(s), from {2} to {3}. Page {4} / {5}."> <f:param value="#{rowsCount}"/> <f:param value="#{displayedRowsCount}"/> <f:param value="#{firstRowIndex}"/> <f:param value="#{lastRowIndex}"/> <f:param value="#{pageIndex}"/> <f:param value="#{pageCount}"/> </ice:outputFormat> </ice:dataPaginator>
Page 281
In this section we will add a commandSortHeader component to each inventory column shown in the previous example. The first step in this process is to modify the TableBean backing bean by extending SortableList.java. The SortableList class is provided for convenience but its functionality could just as easily be added to the base class. The first step in adding a commandSortHeader is to add the attributes sortColumn and sortAscending to the dataTable component. These two attributes provide bindings which are manipulated when a commandSortHeader is activated. The sortColumn attribute is updated to the column name of the selected commandSortHeader and the sortAscending attribute's boolean value is toggled if the same commandSortHeader is activated. The following JSF code snippet shows the modified dataTable decoration:
The next step in updating the dataTable for the commandSortHeader component is to add the component to a column header facet. The following code shows the addition of a commandSortHeader component to the first column.
Page 282
The commandSortHeader in this example wraps the output text for the header and adds an arrow which will indicate the ordering applied to the table data. To help avoid typing errors the 'columnName' attribute is bound to the backing bean, the column name is used to specify which column should be sorted. Now that all the JSF code is in place there is still a little work to be done to the backing bean to get the data sorted. As mentioned earlier, the commandSortHeader component only manipulates the dataTable component's sortColumn and sortAscending attributes and as a result it is up to the table's backing bean to use this information to provide sorted data. The following sort method shows how we sort the dataTable data. Remember that sortColumn is bound to the sortColumnName property and that sortAscending is bound to the ascending property in the TableBean class.
protected void sort() { Comparator comparator = new Comparator() { public int compare(Object o1, Object o2) { InventoryItem c1 = (InventoryItem) o1; InventoryItem c2 = (InventoryItem) o2; if (sortColumnName == null) { return 0; } if (sortColumnName.equals(stockColumnName)) { return ascending ? Integer.valueOf(c1.getStock()).compareTo(Integer.valueOf(c2.getStock())) : Integer.valueOf(c2.getStock()).compareTo(Integer.valueOf(c1.getStock())); } else if (sortColumnName.equals(modelColumnName)) { return ascending ? c1.getModel().compareTo(c2.getModel()) : c2.getModel().compareTo(c1.getModel()); } else if (sortColumnName.equals(descriptionColumnName)) { return ascending ? c1.getDescription().compareTo(c2.getDescription()) : c2.getDescription().compareTo(c1.getDescription()); } else if (sortColumnName.equals(odometerColumnName)) { return ascending ? Integer.valueOf(c1.getOdometer()).compareTo(Integer.valueOf(c2.getOdometer())) : Integer.valueOf(c2.getOdometer()).compareTo(Integer.valueOf(c1.getOdometer())); } else if (sortColumnName.equals(priceColumnName)) { return ascending ? Integer.valueOf(c1.getPrice()).compareTo(Integer.valueOf(c2.getPrice())) : Integer.valueOf(c2.getPrice()).compareTo(Integer.valueOf(c1.getPrice())); } else return 0; } }; Arrays.sort(carInventory, comparator); }
When a commandSortHeader is selected the JSF lifecycle is called and the dataTable values will be retrieved from the backing bean. It is during this dataTable retrieval that the data should be sorted but only if the sortColumnName and sortAscending values have changd. The following code snippet shows the getCarInventory() method has been modified to only sort the array data when required:
public InventoryItem[] getCarInventory() { // we only want to sortColumnName if the column or ordering has changed. if (!oldSort.equals(sortColumnName) || oldAscending != ascending){
Page 283
In this tutorial we have shown how to add sortable data columns to a dataTable and when combined with the comandSortHeader the dataTable becomes a very flexible and powerful component. The next and last section of this tutorial will take a look at how to customize the dataTable with CSS.
We will be specifying a custom style for each of the five columns. The following code is the CSS that defines the five column styles.
/* common to all columns*/ .stockColumn, .modelColumn, .desriptionColumn, .odometerColumn, .priceColumn{ border-right: 1px solid #666666; border-bottom: 1px solid #666666; } .stockColumn{ width: 60px; } .modelColumn{ width: 225px; } .desriptionColumn{ width: 150px; } .odometerColumn{ width: 75px; } .priceColumn{ width: 75px;
Page 284
The rowClasses attribute is used the same way as the columnClasses attribute by the dataTable renderer. Instead of specifying a style class for each row we will specify two style classes which will be applied to every odd then even row of the dataTable. The following screen shot shows what the dataTable looks like with both columnClasses and rowClasses decorations.
The dataTable renders an HTML table as the main construct for the rendered dataTable component. The styleClass attribute value will be rendered as a class attribute for the rendered table. If you wish to change the default header styles you must override ICEfaces' predefined CSS names. These names are as follows:
Description Default CSS class name applied to all table header cells. Default CSS style applied anchor tags in a table header cell.
iceTblHeader a
Page 285
Example dataTable-basic
Notes Simple example of how to dispaly data uses a dataTable component. A dataPaginator is added to the dataTable used in dataTablebasic CommandSortHeaders are added to each column in a data table. The row and column classes are altered with CSS.
dataTable-paginator
dataTable-sortable
dataTable-style
Page 286
Page 287
Drag and Drop functionality can be added to any Panel Group. Keep in mind, you can nest any number of ICEfaces and/or HTML tags in a Panel Group. Typically simple images or text are used. Note about Z-Index: for typical purposes, Draggable Panel Groups should not be obscured by other elements on a page. To avoid this, you can set the Z-Index in the component's CSS style to an arbitrarily high number.
Page 288
The rest of this tutorial will discuss the following topics: Creating a Draggable Panel Drag Values and Drop Values Using Drag and Drop Masks Drag and Drop Options Tutorial Source Code Downloads
We can add some style information and fix the size of the panel to avoid scrollbars that are introduced when moving a Panel Group that is 100% of the page width. Setting the Z-Index ensures that the Draggable Panel is not obscured by other block elements. A background colour makes the outline of the Draggable Panel easily identifiable and distinct from other elements. Finally, the addition of cursor:move to the style will change the mouse cursor to indicate that the Panel can be dragged.
<ice:panelGroup style="z-index:10; width:100px; height: 100px; background-color:silver; cursor:move;" draggable="true" dragListener="#{dragDropBean.dropPanelListener}"> <h3>Drag</h3> </ice:panelGroup>
A dragListener will receive each and every DragEvent by default (see Using Drag and Drop Masks). We can record each event's type and append it to a String, using an outputText to display it.
The following code is taken from DragDropBean.java which uses a simple dragListener method to record the event types to a String.
import com.icesoft.faces.component.dragdrop.DragEvent; ... private String dragMessage = ""; public void dragListener(DragEvent dragEvent){ dragMessage += ", " + DragEvent.getEventName(dragEvent.getEventType()); } ... public String getDragMessage () {
Page 289
return dragMessage;
In addition to a Draggable Panel, we can add Drop Target Panels. When a Draggable Panel is dropped on a Drop Target Panel, the "dropped" DragEvent will occur. These Drop Targets will also allow the remaining DragEvents to occur.
<!-- Drop Target 1 --> <ice:panelGroup style="margin:10px; padding:10px; width:300px; height:200px; background-color:orange; color:white;" dropTarget="true"> <em>Drop Target 1</em> </ice:panelGroup> <!-- Drop Target 2 --> <ice:panelGroup style="margin:10px; padding:10px; width:300px; height:200px; background-color:blue; color:white;" dropTarget="true"> <em>Drop Target 2</em> </ice:panelGroup>
<!-- Drop Target 1 --> <ice:panelGroup dropValue="Target 1" style="margin:10px; padding:10px; width:300px; height:200px; background-color:orange; color:white;" dropTarget="true"> <em>Drop Target 1</em> </ice:panelGroup> <!-- Drop Target 2 --> <ice:panelGroup dropValue="Target 2" style="margin:10px; padding:10px; width:300px; height:200px; background-color:blue; color:white;" dropTarget="true"> <em>Drop Target 2</em> </ice:panelGroup>
Page 290
Page 291
The attributes dropMask and dragMask of a Panel Group can be assigned a comma-separated list of values corresponding to the different event masks. hover_start: started to hover over a drop target hover_end: stopped hovering over a drop target dragged: is being dragged (not necessarily moving) dropped: has been dropped on a drop target drag_cancel: has been dropped but not on a drop target
Typically, we will only want to listen for only one or two of these events. In this tutorial we're only interested in "dropped" events.
<!-- Draggable Panel --> <ice:panelGroup style="z-index:10; width:100px; height: 100px; background-color:silver; cursor:move;" draggable="true" dragMask="hover_start, dragging, hover_end, drag_cancel" dragListener="#{dragDrop.dragListener}"> <h3>Drag Me</h3> <ice:outputText value="#{dragDrop.dropValue}" /> </ice:panelGroup>
Page 292
Page 293
ghosting - when a draggable is dragged, a ghost copy is left in the original position. solid - do not make the panel transparent when dragging.
Page 294
Example dragDrop-basic
Notes Basic example of how to setup a Draggable Panel and its backing bean. Drag and Drop values are used to assign a String in a backing bean. Drag and Drop masks are used to prevent unneccessary DragEvent's from firing. Different Drag and Drop options are shown (ghosting, revert, etc.).
dragDrop-values
dragDrop-masks
dragDrop-options
Page 295
Effects
This page last changed on Dec 09, 2010 by brad.kroeger.
Effects can be used in a variety of ways. The majority of the time effects are used to add additional aesthetic appeal such as expanding a panel when a button is clicked, or having a panel fade out after some information has been submitted. Sometimes, however, they are used to emphasize important data.
The rest of this tutorial will discuss the following topics: Creating a Highlight based on direct-to-dom updates Using an Effect with the panelGroup Tutorial Source Code Downloads
In the backing bean you need to set up an Effect parameter and set the effect to fire when the text is retrieved.
public class BasicEffects{ private Highlight effectOutputText = new Highlight("#ffcc99"); private String text; /** Returns the text effect * @return Effect EffectOutputText */ public Effect getEffectOutputText() { return effectOutputText; }
Page 296
/** * Sets the output text effect * @param Effect effectOutputText */ public void setEffectOutputText(Effect effectOutputText) { this.effectOutputText = (Highlight) effectOutputText; } public String getText() { effectOutputText = new Highlight("#FFCC99"); effectOutputText.setFired(false); return text; } ... }
The following screenshot shows what the page looks like when the effect is fired.
Set the action attribute of your commandButton to the backing bean value.
<ice:panelGrid columns="2"> <ice:panelGroup> <ice:outputText value="Click to reveal ICEfaces info" /> <ice:commandButton value="Reveal" action="#{customEffects.fireEffect}"/> </ice:panelGroup> <ice:panelGroup styleClass="blindDownPanel" effect="#{customEffects.panelEffect}" visible="false"> <ice:outputText value="ICEfaces"/><br/><br/> <ice:outputText value="ICEfaces is more than a rich component library..."/> </ice:panelGroup> </ice:panelGrid>
Page 297
public class CustomEffects { private Effect panelEffect; /** Creates a new instance of CustomEffects */ public CustomEffects() { } public Effect getPanelEffect() { return panelEffect; } public void setPanelEffect(Effect panelEffect) { this.panelEffect = panelEffect; } public String fireEffect(){ panelEffect = new BlindDown(); return null; } }
The following screenshots show what the page looks like before clicking reveal and after.
Page 298
Example effects-basic
Notes Simple example of how to setup effects component and backing bean. Demonstration of how effects component can be used with panels.
effects-custom
Page 299
Menu Bar
This page last changed on Nov 17, 2010 by brad.kroeger.
The rest of this tutorial will discuss the following topics: How to Use the Menu Bar Component - Static Hierarchy Definition - Dynamic Hierarchy Definition How to Style the Menu Bar Component Tutorial Source Code Downloads
Page 300
action: MethodBinding representing the application action to invoke when this component is activated by the user. The expression must evaluate to either a String or a public method that takes no parameters, and returns a String (the logical outcome) which is passed to the NavigationHandler for this application. actionListener: MethodBinding representing an action listener method that will be notified when this component is activated by the user. The expression must evaluate to a public method that takes an ActionEvent parameter, with a return type of void. icon: Location of the icon image to be used by the menuItem. id: The component identifier for this component. This value must be unique within the closest parent component that is a naming container. link: For use in navigation, link to another page/site. value: The current value of this component. The menuItems component is similar to the menuItem component, the major difference being that menuItems is used if you want to supply a dynamic hierarchy for the menuBar. The following is a list of available attributes that can be used for this component: action: MethodBinding representing the application action to invoke when this component is activated by the user. The expression must evaluate to either a String or a public method that takes no parameters, and returns a String (the logical outcome) which is passed to the NavigationHandler for this application. actionListener: MethodBinding representing an action listener method that will be notified when this component is activated by the user. The expression must evaluate to a public method that takes an ActionEvent parameter, with a return type of void. id: The component identifier for this component. This value must be unique within the closest parent component that is a naming container. immediate: Flag indicating that this component's value must be converted and validated immediately (that is, during Apply Request Values phase), rather than waiting until Process Validations phase. rendered: Flag indicating whether or not this component should be rendered (during Render Response Phase), or processed on any subsequent form submit. value: The current value of this component. The last component that can be used with the menuBar is the menuItemSeparator component. This component inserts a line similar to the <hr/> html tag. The screen shot below demonstrates how it is displayed:
Page 301
For the example we have developed a basic menu bar with three top-level menu headers. The top-level menu headers consist of File, Edit, and View. The File sub-menu has the most detail, with icons defined for some headings. It also has another sub-menu defined in the Recent heading, that shows the ability of the component to have a sub-menu hierarchy defined. The following is the code for the basic menuBar component:
<ice:menuBar orientation="#{menuBar.orientation}"> <ice:menuItem value="File" id="file"> <ice:menuItem id="open" value="Open" icon="images/open.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Open"/> </ice:menuItem> <ice:menuItem id="close" value="Close" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Close"/> </ice:menuItem> <ice:menuItemSeparator/> <ice:menuItem id="recent" value="Recent" icon="images/recent.gif" actionListener="#{menuBar.listener}"> <ice:menuItem id="photo1" value="Photo 1" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Photo 1"/> </ice:menuItem> <ice:menuItem id="file2" value="File 2" actionListener="#{menuBar.listener}"> <ice:menuItem id="para1" value="Para 1" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Para 1"/> </ice:menuItem> <ice:menuItem id="para2" value="Para 2" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Para 2"/> </ice:menuItem> <ice:menuItem id="para3" value="Para 3" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Para 3"/> </ice:menuItem> <f:param name="myParam" value="File 2"/> </ice:menuItem> <ice:menuItem id="photo3" value="Photo 3" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Photo 3"/> </ice:menuItem> <ice:menuItem id="file4" value="File 4" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="File 4"/> </ice:menuItem> <f:param name="myParam" value="Recent"/> </ice:menuItem> <ice:menuItem id="save" value="Save" icon="images/save.gif"
Page 302
actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Save"/> </ice:menuItem> <ice:menuItem id="print" value="Print" icon="images/print.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Print"/> </ice:menuItem> </ice:menuItem> <ice:menuItem id="edit" value="Edit"> <ice:menuItem id="cut" value="Cut" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Cut"/> </ice:menuItem> <ice:menuItem id="copy" value="Copy" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Copy"/> </ice:menuItem> <ice:menuItem id="paste" value="Paste" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Paste"/> </ice:menuItem> </ice:menuItem> <ice:menuItem id="view" value="View"> <ice:menuItem id="zoomin" value="Zoom In" icon="images/zoomin.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Zoom In"/> </ice:menuItem> <ice:menuItem id="zoomout" value="Zoom Out" icon="images/zoomout.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Zoom Out"/> </ice:menuItem> <ice:menuItem id="fitinwin" value="Fit In Window" icon="images/fitinwindow.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Fit In Window"/> </ice:menuItem> <ice:menuItem id="actualsize" value="Actual Size" icon="images/actualsize.gif" actionListener="#{menuBar.listener}"> <f:param name="myParam" value="Actual Size"/> </ice:menuItem> </ice:menuItem> </ice:menuBar>
Page 303
The backing bean provides (some variation of) the following infrastructure. Actions and ActionListeners are omitted for brevity:
private List menuModel; public List getMenuModel() { return menuModel; } public MenuBean() { menuModel = new ArrayList(); MenuItem topLevel1 = new MenuItem(); topLevel1.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); topLevel1.setValue("topLevel1"); MenuItem topLevel2 = new MenuItem(); topLevel2.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); topLevel2.setValue("topLevel2"); MenuItem topLevel3 = new MenuItem(); topLevel3.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); topLevel3.setValue("topLevel3"); menuModel.add(topLevel1); menuModel.add(topLevel2); menuModel.add(topLevel3); MenuItem sub1_1 = new MenuItem(); sub1_1.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_1.setValue("sub1_1"); MenuItem sub1_2 = new MenuItem(); sub1_2.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_2.setValue("sub1_2"); MenuItem sub1_3 = new MenuItem(); sub1_3.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_3.setValue("sub1_3"); topLevel1.getChildren().add(sub1_1); topLevel1.getChildren().add(sub1_2); topLevel1.getChildren().add(sub1_3); MenuItem sub1_1_1 = new MenuItem(); sub1_1_1.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_1_1.setValue("sub1_1_1"); MenuItem sub1_1_2 = new MenuItem(); sub1_1_2.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_1_2.setValue("sub1_1_2"); MenuItem sub1_1_3 = new MenuItem(); sub1_1_3.setIcon("xmlhttp/css/xp/css-images/menuitem.gif"); sub1_1_3.setValue("sub1_1_3"); sub1_1.getChildren().add(sub1_1_1); sub1_1.getChildren().add(sub1_1_2); sub1_1.getChildren().add(sub1_1_3); }
Page 304
The following is a screen shot of the menuBar component after the style class has been altered:
The styling of the component is done through a CSS file. The following is an example of the CSS code used:
.iceMnuBar { padding: 0px; white-space: nowrap; } .iceMnuBarItem, .myHomeMenuItem { float: left; padding: 0px; white-space: nowrap; } .iceMnuBarItem a, .myHomeMenuItem a { background:url("../images/blue004.jpg"); height: auto; padding-left: 10px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; color: #FFF; margin: 0px; width: 100px; float: left;
Page 305
display: block; text-decoration: none; font-weight:bold; white-space :normal ; } .myHomeMenuItem a { width: 40px; } .iceMnuBarItem a:hover, myHomeMenuItem a:hover{ background: #006699; color: #FFFFFF; } .iceMnuBarItem hr { border: none 0; border-top: 1px solid #999999; width: 100%; height: 1px; margin-top: 3px; padding: 0px; text-align: left; } .iceMnuBarSubMenu { position: absolute; background-color: #0099CC; width: 138px; border-top:1px solid #FFF; padding: 1px; height: auto; display: block; } .iceMnuItm { padding: 0px; display: block; height: auto; } .iceMnuItm a { color: #FFFFFF; display: block; text-decoration: none; padding-left: 3px; padding-right: 3px; padding-top: 3px; padding-bottom: 3px; font-weight : bold; } .iceMnuItm a:hover { background-color:#0066CC; } .iceMnuItm a:hover .iceOutTxt{ color: #FFFFFF; } .iceMnuItmLabel, .iceMnuBarItemLabel { font-family: Arial, Helvetica, sans-serif; padding-top: 4px; font-size: 1.0em; display: inline; }
Page 306
.iceMnuBarItemImage { width:0px; } .iceMnuItmImage, .iceMnuBarItemImage { display:inline; vertical-align: top; } .iceMnuBarSubMenuInd { display:inline; float:right; padding-top: 3px; padding-right: 1px; }
The default style class names are used except for the myHomeMenuItem class. This class is used to get the My Home heading text to wrap, due to its smaller size it needs a smaller width to get the desired text wrapping effect. The following is a description of the default text style classes and which part of the menuBar component they represent: iceMnuBar: The base name for the entire menuBar component. iceMnuBarItem: Represents the top-level heading. iceMnuBarItemLabel: Represents the text label in the heading. iceMnuBarItemImage: Represents the image for the heading. iceMnuBarSubMenu: Represents the sub-menu for the menuBar component. iceMnuBarSubMenuInd: Represents the indicator for the sub-menu. Displays an arrow when the sub-menu is a header for another menu.
When the menu bar's orientation is set to vertical the style classes change a bit. The following is a list of style classes used when the menuBar components orientation is set to vertical: iceMnuBarVrt iceMnuBarVrtItem iceMnuBarVrtItemLabel iceMnuBarVrtItemImage iceMnuBarVrtSubMenu iceMnuBarVrtSubMenuInd
If the menuBar component is disabled and orientation is set to horizontal(default), the style classes are: iceMnuBar-dis iceMnuBarItem-dis iceMnuBarItemLabel-dis iceMnuBarItemImage-dis iceMnuBarSubMenu-dis iceMnuBarSubMenuInd-dis
If the menuBar component is disabled and the orientation is set to vertical, the style classes are: iceMnuBarVrt-dis iceMnuBarVrtItem-dis iceMnuBarVrtItemLabel-dis iceMnuBarVrtItemImage-dis iceMnuBarVrtSubMenu-dis iceMnuBarVrtSubMenuInd-dis
Page 307
Example menuBar-basic
Notes Basic example demonstrating how to use the menuBar component. Basic example demonstrating how to style the menuBar component through CSS.
menuBar-styled
Page 308
Panel Series
This page last changed on Nov 04, 2011 by akhalil.
The panelSeries component can be bound to an array, an instance of java.util.List, an instance of java.sql.ResultSet, an instance of java.servlet.jsp.jstl.sql.Result, or an instance of javax.faces.model.DataModel. In the tag, specify the value attribute of the component and the var attribute to represent the name of the current item as the component iterates through each item in the value binding.
The rest of this tutorial will discuss the following topics: Creating a Basic Series Panel Creating a Series Panel with Customized Objects Tutorial Source Code Downloads
Page 309
The following screenshot shows what the page looks like once the beans are properly setup.
<ice:panelSeries var="customObject" value="#{customPanelSeriesBean.customObjectList}"> <ice:panelGrid columns="2"> <ice:outputText value="Name:" /> <ice:outputText value="#{customObject.name}" /> <ice:outputText value="Age:" /> <ice:outputText value="#{customObject.age}" /> <ice:outputText value="Email Address:" /> <ice:outputText value="#{customObject.emailAddress}" /> <ice:outputText value="Phone Number:" /> <ice:outputText value="#{customObject.phoneNumber}" /> <ice:outputText value="Anonymous Message?" /> <ice:selectBooleanCheckbox value="#{customObject.anonymous}"/> ...... </ice:panelGrid> <br/> </ice:panelSeries>
The following screenshot shows what the page looks like once the beans are properly setup.
Page 310
Example panelSeries-basic
Notes Simple example of how to setup a basic panelSeries component and backing bean. Demonstration of how the panelSeries component can be used with other components and custom objects.
panelSeries-custom
Page 311
Popup
This page last changed on Nov 18, 2010 by brad.kroeger.
Page 312
The panelPopup does not require any beans specific to the application. For example, static text can be used inside the body using only page level tools, which removes the complexity of bean setup. In the case of each example in this tutorial, a backing bean will only be used for the advanced demo.
Page 313
The rest of this tutorial will discuss the following topics: Creating a Draggable Panel Popup Creating a Modal Panel Popup Customizing Panel Popup Styles Advanced Draggable Panel Popup Tutorial Source Code Downloads
<f:facet name="header"> <!-- header content would go here --> </f:facet> <f:facet name="body"> <!-- body content would go here --> </f:facet>
In this tutorial both facets contain outputText components, although it is possible to place other extended or custom components inside the popup panel. It is recommended that anything inside the facet be wrapped in either an ice:panelGroup or ice:panelGrid. The facets would then be placed inside the ice:panelPopup tag. Because this section is demonstrating a draggable panelPopup, the draggable="true" attribute is added to the tag. This results in the following code:
The example page has added content inside the facets, as well as some minor styling to each component. Once completed, the draggable example looks similar to:
Page 314
The creation of this draggable dialog was very simple, as draggablePanelPopup.jspx shows. The modal panelPopup is implemented in a similar manner to the draggable version, as the next tutorial will demonstrate.
<ice:panelPopup modal="true"/>
Using the draggable page as a basis, the new page modalPanelPopup.jspx can be created easily. When viewed, the page appears similar to:
Page 315
Notice the blocking mechanism of the modal dialog, and also how the panelPopup cannot be dragged.
Page 316
The appearance of these 2 examples is rather generic and may not suit your application. The next section will demonstrate how to customize the CSS for panelPopup.
Next the default panel styles should be copied into the override sheet. To find the default styles, look inside the CSS normally linked to, which is ./xmlhttp/css/rime/rime.css. Copy all popup related styles into a new sheet, in our case override.css. After this is done, you can begin customizing the styles. This demonstration changes the colors and borders of the header and body facet, as well as the panelPopup itself. The result is similar to the following:
After this is done, you can begin customizing the styles. This demonstration changes the colors and borders of the progress bar, to give it a brighter sunken appearance. The result is similar to the following:
Page 317
To achieve the color change of the panelPopup header, the following CSS changes were used:
As was mentioned earlier, complex components can be used inside of the panelPopup, and backing beans can be added to increase the functionality. The next tutorial will demonstrate both of these functions.
Page 318
<ice:selectBooleanCheckbox value="true"/> <ice:outputLink value=""> <ice:outputText value="Output Link"/> </ice:outputLink> <ice:selectInputDate/> </f:facet>
This would result in the dialog body containing an inputText, checkbox, link, and calendar. This demonstrates the flexibility of popup panel contents. With this set of components inside the panelPopup, the page appears similar to:
This section also demonstrates how to use backing beans with this component. As you can see from the screenshot, a close button (appears as X) has been added. This close button acts as a toggle to change the visibility of the panelPopup. The bean PopupBean.java is used, and is bound in faces-config in the standard way (shown below for reference):
Page 319
Once this is done, a visible attribute is added to the panelPopup, which uses the backing bean value, as shown below.
The next step is to add 2 buttons to the page; one for opening a popup and one for closing the popup. These would be similar to the following:
The backing bean methods for these buttons and visibility attribute must now be written. The code for this is simple; the open method would toggle the visibility to true, and the close method would set it to false. For completeness, this is demonstrated below.
public void closePopup() { visible = false; } public void openPopup() { visible = true; }
When these bindings and methods are complete, the page will allow opening and closing of the popup dialog, as can be seen in advancedPanelPopup.jspx. As you can see, it is trivial to add complex components and dynamic functionality to a popup panel.
Example panelPopup-draggable
Notes Simple example of how to setup a basic draggable panelPopup component. Example showing the modal type of panelPopup and the difference between a draggable dialog.
panelPopup-modal
Page 320
panelPopup-style
Demonstration of how easily and fully a panelPopup can be styled with custom CSS. This example shows how complex components can be used, and how to tie a backing bean to the panelPopup.
panelPopup-advanced
Page 321
Progress Bar
This page last changed on Dec 09, 2010 by brad.kroeger.
The progress bar requires the management of the completed percentage at a backing bean level. How the percentage is updated depends on the developer's application. In some cases it is inside a separate thread, in others it is set from a loop in the business logic. In the case of this tutorial, each demo will use a threaded backing bean to track the percentage and any other attributes of the progress bar.
The rest of this tutorial will discuss the following topics: Setting Progress Bar Modes Customizing Progress Bar Labels Customizing Progress Bar Styles Creating Multiple Progress Bars Tutorial Source Code Downloads
Page 322
The determinate or indeterminate mode is reflected in the progress bar component's attribute as shown below.
The percent value is managed in the backing bean by a thread. The thread will slowly increase the percent value, and can be stopped and restarted based on the user's actions. With the mode selector, progress bar, and controls in place, this example looks similar to:
The creation of this selectable progress bar was very simple, as the modeOutputProgress.jspx page shows. In the next tutorial the ability to customize in-progress and completed labels will be demonstrated.
Page 323
attribute label. When the progress bar is finished, the completed label will be displayed until further action is undertaken on the progress bar. This label is set through the labelComplete component attribute. Finally, the position of the labels (both working and completed) can be changed through the labelPosition component attribute, to any of the 8 available positions. The positions are listed below, with embed being the default.
In the case of this tutorial, a combination of inputText and selectOneMenu components are used to allow the user to choose their own labels and position. The above attributes are then applied to the progress bar in a way similar to the following:
The backing for this application is similar to the mode tutorial above, as we use a threaded approach to simulate a long running process. By default, the completed page with label selectors and example progress bar looks similar to:
Notice that by default, a simple percentage label will be displayed, and no completed label is used. The appearance of these two examples is rather generic and may not suit your application. The next section will demonstrate how to customize the CSS for the outputProgress component.
Page 324
Next the default progress bar styles should be copied into the override sheet, and changed as desired. The names of each overriding class are listed below:
After this is done, you can begin customizing the styles. This demonstration changes the colors and borders of the progress bar, to give it a brighter sunken appearance. The result is similar to the following:
For example, to achieve the color change of the outputProgress bar, the following CSS changes were used:
.iceOutProgFill { background-color: #FF0202; background-position: top left; background-repeat: repeat-x; height: 25px; display: block; }
Other CSS changes were done to help display the possibilities, and since all the relevant classes are accessible to the developer the outputProgress style can be completely changed. The next tutorial approaches the progress bar from a different mindset. Instead of using it to display updates on a long running task, the progress bar will be used as a status message. In addition, the next tutorial will look at multiple progress bars on the same page.
Page 325
This is a fairly passive demonstration, with no user input available. As a result, the relevant part of the code is the dataTable, which is similar to:
<ice:dataTable value="#{multiple.progressBarList}" var="progress"> <ice:column> <f:facet name="header"> <ice:outputText value="Server Location"/> </f:facet> <ice:outputText value="#{progress.name}"/> </ice:column> <ice:column> <f:facet name="header"> <ice:outputText value="CPU Load"/> </f:facet> <ice:outputProgress value="#{progress.percent}"/> </ice:column> </ice:dataTable>
As you can see, this is a fairly standard dataTable with two columns. By constantly updating the percentage values of the simulated CPU load, we can demonstrate how a server monitoring suite could implement multiple progress bars. The finished result is similar to the following:
Once the list of progress bars has been created by the backing bean, a thread is started to randomly update the percent value of each simulated server. These updates are then pushed to the page, and give the illusion of actual data changing.
Page 326
Example outputProgress-mode
Notes Allows the switching of determinate and indeterminate mode in a simple progress bar. Example showing the customization of progress bar label text and position. Demonstration of how easily and fully an outputProgress can be styled with custom CSS. This example shows how multiple progress bars can be displayed on the same page.
outputProgress-label
outputProgress-style
outputProgress-multiple
Page 327
Tree
This page last changed on Nov 05, 2011 by akhalil.
The tree displays its data vertically where every node of the tree is represented by a DefaultMutableTreeNode. A node can either be a leaf or branch depending if it has zero or more child nodes. A user can click on the branch expand/contract icon to toggle the visibility of child nodes. The root tree node visibility can be toggled by setting the tree hideRootNode attribute to false. Each DefaultMutableTreeNode wraps an IceUserObject which contains instance variables for common tree node properties such as icon paths, tool tips, display text and expanded state.
The rest of this tutorial will discuss the following topics: Creating a Tree Customising the IceUserObject Responding to Node Selection Customizing a Tree's Display Dynamically Changing a Tree Tutorial Source Code Downloads
Page 328
Creating a Tree
Creating a basic tree component is a pretty standard process comprising of two parts. The first part consists of building a backing bean which will contain the DefaultTreeModel. The second part is to add the tree component to your ICEfaces application. Here is a picture of the tree we will create:
The following code is taken from TreeBean.java which builds a simple DefaultTreeModel, one root node with three child nodes. The TreeBean must expose the DefaultTreeModel instance variable to bind it to the tree components' value attribute.
// create root node with its children expanded DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode(); IceUserObject rootObject = new IceUserObject(rootTreeNode); rootObject.setText("Root Node"); rootObject.setExpanded(true); rootTreeNode.setUserObject(rootObject); // model is accessed by by the ice:tree component via a getter method model = new DefaultTreeModel(rootTreeNode); // add some child nodes for (int i = 0; i <3; i++) { DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode(); IceUserObject branchObject = new IceUserObject(branchNode); branchObject.setText("node-" + i); branchNode.setUserObject(branchObject); rootTreeNode.add(branchNode); }
The TreeBean must be instantiated in faces-config.xml so it can be used in our JSF application. Here is the JSF code that is needed to render the DefaultTreeModel defined in TreeBean:
<ice:tree id="tree"
Page 329
value="#{tree.model}" var="item" hideRootNode="false" hideNavigation="false" imageDir="./xmlhttp/css/xp/css-images/" > <ice:treeNode> <f:facet name="content"> <ice:panelGroup style="display: inline"> <ice:outputText value="#{item.userObject.text}" /> </ice:panelGroup> </f:facet> </ice:treeNode> </ice:tree>
Notice how the tree component has a treeNode child component. This child component is sub-child further with a facet named content. The facet name is self descriptive and allows for any type of JSF component to be added. There is also an icon facet which should be used to hold components related to a tree node icon. The content facet should be used to hold components related to a tree nodes text label. The tree tag is iterative and will apply its child component hierarchy to all of the DefaultMutableTreeNodes found in the DefaultTreeModel. To summarize, the tree component can be created with a simple binding to a backing bean which contains a DefaultTreeModel. You do not have to write any code to make the tree nodes expand and contract.
private String url; public UrlNodeUserObject(DefaultMutableTreeNode wrapper) { super(wrapper); } public String getUrl() { return url; }
Now that every node can have a unique URL we need to update the JSF code in linkTree.xhtml. The following code shows how to add a commandLink to a treeNode which takes advantage of our new UrlNodeUserObject object.
<ice:treeNode> <f:facet name="content"> <ice:panelGroup style="display: inline"> <ice:outputLink value="#{item.userObject.url}" target="_blank"> <ice:outputText value="#{item.userObject.text}" /> </ice:outputLink> </ice:panelGroup> </f:facet> </ice:treeNode>
Customising the IceUserObject is quite simple and when combined with the iterative nature of the tree component, it can be quite powerful. The next section will show how to respond to node selection.
Page 330
public PanelSelectUserObject(DefaultMutableTreeNode wrapper) { super(wrapper); // get a reference to the PanelStackBean from the faces context FacesContext facesContext = FacesContext.getCurrentInstance(); Object panelStackObject = facesContext.getApplication() .createValueBinding("#{panelStack}") .getValue(facesContext); if (panelStackObject instanceof PanelStackBean){ panelStack = (PanelStackBean)panelStackObject; } }
The PanelSelectUserObject needs to be able to respond to a user click and update the internal state of the backing beans. The user clicks are handled by binding a method to the tree nodes action listener. Here is the code needed to respond to a user's click.
The PanelStackBean object is introduced in this code block which is responsible for maintaining the state of selected panel stack in the panelStack component. The full source for this simple class is available with the tree-selection demo source code. Setting up a tree component for user interaction is a relatively simple process which utilizes actionListener mechanisms in the JSF framework. Each tree node's backing bean is responsible for setting a selected panel in the panelStack component. The component nature of JSF allows for easy encapsulation of application logic which makes the application quick to build and debug. The follow is a screen shot of the tree-selection demo.
Page 331
Page 332
The ICEfaces framework comes configured with three distinctly different CSS based themes for all components. The style sheets for these themes, XP, Royale and Rime are available in the resources folder of the ICEfaces bundle. In order apply the XP theme the following include is needed in your xhtml page:
For most ICEfaces components added, the above CSS file include is all that is needed. The tree component requires slightly more configuration to fully apply the theme. First, the tree component requires that an imageDir attribute is set which points to a location where the expand and contract control images can be found. Lastly, the node state icons must be set for each IceUserObject; branch contracted icon, branch expanded icon and finally a leaf icon. This may seem like a lot of work but it allows for a tree that can have multiple variations of branch and leaf icons. The following is an updated tree component declaration which is fully styled:
<ice:tree id="tree" value="#{tree.model}" var="item" hideRootNode="false" hideNavigation="false" imageDir="./xmlhttp/css/xp/css-images/"> <ice:treeNode> <f:facet name="icon"> <ice:panelGroup style="display: inline"> <h:graphicImage value="#{item.userObject.icon}"/> </ice:panelGroup> </f:facet> <f:facet name="content"> <ice:panelGroup style="display: inline"> <ice:commandLink actionListener="#{item.userObject.selectPanelStackPanel}" value="#{item.userObject.text}"/> </ice:panelGroup> </f:facet> </ice:treeNode> </ice:tree>
In summary, the ICEfaces components can easily be styled using CSS and in some cases by specifying image directories as we have done with our tree. In the next example we are going to dynamically change a tree's DefaultTreeModel which will automatically be reflected in the view.
Page 333
This demo will start with the same tree that we used in the tree style demo. We must first add an action listener to the the treeNode commandLink component to listen for user clicks. Next we add a panel which will display the selected node and have add/remove controls when a node is selected. The JSF code for dynamically changing a tree node is as follows:
<ice:panelGroup> <p>Dynamic Tree Node Control:</p> <ice:commandButton actionListener="#{tree.copySelectedNode}" disabled="#{tree.copyDisabled}" value="Copy" /> <ice:commandButton actionListener="#{tree.deleteSelectedNode}" disabled="#{tree.deleteDisabled}" value="Delete" /> <p/> <ice:outputText value="Selected Node: #{tree.selectedNodeObject.text}" escape="false" /> </ice:panelGroup>
The ActionListeners for the add and remove node controls can be added to the TreeBean class. When a node in the tree is clicked an instance variable in TreeBean references the source of the click. The reference to the selected node can them be used to copy or remove the selected node from the DefaultTreeModel when one of the corresponding commandButtons is pressed. Note that the root node is treated as a special case, if it is removed no more nodes can be added to the tree.
public void deleteSelectedNode(ActionEvent event){ if (selectedNodeObject != null && !selectedNode.equals(ROOT_NODE_TEXT)){ selectedNodeObject.deleteNode(event); selectedNodeObject = null; } }
Page 334
Example tree-basic
Notes Simple example of how to setup a basic tree component and backing bean Tree component which has commandLink components as nodes. When a node is clicked a new browser window is launched with the respective URL. Tree component is used to manipulate the selected panel in a panel stack. The XP theme is fully applied to a tree component producing a fully styled tree. A tree components default tree model is manipulated by other Java Beans. This applicaiton shows how the Tree component can be dynamically changed.
tree-links
tree-selection
tree-style
tree-dynamic
Page 335
Page 336
Creator Creation Last Mod Comment (Last Date Date Modifier) Nils Jun 06, 2011Jun 06, 2011 $item.label.getDisplayable Lundquist $webInterfaceContext) | $item.label.getDisplayable $webInterfaceContext)
The all-new ACE FileEntry component introduces in-memory file processing. This feature is designed to provide for antivirus scanning, checksum verification or a scenario where the upload doesn't need to be saved to disk, and doing so immediately is excessive IO. The functionality requires that a listener bean implement FileEntryCallback to handle the incrementally uploaded bytes. Instances of FileEntryCallback must implement:
/* Notification for upload handler when a file begins uploading. * fileInfo - information known about the file, before downloading the contents */ public void begin(FileEntryResults.FileInfo fileInfo); /* We're working with chunks of bytes, as we receive them... */ public void write(byte[] buffer, int offset, int length); public void write(int data); /* Notification for upload handler that the file is finished. */ public void end(FileEntryResults.FileInfo fileInfo);
This example demos in-memory processing to provide an MD5 hash for an uploaded file.
Implementing FileEntryCallback
Creating our handler is the most important step of this tutorial. Everything else is just wiring up the dependant parts.
Page 337
Check fileInfo.getStatus() to determine if the file has pre-failed uploading, due to too many files uploaded, an invalid file extension, or content type. The Class Properties The MessageDigest class is an Apache Commons class for using one-way hash algorithms like MD5 and SHA.
The begin Method The begin method is where your callback should request any resources it will require. The example sets up a MessageDigest object.
public void begin(FileEntryResults.FileInfo fileInfo) { try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { md5NotFound = true; } }
The write Methods These methods will be passed portions of file data. If there is a chance the file will eventually be saved, the byte input should be cached here. This example immediately computes the data as part of our hash.
public void write(byte[] bytes, int offset, int length) { if (!md5NotFound) digest.update(bytes, offset, length); } // Hash a single byte public void write(int i) { if (!md5NotFound) digest.update((byte) i); }
The end Method This method triggers when a file upload is complete, either successfully or with errors. If you want to invalidate a successful upload, perhaps it's over quota, then this method should handle the case. It may massage the result (raising some prompts and accepting something), or possibly fail the upload for good by calling FileInfo.updateStatus(...) with the status "FileEntryStatuses.INVALID". The example below either prints a custom success FileEntryStatus, a custom MD5 error status, or, in other fail cases, lets the failed status passed to end() propagate to the view.
Page 338
// If the file upload was completed properly if (md5NotFound) fileEntryInfo.updateStatus(new EncodingNotFoundUploadStatus(), true, true); if (fileEntryInfo.getStatus().isSuccess()) { fileEntryInfo.updateStatus(new EncodingSuccessStatus(), false); } }
<ace:fileEntry id="fileEntry" callback="#{fileMD5EncodingCallback}" styleClass="ib" /> <h:commandButton styleClass="ib" value="Get MD5 Checksum" /> <div class="messages-holder"><h:messages styleClass="messages" showDetails="true" /></div> <div style="clear:both; height:0px;"> </div>
That concludes this overview of the new in-memory processing feature. If you're interested in further details of how this example works, take a look at the complete source code below; or sign up for ICEfaces training for a complete guide to this example and every feature of ICEfaces!
Name
Size
Creator Creation Last Mod Comment (Last Date Date Modifier) Nils Jun 06, 2011Jun 06, 2011 $item.label.getDisplayable Lundquist $webInterfaceContext) | $item.label.getDisplayable $webInterfaceContext)
Page 339
General Tutorials
This page last changed on Feb 23, 2011 by ken.fyten.
Creating Your First Hibernate-Enabled Application Using ICEfaces with CDI Using ICEfaces with Spring Converters Creating a Composite Component Internationalization in ICEfaces Validators
Page 340
hibernatetutorial.zip
6.30 MB
Creator Creation Last Mod Comment (Last Date Date Modifier) Nils Apr 01, 2011Apr 01, 2011 $item.label.getDisplayable Lundquist $webInterfaceContext) | $item.label.getDisplayable $webInterfaceContext)
Hibernate is the de-facto Java object/relational persistence and query service framework, and the most significant influence on the JPA standard. In other words, Hibernate is a mature, powerful library that lets you efficiently create and manage a DB backend to your application via familiar features of OO languages like: composition, inheritance, polymorphism, collections, etc. Queries can be written in its own SQL extension (HQL), SQL, or an object-oriented Criteria/Example API. This tutorial is meant to teach the fundamental steps to configuration and interfacing with Hibernate/JPA data entities. For this tutorial samples will be drawn from the supplied "Student Registration" demo application. The applications main function is to add, update, and delete dummy objects (students) from the database. Also, as an example of object relationships, the app includes an association between the students and some course objects. The purpose of tutorial is to give a basic idea on how to connect and use Hibernate with a simple set of entities. Our sample defines its entities via vanilla JPA annotations in familiar POJOs, this allows easy porting among JPA implementations; although there're times a Hibernate-specific annotation or option may be more suited. Hibernate configurations in the real world often require more complex mappings and features that go beyond this tutorial. To learn more about advanced features, a good resource is the Hibernate user's guide. Database Connection & Creation Defaults This application is supplied with a configuration to use a HSQL embedded database, therefore the hsqldb.jar file must be present. If you wish to use a different DB, the schema and sample data is created by Hibernate, so it's only necessary to change the connection settings in hibernate.cfg.xml. Notice the schema is generated and new dummy data added during the first connection to your application SessionFactory. That DB is than dropped when the SessionFactory associated with it is closed. This means in the supplied configuration, a server restart or a full application redeploy will reset the database state. Basics to Creating a Hibernate Application Part 1: Create the Java Data Objects Part 2: Define Relational Mappings via Annotations on the Java Objects Part 3: Add a Hibernate Configuration File Part 4: Add the HibernateUtil Helper Class Part 5: Create an Access Class to Manage Data Objects Adding an Object Record to DB Reading Object Records From DB Deleting a Specified Object Record Adding an Association Between Records
Page 341
public class Course { private long courseId; private String courseName; private String description; private Set<Student> students = new HashSet<Student>(); public Course() {} public Course(int courseId, String courseName, String description) ... public public public public public public public public long getCourseId() {return courseId;} void setCourseId(int courseId) {this.courseId = courseId;} String getCourseName() {return courseName;} void setCourseName(String courseName) {this.courseName = courseName;} String getDescription() {return description;} . void setDescription(String description) {this.description = description;} Set getStudents() {return students;} void setStudents(Set students) {this.students = students;}
As you can see, it's a pretty straight forward POJO, aside from having a field for a numeric ID. In the next step, extra information is applied to data classes like Course, concerning how their instances will be mapped to entries in the database.
@Entity
Page 342
@Table(name = "course") public class Course { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="course_id") private long courseId; ... @Column(name="course_name") private String courseName; ... @ManyToMany @JoinTable(name="student_course", //New table name joinColumns=@JoinColumn //My column in the join table (name="course_id",referencedColumnName="course_id"), inverseJoinColumns=@JoinColumn //Associated column in the join table (name="student_id", referencedColumnName="student_id") ) private Set<Student> students = new HashSet<Student>(); ... //By default, constructors and getters/setters are not persisted. public Course(int courseId, String courseName, String description){...} public long getCourseId() {return courseId;} public void setCourseId(int courseId) {this.courseId = courseId;} //...like this method @Transient public String clear() { courseId = 0; courseName = ""; description = ""; return "clear"; } }
@Entity Entity indicates this data class should have persistent instances in the database (i.e mapped to records in a DB table). Entity is followed by Table, used to set attributes of the table being mapped; its presence is optional. Above we use it specify the name of the table. Take note that name isn't used in HQL queries, column names are only used in configuration.
@Id Id is often used alongside GeneratedValue. GV provides a sequence of unique values to be set by Id as the Primary Key of this table. (i.e - A field guaranteed to be unique among the persisted records of this class.)The PK is a fundamental of database theory and is how the DB differentiates two class instances with the same mapped field values. Although most often DB schema use of numeric IDs, JPA has supports identifying records by a unique non-numeric column or a subset of columns.
@Column
Page 343
Column annotation, similar to Table, is optional and exists to supply configuration attributes for the field it is attached to. Any un-annotated fields are persisted as if it they'd been marked with the defaults of the Basic and Column annotations. The options implied by Basic are configurable.
@ManyToMany ManyToMany is the most complicated of the annotations demonstrated here along with the JoinTable/ JoinColumn used. ManyToMany defines relationships where a class field can have references to any number other class instances, and those class instances, in inverse, are referenced by any number of instances of the original class. To define this relationship, above, we are supplying the name of the table that represents this association, the names of the identifying columns as they will be recorded in the association table, and the names of the identifying columns as they appear in the entity tables we're associating. The other side of the ManyToMany doesn't require a JoinTable, at Student for details.
@Transient Transient is is used to denote class members that should not be part of the database record. There are of course many optional attributes and annotations that we're avoiding. The annotations we've covered here are only a fraction of the standard relationships along with a minimum of config for naming.
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.url">jdbc:hsqldb:file:HibernateTutorialDB</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.HSQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property>
Page 344
<!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create</property> <mapping class="com.icesoft.icefaces.tutorial.crud.hibernate.Student"/> <mapping class="com.icesoft.icefaces.tutorial.crud.hibernate.Course"/> </session-factory> </hibernate-configuration>
The session-factory tag denotes a configuration for the Hibernate SessionFactory java object. The first four elements define the DB connection. The dialect property element specifies the particular SQL variant Hibernate generates. The show_sql property outputs all the mapped SQL commands (apart from table generation) to the console window. We also remove caching and restrict the pool size for this demo. The last two tags identify the mapping files of entities in this database. The hibernate.cfg.xml file must be located at the source directory root.
import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml SessionFactory f = new Configuration().configure().buildSessionFactory(); return f; } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
Page 345
public void addStudent(ActionEvent event){ Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Student s = newStudent("John","Smith","123 Fake St."); session.save(s); session.getTransaction().commit(); s.clear(); init(); }
First a new Session is created via HibernateUtil. Using HibernateUtil to provide the SessionFactory ensures that only one Session executes on our data objects at time. If an application required, you could create more Sessions, each one representing a single sequence of SQL work. A Session SQL sequence is an update to the DB mapped tables with the changes, additions and deletions of data objects (saved/"persisted" via executeUpdate(), save(), etc.) that take place between its beginTransaction() and commit() methods. However, until commit() is run successfully no change actually takes place in the database. Session provides several methods to manipulate the DB, in the sample app two are used. Above, addStudent() uses session.save(). This generates for Session an SQL command to insert that data entity instance into the database. Below, the alternative method is used.
private synchronized void init(){ ... Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); //Load all objects from tables List studentResult = session.createQuery("select s.studentId from " + "Student as s").list(); List courseResult = session.createQuery("select c.courseName from " + "Course as c").list(); session.getTransaction().commit(); studentItems.add(new SelectItem("")); ... }
init() creates a new session just like the addStudent() method, difference being that it uses the query-language oriented createQuery() method over an object-model oriented method like save(). CreateQuery() can work with SQL or HQL, and returns a list of data objects; the result of entity records that it found in the database.
Page 346
Session's been used to add an object to the database without needing to write any SQL, as well as writing an SQL statement to load objects. Below the use of named parameters in query language is shown.
public void deleteStudent(ActionEvent event){ if(currentStudent != null){ int id = currentStudent.getStudentId(); Session session = HibernateUtil.getSessionFactory() .getCurrentSession(); session.beginTransaction(); Query q = session.createQuery("delete from Student as s where " + "s.studentId =:id"); q.setInteger("id",id); int rowCount = q.executeUpdate(); session.getTransaction().commit(); System.out.println("Rows affected: " + rowCount); currentStudent.clear(); studentItems.clear(); init(); } }
Everything above is similar to before, although now the objective is deleting a student of a particular ID. To avoid building complex string compositions, or to allow use of pre-prepared queries, queries allow using parameters in variable positions. To denote a named parameter in a query language statement, prefix the name with a colon. Above, a Query object's been created to define the SQL and the parameter is supplied before executing. The use of a parameter above could be easily avoided, but for an example of where compositing a complex query is eased by parameters, examine the Student update function of RegisterManager. Although the same object-model and query-language data access methods above can be applied to perform DB record updates; apart from that there's still a feature of the relational data object design not yet covered. The ManyToMany association we added between Course and Student needs the ability to add new reference pairs.
public void addCourseToStudent(ActionEvent event){ Session session = HibernateUtil.getSessionFactory(). getCurrentSession(); session.beginTransaction(); Student s = (Student)session.load(Student.class, currentStudent.getStudentId()); Course c = (Course)session.load(Course.class, currentCourse.getCourseId()); s.getCourses().add(c); // or .remove for delete session.getTransaction().commit(); }
Most of above is familiar, although there is a difference in the origin of the data objects. They're loaded within the transaction, as opposed to working with our in-memory lists of Student and Course objects, only doing a save of the changes we just made. Referred to as automatic dirty checking, making updates
Page 347
to objects that are looked up by transaction is less efficient, but are easier to write as it doesn't require local instances or explicit info about how the updates should be made. If you've successfully followed this tutorial till now, you should know the basics of: creating a Hibernate configuration creating data objects session & transaction usage manipulating the DB via the Hibernate Session object
Name
Size
hibernatetutorial.zip
6.30 MB
Creator Creation Last Mod Comment (Last Date Date Modifier) Nils Apr 01, 2011Apr 01, 2011 $item.label.getDisplayable Lundquist $webInterfaceContext) | $item.label.getDisplayable $webInterfaceContext)
Page 348
Here is the entire list of steps worked through during this exercise: 1. 2. 3. 4. 5. 6. Download Weld and examples Servers Begin With Weld Examples War deployment Ear deployment Add push
1. Download Weld and examples:To download Weld the source and binaries, as well as documentation is here:- http://seamframework.org/ Weld/WeldDistributionDownloads Weld is also available from the JBoss Maven Repository. Maven 3.0 is a requirement, however, it appears that the samples can be built with a combination of Ant and Maven 2.
2. Servers
Currently, it is easiest to test this all out with jboss-6.0.0.Final, but a good idea is to download whatever version is most recent of jboss application server 6.0. Weld is already built into this server and tested regularly. Weld also supports other containers, including tomcat, Glassfish and Jetty, but be sure to see which containers use jsf2.0.
Examples follow which show a war deployment and an ear deployment to jboss-6.
Page 349
Assuming that jboss-6.0.0.Final is the application server used, exclude the jsf jars as a dependency for icefaces-2.0.0.jar for the profile with id of jboss6 and add the following dependencies:-
<dependency> <groupId>org.icefaces</groupId> <artifactId>icefaces</artifactId> <version>2.0.0</version> <exclusions> <exclusion> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.icepush</groupId> <artifactId>icepush</artifactId> <version>2.0.0</version> </dependency>
If ICEfaces push capability is not a requirement, the entry for the icepush jar can be omitted. One more modification is required. In jsf/numberguess/src/main/webapp/template.xhtml, change the
head
tag to that of
h:head
and the
body
tags to
h:body
. If you have modified the build.properties file in the examples root folder to define the jboss.home property, then you may simply run the build.xml ant script in examples/jsf/numberguess, as the default is for jboss6 and will actually deploy the example after building it. Since numberguess was not designed with ajax (ie: no f:ajax tags), you are getting ajax without any markup at all, just by adding ICEfaces jars to the application. This tutorial does not maximize the benefits of ajax via ICEfaces, but simply adds it to the page. You may notice that the inputText for input of the number you guess is ajax-enabled (once the focus is lost on the input text by tab or enter for example, the number is updated to the backing bean), but the actionListener of the button is not activated. If an
Page 350
<ice:inputText> field is used, then you can trigger an action to do the check and dispose of the button altogether. That information can be reviewed on any ICEfaces example or tutorial. You can add the component jars (ice or ace) to the application by adding them as dependencies to the pom.xml that you already modified above and place the corresponding namespaces to the page.
b. Ear deployment Example
Since jee6 (jboss-6.0.0 application server) includes ebj3.1 and JPA2, this means that an ejb jar can now be included in a war deployment. The ear that is included in the weld examples is a standard ear deployment:- examples/jsf/weld-translator which will require the icefaces and icepush jar loaded at the ear level. It is assumed that icepush will be a requirement in this example. If only the icefaces and any of it's component jars are required, then the war level is fine. In examples/jsf/translator/ear/pom.xml, modify the build target to include the following:-
<build> <finalName>weld-translator</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-ear-plugin</artifactId> <configuration> <modules> <webModule> <groupId>org.jboss.weld.examples.jsf.translator</groupId> <artifactId>weld-jsf-translator-war</artifactId> <contextRoot>/weld-translator</contextRoot> </webModule> <jarModule> <groupId>org.icefaces</groupId> <artifactId>icefaces</artifactId> <bundleDir>lib</bundleDir> </jarModule> <jarModule> <groupId>org.icepush</groupId> <artifactId>icepush</artifactId> <bundleDir>lib</bundleDir> </jarModule> </modules> </configuration> </plugin> </plugins> </build>
Note that you will still need to refer to the repository and state the dependency as well. This entry just determines the packaging for where the jars are to be located when deployed.
6. Add Push.
Since icepush.jar is already included in the numberguess example above, it will be used to show how simple it is to add ICEfaces push capability. No modifications are required to the configuration files (facesconfig.xml or web.xml). If the jar is included in the deployed application, then push is available. Modify the numberguess application to include a StatsModel object, which will include the number of guesses a user (denoted by their sessionId) takes.
package org.jboss.weld.examples.numberguess; import java.io.Serializable; //just holds the value pairs for example of push
Page 351
public class StatsModel implements Serializable { private String text; private int numberOfGuesses; public StatsModel() { } public StatsModel(String text, int guesses) { this.text = text; this.numberOfGuesses = guesses; } public String getText() { return text; } public void setText(String text) { this.text = text; } public int getNumberOfGuesses() { return this.numberOfGuesses; } public void setNumberOfGuesses(int guesses) { this.numberOfGuesses = guesses; } public String toString() { return text+" with guesses ="+this.numberOfGuesses; } }
Create an application-scoped message bean that will track all the entries of StatsModel in a list (once you get 25 records, clear it off and start again since this is only a demo):-
package org.jboss.weld.examples.numberguess; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Named; import javax.enterprise.inject.Produces;
@ApplicationScoped public class MessageBean implements Serializable { private static final int MAX_SIZE = 25; private List<StatsModel> textList = new ArrayList<StatsModel>(0); public MessageBean() { }
Page 352
public void addToList(@Observes StatsModel data){ textList.add(data); if (textList.size() > MAX_SIZE) { textList.clear(); } } }
package org.jboss.weld.examples.numberguess; import java.io.Serializable; import javax.annotation.PostConstruct; import javax.enterprise.context.SessionScoped; import javax.enterprise.inject.Instance; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.inject.Inject; import javax.inject.Named; //need these imports for PUsh import org.icefaces.application.PushRenderer; import javax.servlet.http.HttpSession; import javax.enterprise.event.Event; import javax.enterprise.inject.Any;
@Named @SessionScoped public class Game implements Serializable { /** * */ private static final long serialVersionUID = 991300443278089016L; //add this line for name of push group private static final String PUSH_GROUP = "stats"; private String sessionId; private int number; private int guess; private int smallest;
/* inject an event in to trigger when a StatsModel object can be created and added to the list in MessageBean class */ @Inject @Any Event<StatsModel> statsEvent; @Inject @MaxNumber private int maxNumber; private int biggest;
Page 353
private int remainingGuesses; @Inject @Random Instance<Integer> randomNumber; public Game() { //add some stuff for push and getting sessionID to create StatsModel object to push PushRenderer.addCurrentSession(PUSH_GROUP); FacesContext fc = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession)fc.getExternalContext().getSession(false); sessionId = session.getId(); } public int getNumber() { return number; } public int getGuess() { return guess; } public void setGuess(int guess) { this.guess = guess; } public int getSmallest() { return smallest; } public int getBiggest() { return biggest; } public int getRemainingGuesses() { return remainingGuesses; } public void check() { if (guess > number) { biggest = guess - 1; } else if (guess < number) { smallest = guess + 1; } else if (guess == number) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!")); /*we now have the information to create our StatsModel object so trigger an event to update the list*/ statsEvent.fire(new StatsModel(sessionId, 10-remainingGuesses)); /* trigger the push */ PushRenderer.render(PUSH_GROUP); } remainingGuesses--; } @PostConstruct
Page 354
public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) { if (remainingGuesses <= 0) { FacesMessage message = new FacesMessage("No guesses left!"); context.addMessage(toValidate.getClientId(context), message); ((UIInput) toValidate).setValid(false); return; } int input = (Integer) value; if (input < smallest || input > biggest) { ((UIInput) toValidate).setValid(false); FacesMessage message = new FacesMessage("Invalid guess"); context.addMessage(toValidate.getClientId(context), message); } } /** remove this session from the render group when the bean is * no longer around */ @PreDestroy public void destroy(){ PushRenderer.removeCurrentSession(PUSH_GROUP); } }
A few things to note are the @Event and @Observes annotations that Weld provides. Also check out the @Produces on the @ApplicationScoped MessageBean class. Weld documentation is included in the bundled distribution that the samples came in, if you don't know what these annotations represent. When given a choice with the same annotation in jsf or Weld, choose the Weld (like @ApplicationScoped) import. Will make life easier.
Page 355
About Spring
Spring provides "a lightweight container providing centralized, automated configuration and wiring of your application objects." In addition, Spring provides a widely used abstraction layer for JDBC and transaction management. The tutorials below were developed using ICEfaces 2.0, JSF 2.0, and Spring 3.0.5: Spring Web Flow 2 Spring Security
Page 356
booking289 kB icefaces.zip
Technologies/Libraries Used
This tutorial uses Spring Web Flow 2.3, Spring Security 3, Spring 3.0.5, JSF 2 and ICEfaces 2.0. Additional libraries are needed to support these frameworks and have been noted in the tutorial's build.xml or pom.xml file. This tutorial also has been tested with the Spring Web Flow 2.2.1 library as well. The JSF version in the attached tutorial is 2.1.0-b03. Starting with JSF v2.1.0-b08, there is an UnsupportedOperationException thrown by a JSF baseclass with improperly overridden methods. This wont be resolved until Spring releases a newer version of Spring-webflow. Note in the included pom.xml file, the ICEfaces dependency on higher versions of JSF (in the ICEfaces pom) must be excluded or multiple versions of JSF will be included in the war.
Page 357
1. 2. 3. 4.
Your Web.xml For Spring (Core, Web Flow, and Security) Spring Core Spring Web Flow Spring Security
<?xml version="1.0" encoding="UTF-8"?> <web-app 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_2_5.xsd" version="2.5"> <!-- Use JSF view templates saved as *.xhtml, for use with Facelets --> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <!-- Enables special Facelets debug output during development --> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <!-- Causes Facelets to refresh templates during development --> <context-param> <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name> <param-value>1</param-value> </context-param> <!-- Enforce UTF-8 Character Encoding --> <filter> <filter-name>charEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>charEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Enables Spring Security --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern>
Page 358
</filter-mapping> <!-- Loads the Spring web application context --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Map all /spring requests to the Dispatcher Servlet for handling --> <servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/spring/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>Icefaces Resources Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Just here so the JSF implementation can initialize, *not* used at runtime --> <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>Icefaces Resources Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <!-- Just here so the JSF implementation can initialize --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
Page 359
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!-- Scans for application @Components to deploy --> <context:component-scan base-package="org.springframework.webflow.samples.booking" /> <!-- Imports the configurations of the different infrastructure systems of the application --> <import resource="config/webmvc-config.xml" /> <import resource="config/webflow-config.xml" /> <import resource="config/data-access-config.xml" /> <import resource="config/security-config.xml" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:webflow="http://www.springframework.org/schema/webflow-config" xmlns:faces="http://www.springframework.org/schema/faces" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ spring-beans.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/ webflow-config/spring-webflow-config.xsd http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/springfaces.xsd"> <!-- Executes flows: the central entry point into the Spring Web Flow system --> <webflow:flow-executor id="flowExecutor"> <webflow:flow-execution-listeners> <webflow:listener ref="facesContextListener"/> <webflow:listener ref="securityFlowExecutionListener" /> </webflow:flow-execution-listeners> </webflow:flow-executor> <!-- The registry of executable flow definitions --> <webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/ WEB-INF/flows"> <webflow:flow-location-pattern value="/**/*-flow.xml" /> </webflow:flow-registry> <!-- Configures the Spring Web Flow JSF integration --> <faces:flow-builder-services id="facesFlowBuilderServices" development="true" /> <!-- Installs a listener that creates and releases the FacesContext for each request. -->
Page 360
<bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener"/> <!-- Installs a listener to apply Spring Security authorities --> <bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <!-- Configure Spring Security --> <http auto-config="false" use-expressions="true" access-denied-page="/spring/login"> <form-login login-page="/spring/login" login-processing-url="/spring/loginProcess" default-target-url="/spring/main" always-use-default-target="true" authentication-failure-url="/spring/login?login_error=1" /> <!-- When using custom filters, please make sure the positions do not conflict with default filters. Alternatively you can disable the default filters by removing the corresponding child elements from http and avoiding the use of http auto-config='true'. --> <custom-filter ref="exceptionTranslationFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<logout logout-url="/spring/logout" logout-success-url="/spring/logoutSuccess"/> <intercept-url pattern="/secure" method="POST" access="hasRole('ROLE_SUPERVISOR')"/> </http> <!-Define local authentication provider, a real app would use an external provider (JDBC, LDAP, CAS, etc) usernames/passwords are: keith/melbourne erwin/leuven jeremy/atlanta scott/rochester --> <authentication-manager> <authentication-provider> <password-encoder hash="md5"/> <user-service>
Page 361
<user name="keith" password="417c7382b16c395bc25b5da1398cf076" authorities="ROLE_USER, ROLE_SUPERVISOR"/> <user name="erwin" password="12430911a8af075c6f41c6976af22b09" authorities="ROLE_USER, ROLE_SUPERVISOR"/> <user name="jeremy" password="57c6cbff0d421449be820763f03139eb" authorities="ROLE_USER"/> <user name="scott" password="942f2339bf50796de535a384f0d1af3e" authorities="ROLE_USER"/> </user-service> </authentication-provider> </authentication-manager>
<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter"> <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" / > <beans:property name="invalidSessionUrl" value="/auth/sessionExpired.jsf" /> <beans:property name="redirectStrategy" ref="jsfRedirectStrategy" /> </beans:bean>
<!-- http://static.springsource.org/spring-security/site/docs/3.1.x/reference/core-web-filters.html --> <beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter"> <beans:property name="accessDeniedHandler" ref="jsfAccessDeniedHandler"/> <beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/> </beans:bean> <beans:bean id="jsfAccessDeniedHandler" class="com.icesoft.spring.security.JsfAccessDeniedHandler"> <beans:property name="loginPath" value="/spring/login" /> <beans:property name="contextRelative" value="true" /> </beans:bean> <beans:bean id="authenticationEntryPoint" class="com.icesoft.spring.security.JsfLoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/spring/login"/> <beans:property name="redirectStrategy" ref="jsfRedirectStrategy" /> </beans:bean >
Resources
Spring Web Flow 2.3 Documentation
Page 362
Spring Security
This page last changed on Mar 21, 2011 by ben.simpson.
Creator Creation Last Mod Comment (Last Date Date Modifier) SpringSecurity3IceFaces2-Ben Simpson Mar 04, 28 kB Mar 04, Spring $item.label.getDisplayable tutorial.zip 2011 2011 Security $webInterfaceContext) Sample App | $item.label.getDisplayable $webInterfaceContext)
Technologies/Libraries Used
This tutorial uses Spring Security 3.1, Spring 3, JSF 2 and ICEfaces 2. Additional libraries are needed to support these frameworks and have been noted in the tutorial application's build.properties file. Configuration Areas: 1. 2. 3. 4. Configure Your Web.xml For Spring Security Configure Your applicationContext.xml For Spring Security Configure Your Web.xml For JSF Advanced: Configure Your Spring Security redirectStrategy
Page 363
<web-app 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_2_5.xsd" version="2.5"> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext.xml /WEB-INF/applicationContext-security.xml </param-value> </context-param> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <!-- key configuration here is an entry point to be used by security intercepts --> <http realm="Sample Realm" entry-point-ref="authenticationEntryPoint"> <!-- any role that is used to protect a directory, can be multiples --> <intercept-url pattern='/secure/**' access='ROLE_READER' /> <!-- enable form login to use UsernamePasswordAuthenticationFilter [/j_spring_security_check] --> <form-login login-page="/general/logins/htmlLogin.faces" authentication-failure-url="/general/logins/loginFailed.faces"/> <!-- logout page uses the default LogoutFilter, no changes are needed as IT accepts a GET call... --> <!-- here is an example logout link: <a href="#{request.contextPath}/j_spring_security_logout">Logout</a> --> <logout logout-url="/j_spring_security_logout" logout-success-url="/general/main.faces" invalidate-session="true"/> </http> <beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/general/logins/htmlLogin.faces" />
Page 364
</beans:bean> <!-- test with this before you hook up your LDAP or other Authentication Manager --> <authentication-manager alias="authenticationManager"> <authentication-provider> <user-service> <user name="joe.blow@icesoft.com" password="pass1234" authorities="ROLE_READER"/> <user name="ben.simpson@icesoft.com" password="pass5678" authorities="ROLE_READER"/> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
... <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</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> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> ...
Page 365
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <!-- key configuration here is an entry point to be used by security intercepts --> <http realm="Sample Realm" entry-point-ref="authenticationEntryPoint" auto-config="false"> <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" /> <!-- any role that is used to protect a directory, can be multiples --> <intercept-url pattern='/secure/**' access='ROLE_READER' /> <!-- enable form login to use UsernamePasswordAuthenticationFilter [/j_spring_security_check] --> <form-login login-page="/general/logins/htmlLogin.faces" authentication-failure-url="/general/logins/loginFailed.jsf"/> <!-- logout page uses the default LogoutFilter, no changes are needed as IT accepts a GET call... --> <!-- here is an example logout link: <a href="#{request.contextPath}/j_spring_security_logout">Logout</a> --> <logout logout-url="/j_spring_security_logout" logout-success-url="/general/main.jsf" invalidate-session="true"/> </http> <beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/general/logins/login.jsf" /> </beans:bean> <!-- test with this before you hook up your LDAP or other Authentication Manager --> <authentication-manager alias="authenticationManager"> <authentication-provider> <user-service> <user name="joe.blow@icesoft.com" password="pass1234" authorities="ROLE_READER"/> <user name="ben.simpson@icesoft.com" password="pass5678" authorities="ROLE_READER"/> </user-service> </authentication-provider> </authentication-manager> <beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter"> <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" / > <beans:property name="invalidSessionUrl" value="/general/logins/sessionExpired.jsf" /> <!-- this permits redirection to session timeout page from javascript/ajax or http --> <beans:property name="redirectStrategy" ref="jsfRedirectStrategy" /> </beans:bean> <beans:bean id="jsfRedirectStrategy" class="com.icesoft.spring.security.JsfRedirectStrategy"/> <beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/> </beans:beans>
Resources
For more information on Spring Security, please check out the content below: Spring Security Tutorials Spring Security Documentation
Page 366
Converters
This page last changed on Dec 10, 2010 by brad.kroeger.
This tutorial will discuss the following topics related to the use of JSF converters: Single / Partial Submit and Immediate Attributes
Page 367
How to Use Standard JSF Converters How to Write Custom Converters Message and Messages Tags Tutorial Source Code Downloads
The immediate attribute can be used to achieve the following effects: Allow a commandLink or commandButton to navigate the user to another page without processing data currently in input fields of the current screen. In particular, this allows navigation to occur even when there are currently validation errors. Ex: a "Cancel" button. Allows a commandLink or commandButton to trigger back-end logic while ignoring validation for some of the fields on the screen. Makes one or more input components "high priority" for validation, so that if any of these are invalid then validation is not performed for any "low priority" components on the same page. This can reduce the number of error messages shown. Using the immediate attribute on a component means its value will be validated during the apply request values phase in the JSF lifecycle. Since conversion already occurs in this phase the use of this attribute does not affect conversion. The immediate attribute is used to affect validation.
Page 368
For the standard converter tag, <f:converter/>, JSF has many standard data converters. The following is a sample of the id's of the data converters available: javax.faces.Double javax.faces.Integer javax.faces.Float javax.faces.Boolean
To use the converter with a component, the converter must be nested inside the components tag. The following JSF code shows how to add a standard converter for an inputText component:
This will now ensure that only integer values can be sent into the backing bean and not something else such as a character. In the screen shot below, you can see what happens when a non-integer value is entered.
When dealing with date data you must use the <f:convertDateTime/> converter tag. This will convert a string to a proper Date object. If the string entered in is not convertible then an error message will be displayed. The following JSF code is an example on how to implement a date converter:
Page 369
This will convert the entered string to a short Date format. The following table displays all the standard formats available and what they look like:
Format 26-Apr-99 4/26/99 26-Apr-99 April 26, 1999 Monday, April 26, 1999
In addition to converters for primitives, date, and time data types, JSF provides another converter for dealing with numbers such as percentages and currency. This converter deals with grouping, number of decimal digits, currency symbols, etc. The following JSF code shows how to add a number converter for dealing with currency:
<ice:inputText id="salary" value="#{user.salary}"> <f:convertNumber maxFractionDigits="2" groupingUsed="true" currencySymbol="$" maxIntegerDigits="7" type="currency"/*> </ice:inputText>
This will allow only whole numbers entered with a dollar sign and up to seven digits can only be entered at a time. Anything that breaches these conditions will cause a Conversion Error to be thrown.
Create a utility class that will handle all of the conversion duties. This class must implement the Converter interface as shown below:
import javax.faces.convert.Converter
Page 370
public class PhoneConverter implements Converter { public Object getAsObject(FacesContext context, UIComponent component, String value){ if(StringUtils.isEmpty(value)){ return null; } PhoneNumber phone = new PhoneNumber(); String [] phoneComps = StringUtils.split(value," ,()-"); String countryCode = phoneComps[0]; phone.setCountryCode(countryCode); if(countryCode.equals("1")){ String areaCode = phoneComps[1]; String prefix = phoneComps[2]; String number = phoneComps[3]; phone.setAreaCode(areaCode); phone.setPrefix(prefix); phone.setNumber(number); } else { phone.setNumber(value); } return phone; } }
public class PhoneConverter implements Converter { ... public String getAsString(FacesContext context, UIComponent component, Object value){ return value.toString(); } }
For the above code to work you must implement the objects (PhoneNumber) toString() method accordingly. For example:
Page 371
return countryCode + "-" + areaCode + "-" + prefix + "-" + number; } else { return number; } } }
This step can be executed in two ways. Option one is to register the PhoneConverter class with a user defined id (icefaces.PhoneConverter). This id is used by <f:converter/> tags converterId attribute. To implement this, insert the following code into your faces-config.xml file:
The other option is to register the PhoneConverter class to handle all PhoneNumber objects automatically. To do this insert the following code into your faces-config.xml file:
The last step is using the converter. This is very similar to using the standard JSF <f:converter> tag. For the first option from step four:
For the second option from step 4, there is no need to use the <f:converter/> tag since the PhoneConverter class handles all PhoneNumber objects automatically.
Page 372
<ice:inputText id="age" value="#{user.age}"> <f:converter converterId="javax.faces.Integer"/> </ice:inputText> <ice:message style="color:red;" id="ageError" for="age"/>
Custom Messages
The default messages that are supplied by JSF can be quite verbose and could cause confusion for end users. For conversion the default error message is the vague "Conversion error occurred". To change the default message you can create your own message.properties file and switch out the message resource bundle in the faces context. The following code shows how to add the properties file to the faces context:
Page 373
</message-bundle> </application>
The following is the entry in the messages.properties file that will override the default converter error message:
This will now display the message "invalid input" beside the field that is causing the error shown in the screen shot below.
Page 374
Example converter-basic
Notes Simple example of how to use the standard JSF converters. A custom converter is added to the converter-basic application.
converter-custom
Page 375
Here is the entire list of steps worked through during this tutorial: 1. 2. 3. 4. 5. 6. Make the compositeComponent Project Add ICEfaces Create main.xhtml Create NameBean.java Deploy the Application Create a Composite Component Create Directory Structure Create Component Page 7. Using a Composite Component Add Namespace Use fieldSet.xhtml 8. Add Middle Name Add to Bean Add to Page 9. Re-Deploy the Application Tutorial Source Code Downloads
Page 376
2. Add ICEfaces
Add the icefaces.jar to your project from the ICEfaces 2 bundle. This can be added to the project through a custom User Library or by putting it into compositeComponent/WEB-INF/lib/. The approach doesn't matter as long as the jar is included in the deployed war file.
3. Create main.xhtml
Create a new page called main.xhtml and paste the code below:
<!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" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Composite Component - Main</title> </h:head> <h:body> <h:form> <h:panelGrid columns="3"> <f:facet name="header"> Hello, what is your name? </f:facet> <h:outputLabel for="firstName" value="First Name"/> <h:inputText id="firstName" value="#{nameBean.firstName}" required="true"/> <h:message for="firstName"/> <h:outputLabel for="lastName" value="Last Name"/> <h:inputText id="lastName" value="#{nameBean.lastName}" required="true"/> <h:message for="lastName"/> <f:facet name="footer"> <h:commandButton value="Submit"/><br/> </f:facet> </h:panelGrid> <h:outputText value="Greetings '#{nameBean.firstName} #{nameBean.lastName}'." rendered="#{nameBean.hasName}"/> </h:form> </h:body> </html>
This basic page prompts the user for their first and last name, and displays the result after the user has submitted the form. The page doesn't use any composite components, but the similar, repeated markup of h:outputLabel, h:inputText, and h:message is a perfect candidate for a composite component.
4. Create NameBean.java
Create a new Java class file called NameBean in the package org.icefaces.tutorial.composite.beans and paste the code below:
Page 377
@SessionScoped public class NameBean { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public boolean getHasName() { return firstName != null && lastName != null; } }
As with the page this backing bean is very simple. We manage the first and last name variables, and also have a convenience method to determine if a name has been entered or not.
When entering a name and pressing the "Submit" button you will see "Greetings, firstName lastName" appear at the bottom.
Page 378
6b. Create Component Page Inside the example/ directory created above, create a new page called fieldSet.xhtml and paste the code below:
<?xml version="1.0" encoding="utf-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:composite="http://java.sun.com/jsf/composite"> <composite:interface> <composite:attribute name="label" /> <composite:attribute name="value" required="true" /> <composite:attribute name="required" default="false" /> <composite:editableValueHolder name="input" /> </composite:interface> <composite:implementation> <h:outputLabel for="input" value="#{cc.attrs.label}" style="float:left;"/> <h:inputText id="input" value="#{cc.attrs.value}" style="float:left;" required="#{cc.attrs.required}"/> <h:message for="input" id="msg"/> </composite:implementation> </html>
This is our composite component interface and implementation. The interface declares how the composite component will be used in a parent page, including available attributes and the default values for those attributes. The implementation actually holds the markup that is inserted into the parent page when the composite component is used. The new markup used in our page as a result of creating the composite component:
In the <html> container at the top of main.xhtml add the namespace above.
Page 379
7b. Use fieldSet.xhtml Now let's replace our first and last name markup with the new composite component. Replace the existing <h:panelGrid> with the following code:
<h:panelGrid> <f:facet name="header"> Hello, what is your name? </f:facet> <ourComp:fieldSet label="First Name" value="#{nameBean.firstName}" required="true"/> <ourComp:fieldSet label="Last Name" value="#{nameBean.lastName}" required="true"/> <f:facet name="footer"> <h:commandButton value="Submit"/><br/> </f:facet> </h:panelGrid>
The markup is simpler while still remaining functional. If we needed more attributes than the three (label, value, required) we made available in the composite component, we could just modify the composite:interface to add more "passthrough" attributes, such as maxlength, size, style, etc.
* Also modify the getHasName method to include the new middleName variable. 8b. Add to Page Add the new middleName by pasting another instance of our new composite component between the firstName and lastName markup in main.xhtml:
* Also modify the outputText at the bottom to include displaying the new #{nameBean.middleName} variable.
Page 380
Notes Basic example project demonstrating how a composite component can be created and added to an ICEfaces 2 page.
Page 381
Internationalization in ICEfaces
This page last changed on Dec 10, 2010 by brad.kroeger.
Here is the entire list of steps worked through during this tutorial: 1. 2. 3. 4. 5. 6. 7. Make the internationalization Project Add ICEfaces Setup faces-config.xml Locales Create Resource Bundles Create main.xhtml Create PageBean.java Deploy and Test the Application
2. Add ICEfaces
Add the icefaces.jar to your project from the ICEfaces 2 bundle. This can be added to the project through a custom User Library or by putting it into internationalization/WEB-INF/lib/. The approach doesn't matter as long as the jar is included in the deployed war file.
Page 382
<application> <locale-config> <default-locale>en</default-locale> <supported-locale>de</supported-locale> </locale-config> <resource-bundle> <base-name> org.icefaces.tutorial.internationalization.resources.messages </base-name> <var>msgs</var> </resource-bundle> </application>
This code performs two tasks related to internationalization. First we specify our default locale (English en) and our supported locale(s), in this case only German de. If we wanted to add more locales we could specify further supported-locale nodes. The second piece of code tells our application where the internationalized resource bundle is. The basename points to a series of property files that we'll create in Step 4. The var is the name used to access the messages from our page markup.
As you can see when we reference "firstName" in the page markup, we will get the value "First Name" returned. Similary paste the German version of these values into the messages_de.properties file:
firstName=Vorname lastName=Nachname
5. Create main.xhtml
Now we will create a simple page that will use the internationalized strings. Create a new page called main.xhtml and paste the code below:
Page 383
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <f:view locale="#{pageBean.currentLocale}"> <h:head> <title>Internationalization - Main</title> </h:head> <h:body> <h:form> <h:panelGrid columns="2"> <h:selectOneMenu value="#{pageBean.dropdownItem}" valueChangeListener="#{pageBean.localeChanged}"> <f:selectItems value="#{pageBean.availableLocales}"/> </h:selectOneMenu> <h:commandButton value="Change Locale"/> <h:outputLabel for="firstName" value="#{msgs.firstName}"/> <h:inputText id="firstName"/> <h:outputLabel for="lastName" value="#{msgs.lastName}"/> <h:inputText id="lastName"/> </h:panelGrid> </h:form> </h:body> </f:view> </html>
The <h:selectOneMenu> will be managed through our upcoming backing bean. The component will be used to allow users to dynamically switch their locale for the entire app. Notice that the <h:outputLabel value attributes are internationalized. We use the var msgs that was previously declared in faces-config.xml, and a key that corresponds to the resource bundle. So #{msgs.firstName} will correspond to "First Name" in the English locale, or "Vorname" in the German locale. We manually specify the current locale in the <f:view> container, via the locale attribute. This allows us to modify that variable and have it apply properly to the entire page.
6. Create PageBean.java
Create a new Java class file called PageBean in the package org.icefaces.tutorial.internationalization.beans and paste the code below:
package org.icefaces.tutorial.internationalization.beans; import import import import import import import import import import java.io.Serializable; java.util.ArrayList; java.util.Iterator; java.util.List; java.util.Locale; javax.faces.bean.ManagedBean; javax.faces.bean.SessionScoped; javax.faces.context.FacesContext; javax.faces.event.ValueChangeEvent; javax.faces.model.SelectItem;
@ManagedBean(name="pageBean") @SessionScoped public class PageBean implements Serializable { private List<SelectItem> availableLocales; private Locale currentLocale; private String dropdownItem;
Page 384
public PageBean() { setCurrentLocale(FacesContext.getCurrentInstance().getViewRoot().getLocale()); dropdownItem = currentLocale.getLanguage(); } private void generateAvailableLocales() { availableLocales = new ArrayList<SelectItem>(0); // Add the default locale availableLocales.add (makeLocaleItem(FacesContext.getCurrentInstance().getApplication().getDefaultLocale())); // Add any other supported locales for (Iterator<Locale> iter = FacesContext.getCurrentInstance().getApplication().getSupportedLocales(); iter.hasNext();) { availableLocales.add(makeLocaleItem(iter.next())); } } private SelectItem makeLocaleItem(Locale toWrap) { if (toWrap != null) { return new SelectItem(toWrap.getLanguage(), toWrap.getDisplayName()); } return null; } public List<SelectItem> getAvailableLocales() { if (availableLocales == null) { generateAvailableLocales(); } return availableLocales; } public void setAvailableLocales(List<SelectItem> availableLocales) { this.availableLocales = availableLocales; } public Locale getCurrentLocale() { return currentLocale; } public void setCurrentLocale(Locale currentLocale) { this.currentLocale = currentLocale; } public String getDropdownItem() { return dropdownItem; } public void setDropdownItem(String dropdownItem) { this.dropdownItem = dropdownItem; } public void applyLocale(Locale toApply) { System.out.println("Apply Locale: " + toApply.getDisplayName() + " (" + toApply.getLanguage() + ")"); setCurrentLocale(toApply); FacesContext.getCurrentInstance().getViewRoot().setLocale(toApply);
Page 385
The bean code is fairly long, but has a few important concepts to learn. The currentLocale variable is what we use to track what java.util.Locale JSF detected or the user has selected. The initial status is set through the constructor by getting the current locale from the ViewRoot (which corresponds to <f:view> in the page), using the code:
FacesContext.getCurrentInstance().getViewRoot().getLocale()
The availableLocales list is used to populate the <h:selectOneMenu> on the page. Inside the generateAvailableLocales method we use FacesContext to retrieve the default locale (from the <default-locale> value in faces-config.xml) and all supported locales (from the <supported-locale value(s) in facets-config.xml). Then we wrap those values in javax.faces.model.SelectItem objects so the page can understand them and use them properly in the <h:selectOneMenu> component. When the locale is changed via the page level dropdown, we use the localeChanged value change listener method to apply the new locale to the page. Applying the locale is achieved through the ViewRoot, as such:
FacesContext.getCurrentInstance().getViewRoot().setLocale(localeToSet);
Selecting a different Locale and clicking the "Change Locale" button will modify the two field labels, based on the contents of our messages.properties resource bundles. If you change your web browser locale to English (en) or German (de), restart the browser, and revisit the page it will automatically detect and apply the proper locale. For example, adding a locale in Firefox:
Page 386
After this change returning to the internationalization application would automatically set German as the page locale through JSF. As you can see internationalization is both easy to setup and powerful to use. Resource bundles can also be access from the bean level, and default JSF error messages can be overridden, but that is beyond the scope of this tutorial.
Page 387
Page 388
Validators
This page last changed on Dec 09, 2010 by brad.kroeger.
This tutorial will discuss the following topics: Standard JSF Validation Application Level Validation Custom Validator Custom Validator Methods in Backing Beans Single / Partial Submit Tutorial Source Code Downloads
<!-- age validator --> <ice:inputText id="age" value="#{user.age}"> <f:validateLongRange maximum="120" minimum="1"/> </ice:inputText> <ice:message style="color: red;" id="ageError" for="age"/>
Page 389
public String register(){ FacesContext context = FacesContext.getCurrentInstance(); if(StringUtils.isEmpty(user.getName())){ FacesMessage message = new FacesMessage(); message.setSeverity(FacesMessage.SEVERITY_ERROR); message.setSummary("Name Field is Blank"); message.setDetail("Name Field is Blank.."); context.addMessage("tutorialForm:name",message); return "error" } return "success" }
Custom Validator
Creating a custom validator requires four steps: 1. 2. 3. 4. Create a class that implements the Validator interface Implement the validate() method Register your custom validator in faces.config Use the <f:validator/> tag in your page
public class PhoneNumberValidator implements Validator{ /** phone number in form of xxx-xxxx*/ private static final String PHONE_NUM = "[0-9]{3}[-]{1}[0-9]{4}"; ... }
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException{ /* create a mask*/ Pattern mask = Pattern.compile(PHONE_NUM); /* retrieve the string value of the field*/ String phoneNumber = (String)value; /*check to ensure that the value is a phone number*/ Matcher matcher = mask.matcher(phoneNumber); if(!matcher.matches()){ FacesMessqage msg = new FacesMessage(); message.setDetail(" Phone number not in valid format"); message.setSumamry("Phone number not in valid format"); message.setSeverity(FacesMessage.SEVEROTY_ERROR); throw new ValidatorException(message); }
Page 390
public void validateEmail(FacesContext context, UIComponent validate, Object value){ String email = (String)value; if(email.indexOf('@')==-1){ ((UIInput)validate).setValid(false); FacesMessage msg = new FacesMessage("Invalid Email"); context.addMessage(validate.getClientId(context), msg); } }
Tag usage:
<h:form> <icecore:singleSubmit /> <ice:inputText id="age" value="#{user.age}" > <f:validateLongRange maximum="120" minimum="1"/>
Page 391
</ice:inputText> </h:form>
Example validators-standard
Notes Simple example of how to setup standard validators. Demonstration of how to setup custom validators. Example showing to set up a validator in the backing bean. This example explains how to set up validators at the application level.
validators-custom
validators-backing-bean
validators-app-level
Page 392