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.
Niciun comentariu :
Trimiteți un comentariu