JSF 2.0 : Runtime variables in property files - jsf

All text in our app is read from properties file
e.g.
<h:outputText value="#{text['fill.form']}"/>
text is a resource bundle that resolves to Text.properties.
Text.properties
fill.form=Please fill out the form below
There are other instance where we need run time variables inside the properties
e.g.
welcome.user=Welcome #{name.last}, #{name.first} to our site
name is a managed bean whose properties first and last get resolved at run time.
However the first name and last name are not resolved at run time. Instead the user sees the following
Welcome #{name.last}, #{name.first} to our site
Any solutions to this problem?
Should I write a custom EL resolver to resolve the text from the properties and also any run time properties inside of it.

I believe you want to use h:outputFormat to accomplish this. In your example, you might do this:
<h:outputFormat value="#{text['welcome.user']}">
<f:param value="#{name.last}"/>
<f:param value="#{name.first}"/>
</h:outputFormat>
For this to work, you need to change your welcome message to this:
welcome.user=Welcome {0}, {1} to our site

Related

Init method is not filled in even with parameters

I have lost a few hours trying to figure out why I can not retrieve the parameters of my link. Following this question, I did my link with passing parameters. My problem is relatively easy, if I can get the parameters in the popup that opens when the user clicks the link. Except that I can not get them.
My class has a method annotated with #Create that every time the object is initialized it executes this method.
The only way I can get the idsess_ parameter is in the URL, but I can not pass any parameters I want the URL.
In short, by clicking on my <a:commandLink> wish the <f:param>'s were passed to the bean in a matter and the same to process according to these parameters.
Edit: changed my code and created my own action. In this case I was reusing an action of another view. I recreated my action and used the method described in the answer that was accepted
Not sure what your <a:commandLink/> component is? (Im assumed you re-mapped a4j:commandLink somehow?)
I think the problem you are having is that the #RequestParameter variables are only populated when the page first renders, when you click the commandLink you are performing a postback so the values are lost.
You should try doing a redirect instead (ie. using <s:link> with <f:param> rather than commandLink) or you can pass the parameters using pages.xml to bind the request params, using this markup:
<page view-id="/your-page.xhtml">
<param name="pId" value="#{bean.variable}" required="false" />
<action execute="#{bean.action}" />
</page>

Customize bean validation message?

Two stupid questions about bean validation used in JSF:
How can I remove the prefix form1:userName: from the output message?
<h:message for="userName" />
Which gets:
form1:userName: Please enter a valid username (5-20 characters)
I‘d also like to translate the name form1:userName to User Name, it's easy to implement such translation but I can't find where to build the message.
I have a custom validator, say #CreditCard, its default message is {foo.bar.BadCreditNumber}
#interface CreditCard {
String message() default "{foo.bar.BadCreditNumber}";
}
And the message is defined in foo/bar/ValidationMessages.properties in classpath. Now how can I make this properties file loaded in every page?
Concerning 1: The error message's format depends on the property javax.faces.validator.BeanValidator.MESSAGE which must be specified in a resource bundle of the application like this:
javax.faces.validator.BeanValidator.MESSAGE={1}: {0}
The placeholder {0} refers to the error message as created by the Bean Validation runtime, {1} refers to the component label. So if you don't want to have the label within the message, just make sure that the placeholder {1} isn't contained within that property value.
More information can be found in the JSF 2 spec. section 3.5.6.3.
Concerning 2: It's as BalusC is saying, just put ValidationMessages.properties to the root of your classpath. More information can also be found in the Hibernate Validator reference guide.
Use the input element's label attribute.
<h:inputText label="User name" ... />
See also JSF 2.0 tutorial - Finetuning validation.
The ValidationMessages.properties file has to be placed in the classpath root, without any package. See also JSR-303 specification.

Dynamic JSF resource bundle/message bundle

