My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians


luni, 9 martie 2015

JSF 2.2 - <h:form> and request/view parameters

JSF draws certain limitations when we have to exploit the interaction between request parameters, view parameters and forms. For novices, these limitations are not very clear, and usually they end up in a total confusion that give "birth" to bad practices and roundabout code.

First, is important to know what's happening with the query string (the URL part after "?") in JSF. At initial request, the query string is parsed and the request parameters from query string are stored in the request parameters map (accessible with EL via #{facesContext.externalContext.requestParameterMap} expression, or via the implicit object, param, like: #{param.parameter_name} or #{param['parameter_name']}, or in managed bean via FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()). Further, at postbacks, these request parameters don't arrive in the request parameters map anymore, because the query string doesn't participate in postbacks - this is happening because, by default, JSF doesn't preserve the query string when it compose the value for the action attribute of a form (so, at initial request, even if you see the query string in the URL (browser address bar), it is not present in any action attribute of the forms in the page, and it is not added dynamically also. Obviously, without a custom solution, at first postback, we are losing the query string and the request parameters wrapped into it.  The query string can be written manually, or it can be generated using <f:param> nested in <h:link> or <h:button>. These tags are the arsenal of preemptive (predetermined) navigation and they cannot be used for form submissions. So, in this case, <f:param> generates query request parameters, which is perfectly logical since <h:link> and <h:button> are used for GET requests. When <f:param> is used in <h:commandButton> or <h:commandLink>, the request parameters are accessible in the corresponding managed bean (if exist one) via FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(), and they doesn't appear in the query string (in the URL), since they become part of the POST request that submits the current form. Of course, during this request-response lifecycle, these parameters are available via param implicit object and #{facesContext.externalContext.requestParameterMap}. Typically, you will use <f:param> nested in <h:commandButton> or <h:commandLink> for submitting some extra parameters that doesn't make sense to appear in the managed beans properties and they have to be removed once the current request-response lifecycle is over. Nevertheless, you probably need them in your managed bean's methods for some business logic.
View parameters can be an workaround to avoid losing the request parameters values that comes via query string (GET requests). Is like JSF is asking you to point out the request parameters from the query string of this GET request that contains values that are essential to "live" across POST requests in this view (postbacks), or they should be used to initialize some managed beans properties, or to be perpetuated (altered or not) in other URLs, etc. For this, view parameters are initialized via query string using the <f:viewParam> tag nested in <f:metadata> tag and using the same parameters names - as a quick note here, the metadata section is readable without having the entire view available. A view parameter name matches a request parameter name from the query string, and this tells JSF that the view parameter value should be equal to that of the request parameter (this is the initialization of the view parameter). Further, the value of the view parameter can be converted, validated and passed in a managed bean property. Moreover, it is stored in state, which makes is available over postbacks , because view parameters are stateful - needs to be initialized only once. Nevertheless, do not conclude that view parameters can be initialized only via the query string because that is not true. There is nothing wrong with the below two view parameters, even if they don't appear in the query string:

<f:viewParam name="vat" value="24"/>
<f:viewParam name="vat" value="#{myBean.myVat}"/>

View parameters are shaped by UIViewParameter class, which is an extension of UIInput. This is major, because view parameters values can be converted and validated before they reach managed beans. Practically, they act as UIInputs. If the value is missing (value attribute is not present) or is a string literal, then JSF sets view parameters as request attributes on their names, available as #{view_parameter_name}. Actually, the main goal of view parameters is to provide support for creating bookmarkable URLs. View parameters can be included in the query string via includeViewParams="true" attribute in <h:link> and <h:button> and via includeViewParams=true request parameter in any URL (e.g. the two parameters from above can be some good candidates to build such an example). When includeViewParams=true request parameter is used (e.g. in action attribute of <h:commandButton> or  <h:commandLink>, or in a managed bean method that returns a navigation case) it takes effect only in conjunction with faces-redirect=true. With other words, view parameters can be included in the query string only for GET requests and POST redirectations (typical PRG (POST-Redirect-GET) ), NOT for POST "forwards".
Forms are the "stars" of JSF. They "shine" in JSF applications and everything "orbits" them. Basically, they encapsulate POST requests meant to "transport" data from client side to server side and expect a response. They can be easily inspected with dedicated tools, like Firebug (e.g. below picture):

The parameters submitted via a POST request (form parameters) are available via getRequestParameterMap(), but most of the time we are referring the managed beans properties that wraps these parameter's values. Moreover, the getRequestParameterMap() contains the extra request parameters that doesn't fit the managed bean properties (e.g. parameters passed via <f:param> nested in <h:commandButton> or  <h:commandLink>). Think of request parameters map as a temporarily storage for the goodies (parameters) that HTTP brought at current request. HTTP is stateless, so JSF needs to transfer the request content into managed beans and store/update managed beans instances in its scopes (request, session, application map) . The values of the parameters that doesn't fit the managed beans properties (automatically or programmatically) will be lost when the request parameter map is emptied.

Note  OmniFaces  provides a custom component named, <o:form> which extend the JSF <h:form> and provides a way to keep view or request parameters in the request URL after a post-back.

Niciun comentariu :

Trimiteți un comentariu


Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors