EL variable in JSF ResourceBundle - jsf

i read somewhere (don't find it anymore) that i can use EL Expresions in the resource bundle and then use it without changes in *.xhtml files.
some.text=#{someBean.stepsLeft} more
to switch the position of the variable in different languages. But actually it wont work.
I can use Interpolator class to handle the parsing or add some.text.before some.text.after and let one of them empty. I would prefer it to use it without interpolator.interpolate() if possible.

JSF resourcebundles does by default not resolve EL. It however by default supports MessageFormat API in combination with <h:outputFormat> and <f:param>.
some.text = {0} more
with
<h:outputFormat value="#{i18n['some.text']}">
<f:param value="#{someBean.stepsLeft}" />
</h:outputFormat>
You can even explicitly make it a number type so that e.g. 1000 will be displayed as 1,000 or 1.000 depending on the view locale.
some.text = {0,number} more
For more formatting options see thus the MessageFormat API documentation.

Related

Can JSF be configured to not invoke Entity setter unless the field actually changed?

When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?

JSF Multiple components in grid

I am trying to get the reusable group of jsf 1.2 components inside a panelgrid using Facelet tag file. #Balusc's previous answer at How to make a grid of JSF composite component? was a fabulous resource. I have a couple of followup questions:
In my c:when how do I test for the tagName itself instead of checking for the attributes. Instead of
<c:when test="#{type != 'submit'}">
I want to check tagName itself to decide how to format it. If 'input' do xxx.
2 Is this approach is still valid with jsf 1.2 other than f:ajax? If yes, can I replace with a4j:support...?
In my c:when how do I test for the tagName itself instead of checking for the attributes.
I'm not sure how this question makes sense. It sounds like that you're approaching something not entirely right. Do you maybe have copypasted exactly the same piece of code over multiple tag files? You should not do that. Make it a reuseable <ui:composition> or maybe <ui:decoration> instead which you compose/decorate in every tag file along with a fixed and unique <ui:param> value depending on the taglib file.
Is this approach is still valid with jsf 1.2 other than f:ajax? If yes, can I replace with a4j:support...?
Being able to create tag files is not necessarily specific to JSF, but to the view technology used, which is in this case Facelets. You can even do similar stuff in its predecesor JSP, see also this answer for an example: JSF 1.2 custom component from jsp:include It should work just fine in every JSF version supporting the view technology in question.
As to ajax support, it doesn't matter to the tag file what you're all doing inside the tag file. If you want and can use <a4j:support> then just do it.

How to get a JSF resource bundle property value in backing bean?

I am using JSF 2. I am trying to resolve a message bundle reference dynamically the a managed bean property. The value contains the bundle name as well as the key. This is required as the value may come from one of a few different bundles. I have tried many permutations, but the value from the bean seems to be always resolved as a literal String (outputting with EL brackets) and the bundle is never called to resolve and return the value. Any ideas?
I have tried:
#{bundle['key']}
${bundle['key']}
bundle['key']
They are outputted exactly as-is, also in a <h:outputText>. It works fine if I write it directly in the page. My theory is that JSF doesnt realise it has to process the String as an expression. Is there some way to force it?
EL will only be resolved in the view, not in the model. It would otherwise be a huge EL injection attack hole which allows endusers to enter arbitrary EL expressions in input fields and have them resolved. No, you cannot force it in any way.
You need to resolve it yourself. You can do that by either evaluating it programmatically using Application#evaluateExpressionGet():
FacesContext context = FacesContext.getCurrentInstance();
String value = context.getApplication().evaluateExpressionGet(context, "#{bundle['key']}", String.class);
// ...
Or, in this particular case, by just using the ResourceBundle API directly like as JSF is doing under the covers:
ResourceBundle bundle = ResourceBundle.getBundle(basename, FacesContext.getCurrentInstance().getViewRoot().getLocale());
String value = bundle.getString("key");
// ...
Try this..
Resource Bundle referenced by msg
USD=$
xhtml code:
<c:set var="key" value="#{managedBean.currencyCode}" />
<h:outputText value="#{msg[key]}"/>
This should work..

Is the ID generated by JSF guaranteed to be the same across different versions and implementations?

We are about to write a full set of tests for one of our JSF applications using Selenium.
So far, it seems that there are two preferred approaches to uniquely identify each element: by ID or using a unique class name. The later is really a hack and doesn't make sense semantically. The former is the right approach, but the element IDs are generated by JSF.
All the different JSF implementations I've seen seem to be using the same approach: use the parent element as the namespace and then concatenate the element ID using a colon. Fair enough.
The question is: do you know if this is guaranteed in some part of the JSF specification? It'd be a real problem to find out later that we need to rewrite all the component selectors in the tests just because JSF x.y changed the way it generates the ID names.
Thanks!
JSF usually generated the ID of components, if ID attribute is not explicitly mentioned.
It will be generated in the format j_idXXX (XXX will be number incremented)
<h:form id="LoginForm">
<h:inputText id="userName" .../>
</h:form>
for this inputText the id will be formed as LoginForm:userName and if id is not mentioned explicitly,then it will be formed something like LoginForm:j_id15
This is mentioned in JSF specification in section 3.1.6, But the exact format is not specified though.
The clientId is generated using this method UIComponent.getClientId(); Follow this link UIComponent
Is the ID generated by JSF guaranteed to be the same across different versions and implementations?
No. You've to explicitly specify the component ID on the UIInput component of interest and all of its parent UINamingContainer components such as <h:form>, <ui:repeat>, <h:dataTable>, etc yourself. Those IDs will by default be woodstocked using separator character :.
However, the separator character is in turn configureable since JSF 2.0. So, if you change the separator character for your webapp from : to - or something, then you'd have to rewrite the selenium tests which are relying on the HTML element IDs.
From the JSF (2.1) spec:
The client identifier is derived from the component identifier
(or the result of calling UIViewRoot.createUniqueId() if there is
not one), and the client identifier of the closest parent component
that is a NamingContainer according to the algorithm specified
in the javadoc for UIComponent.getClientId(). The Renderer
associated with this component, if any, will then be asked to convert
this client identifier to a form appropriate for sending to the
client. The value returned from this method must be the same
throughout the lifetime of the component instance unless setId() is
called, in which case it will be recalculated by the next call to
getClientId().
Aside from the spec, 3rd party plugins can affect the client identifier (e.g. protlet bridge APIs)

JSF validation error, lost value

I have a update form, with composite keys All composite keys are displayed in outputbox as I have hidden field for each composite keys. These outputbox values are empty after validation error. How do I resolve this. I am on the same page so doesn't it has to have the values.
This is indeed a non-intuitive behaviour of the h:inputHidden (I've ever filed a issue against it at the Mojarra issue list, but they didn't seem to do anything with it). The whole problem is that the component's value unnecessarily is also taken into the entire validation cycle while there's no means of user-controlled input. It will get lost when the validation fails. There are at least three ways to fix this non-intuitive behaviour.
First way is to use the binding on the h:inputHidden instead:
<h:inputHidden binding="#{bean.hidden}" />
This way the value won't undergo the unnecessary validation cycle. This however requires changes in the way you get/set the values in the backing bean code. For example:
private HtmlInputHidden hidden = new HtmlInputHidden(); // +getter +setter.
public void setHiddenValue(Object hiddenValue) {
hidden.setValue(hiddenValue);
}
public Object getHiddenValue() {
return hidden.getValue();
}
Second (and IMHO the preferred way) is to use Tomahawk's t:saveState instead.
<t:saveState value="#{bean.property}" />
The major advantage is that you don't need to change anything in the backing bean code. It will restore the value early before the apply request values phase. You only need to add extra libraries if not done yet, but as Tomahawk provides much more advantages than only the t:saveState, such as the in basic JSF implementation missing components/features t:inputFileUpload, t:dataList, t:dataTable preserveDataModel="true", t:selectOneRadio layout="spread" and so on, it is worth the effort.
The third way is to store it in a session scoped bean, but you actually don't want to do that for request scoped variables. It would only give "wtf?" experiences when the enduser has multiple tabs/windows open in the same session.

Resources