I would like to have a dynamic resource bundle in my application. I will show a form to the user where he can edit the value of Resource Bundle. I can’t restart my application for this changes take effect. I found a solution that solves part of my problem. Using “commons-configuration” from Apache or/and this http://www.coderanch.com/t/292347/JSP/java/we-reload-property-file , i could change my “.properties” file and get the results using “ResourceBundle.getBundle” .
The problem is when I try to access the property in my XHTML file like this:
<h:outputLabel value="#{msg[user.name]}" />
The value of this key is out of date.
Is there a solution for this?
Just for info, I am using spring, so I have this in my faces-config:
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
But I don’t think this is the problem. Anyway, another solution would be to use a session bean and get the property values accessing it.
What do you think about it? Would be better store this values in my database and forget about the properties file?
\o/
I have tested to move my resource bundle definition from my faces-config to my page using tag f:loadBundle and it worked!

JSF: bean scope; session vs request

I have a managed bean called UserSearchHandler, it has a doSearch method that populates UserSearchHandler.searchResults which are displayed in a table on the userSearch.xhtml page.
I have another managed bean called UserHandler, it has a showUser method and so on.
In the search results table, the user name is a link that, when clicked, is supposed to show user details on a userView.xhtml page. The table and link looks like this:
<p:dataTable var="user" value="#{userSearchHandler.searchResults" >
// ... and so on ... then
<h:commandLink value="#{user.firstName}" action="#{userHandler.showUser}">
<f:setPropertyActionListener target="#{userHandler.userIdToShow}" value="#{profile.id}"/>
</h:commandLink>
Everything works fine when the managed beans are set to session scope.
However, when I change the scope on the beans to request, the search works and the table gets populated, but when I click on the name link nothing happens. I put a break point on the userHandler.showUser method and it never gets hit when the userSearchHandler is set to "request" scope.
Can anyone help explain why this is, or what I'm doing wrong?
That's because the #{userSearchHandler.searchResults} is empty during the new request and therefore JSF is unable to locate the associated row where the commandlink is been invoked in order invoke the action (and to pass/set properties if any).
You need to ensure that the same #{userSearchHandler.searchResults} is precreated during bean's construction/initialization. If it's to be created based on a specific set of parameters, then you've to pass them along with the form as well.
That's exactly the reason why solutions like Tomahawk's <t:saveState /> and new JSF 2.0 view scope exist.
See also:
What are the main disadvantages of JSF 2.0?
I have a couple of ideas. If you're using a in your navigation you can try taking that out. Doing so would mean the browser will not make a new HTTP request when it renders the second window. It is the new HTTP request which clears the request scoped beans by. If that is not an option, you may be able to pass a parameter in your link such as a record id, which could allow you to pull data from your data source matching that id.

Displaying custom error message for a blank field in a simple JSF application

I was trying out a simple JSF application, in which I need to check if the "name" field is blank, then display an error message.
The code which takes the field's value is:
<h:outputLabel value="Name"/>
<h:inputText value="#{greeting.name}" required="true">
<f:validator validatorId="NumValidator"/>
</h:inputText>
The control of the program does not go into the validator class, if the field is submitted without entering anything, and it displays the default error message:
j_id_jsp_869892673_1:j_id_jsp_869892673_4: Validation Error: Value is required.
How do i display a custom message for this ?
The Message.properties file stored the default validation messages. This file is contained in the JAR of the JSF implementation library.
If you look at the content of this file, regarding the required validation, you will see that:
javax.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required.
To define your own error messages, create a new properties file, add the adequate error message, for example:
javax.faces.component.UIInput.REQUIRED=Hey, you forgot to fill the input {0}!
(note that {0} will be replaced by the ID of the field)
then, in your faces-config.xml, define a new message-bundle:
<message-bundle>package.that.contains.the.properties.file</message-bundle>
So for example, if your my-messages.properties is stored in the foo/bar package, you will have to write:
<application>
...
<message-bundle>foo.bar.my-messages</message-bundle>
</application>
(note that you will not have to specify the .properties extension)
The way suggested by romaintaz is definitely way to go.
On the other hand if you are looking for more customization, you can use a phase listener that fires before render response phase as does some customizing.
For example first define the value for key as below:
javax.faces.component.UIInput.REQUIRED=INPUT_REQ_FAIL
then for input components that require validation have them pass a attribute using f:attribute .Then in phase listener iterate over the face messages and check for INPUT_REQ_FAIL and replace it with cutom message along with the attribute value for the component.
I think you should look at JSR 303! This is fully standard based user input, it works out of the box with JSF 2 (I use My Faces). And the nice thing is, no need for xml or properties files to specify custom messages.

Resources