Primefaces and tag value from bean method - jsf

I want to set the value of a primefaces tag from a bean method using arguments but this doesn't work.
On the Facelets page:
<p:outputLabel id="userLabel" value="#{languageBean.retrieveLanguage(1)}" />
<p:commandButton value="#{languageBean.retrieveLanguage(2)}"
action="#{loginBean.logIn()}"
update="loginForm"/>
On the bean:
public String retrieveLanguage(int key) {
return (String) getPageMap(pagePath, pageName).get(key);
}
I get the following exception:
javax.faces.view.facelets.FaceletException: Error Parsing /components/login.xhtml: Error Traced[line: 24] Element type "p:outputLabel" must be followed by either attribute specifications, ">" or "/>".
Could you give me any idea, please?
Regards,
Roberto

You shouldn't be passing in the language value from the front page - this is moving actual login from the app into the graphical frontend. Rather, store the language value in the bean and simply call retrieveLanguage.
If you are trying to handle translations, have a look at resource bundles instead.

Related

how is the bean accessed first time?

I am going through the tutorial of Java EE 7 in oracle.
Here is a simple form that gets User name in a input box:
<h:body>
<h:form>
<h:graphicImage url="#{resource['images:duke.waving.gif']}"
alt="Duke waving his hand"/>
<h2>Hello, my name is Duke. What's yours?</h2>
<h:inputText id="username"
title="My name is: "
value="#{hello.name}"
required="true"
requiredMessage="Error: A name is required."
maxlength="25" />
<p></p>
<h:commandButton id="submit" value="Submit" action="response">
</h:commandButton>
<h:commandButton id="reset" value="Reset" type="reset">
</h:commandButton>
</h:form>
I see that value="#{hello.name}" is used in the code. what does this line do?
This is what is mentioned in the tutorial link:
The web page connects to the Hello managed bean through the Expression Language (EL) value expression #{hello.name}, which retrieves the value of the name property from the managed bean.
Q1) But the first time the form is loaded, there is no name attribute attached to hello bean. so Fetching that should return null correct?
Q2) Secondly, how does the value entered in the input box bind to the hello bean's name attribute?
In fact, after the form is submitted, the page is redirected to "response.xhtml" where the value of hello bean's name attribute is fetched in the same way i.e #{hello.name}.
Short answer:
Q1: correct
Q2:
On each page rendering elements, bound to #{hello.name} will receive the value, returned by Hello.getName() method.
On each form submit (in case form is valid), Hello.setName(param) will be called with param equals to value of element, bound to #{hello.name}
Longer answer:
You have:
Hello.java, the class annotated with #Named and #RequestScoped
<h:inputText value="#{hello.name}" /> inside <h:form> on index.xhtml
#{hello.name} inside <h2> on response.xhtml
Prerequisites:
#Named is a CDI annotation.
When application is deployed, the server "registers" Hello.java as a managed bean.
#Named could be used as #Named(name="explicitHelloName"), but if argument isn't provided, the bean will be registered as "lower cased class name", so, after your application is deployed, we have hello to be used wherever it needed.
#RequestScoped says that data of each Hello instance will "live" only during request-response (see this answer for scoping details).
This article greatly describes JSF lifecycle. We are interested in two fazes of it:
RENDER_RESPONSE and UPDATE_MODEL_VALUES.
Let's go step by step:
I. Browser requests index.xhtml
FacesServlet's responsibility (because we are mapping all *.xhtml files to Faces Servlet inside web.xml) is to build html and return it as a response.
Building consists of several phases (look here for details), one of which, RENDER-RESPONSE:
Builds a UIViewRoot
Recursively builds UIViewRoot's children.
During 2) for children, that has some EL expressions, these expressions being "resolved".
In your case we have #{hello.name} expression, bound to value of an UIInput (h:inputText is an UIInput).
<h:inputText> will be rendered as HTML's <input type="text">.
FacesServlet "understands" that value for this input should be taken from something that #{hello.name} represents.
To get the value:
FacesServlet "asking" for hello from container (server)
Container searches for registered hello, finding Hello.java, instantiating it and gives to FacesServlet.
FacesServlet calling for getName() (JavaBean convention to get the "name") of Hello instance and receives the value of Hello's private field name, which after class instantiation is null.
FacesServlet writes <input> without value to response and on index.xhtml you see an empty input.
II. When you press submit button
...and form is valid, there is UPDATE_MODEL phase (more detailed here),.
For our h:inputText component FacesServlet again searches for hello, finding an instance of Hello and calls setName(value) on it.
As <h:commandButtons>'s action attribute is response, browser is about to receive response.xhtml's content (this is not a redirection, see this answer, so, #RequestScoped hello isn't being recreated).
III. response.xhtml
...has <h3>Hello, #{hello.name}</h3>, so, again, FacesServlet must resolve it as described earlier.
But in current request the Hellohave been instantiated and it's field name was already set (in UPDATE_MODEL_VALUES phase) with the value you entered to input, so, <h3>Hello, YOUR_SUBMITTED_TO_INPUT_TEXT_VALUE</h3> is written to response and displayed in browser.
More details about expressions can be found here
Edit
If you use <h:comandButton action="response?faces-redirect=true"/> on the index.xhtml, then after II there will be a redirect to response.xhtml, and Hello bean become recreated, so, you will see "Hello, " (name will be null)

Show #NotNull message in p:tooltip

I was wondering if one could access the validation error message assigned via Bean validation through the UIInput's binding.
For example, i have the following property:
#NotNull(message = "{username_required}")
private String username;
When I print the error using h:message, i get the appropriate message printed out, so I know that Bean Validation works correctly. I would like to print out the message without h:message tag, supplying the value directly to a tooltip, like this:
<p:tooltip for="usernameErrorImage" rendered="#{!usernameInputBinding.valid}"
value="#{!usernameInputBinding.requiredMessage}"/>
The 'rendered' attribute works as expected, however the value of the tooltip is 'true', which is not my message. I have also tried 'convertedMessage' and 'requiredMessage', but both of them also return the string 'true'. Putting the h:message inside of the tooltip tag prints out the message, however I would like to know if I can access the validation message directly through the binding.
Provided that you've a ValidationMessages.properties with among others the username_required entry, just use <f:loadBundle> the usual way to load it as a resource bundle in JSF view.
<f:loadBundle basename="ValidationMessages" var="validationMessages" />
...
<p:tooltip ... value="#{validationMessages['username_required']}"/>
Grabbing the component's requiredMessage attribute as in your initial attempt will definitely not work as it only returns the manually definied requiredMessage attribute.
You can nest the message inside the tooltip.
This worked for me in Primefaces 4.
bean:
#NotNull(message = "{username_required}")
private String username;
xhtml:
<p:tooltip for="usernameErrorImage">
<p:message for="usernameErrorImage" />
</p:tooltip>

CommandButton action: use value of inputText as parameter in dynamic URL

I need to make a small form where user types a number into the inputField, and clicks on a button, then is sent to a page, using that number as a parameter to the page.
So far I got into this:
<p:inputText id="myText" style="width:75px;" />
<p:commandButton id="myButton" value="Ir"
action="/site/page.xhtml?id=${param['form:myButton']}"
title="Ir" ajax="false" proces="#this,myText" />
tried with ${param['form:myButton']} and #{param['form:myButton']}, error is the same.
Problem is, JSF thinks its a method expression...
GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/intranet] threw exception [/myPage action="/site/page.xhtml?id=${param['form:myButton']}".xhtml #95,41 action="/site/page.xhtml?id=${param['form:myButton']}" Not a Valid Method Expression: action="/site/page.xhtml?id=${param['form:myButton']}" with root cause
javax.el.ELException: Not a Valid Method Expression: action="/site/page.xhtml?id=${param['form:myButton']}"
at org.apache.el.lang.ExpressionBuilder.createMethodExpression(ExpressionBuilder.java:236)
at org.apache.el.ExpressionFactoryImpl.createMethodExpression(ExpressionFactoryImpl.java:55)
at org.jboss.weld.util.el.ForwardingExpressionFactory.createMethodExpression(ForwardingExpressionFactory.java:43)
at org.jboss.weld.el.WeldExpressionFactory.createMethodExpression(WeldExpressionFactory.java:64)
at com.sun.faces.facelets.tag.TagAttributeImpl.getMethodExpression(TagAttributeImpl.java:222)
at com.sun.faces.facelets.tag.jsf.ActionSourceRule$ActionMapper2.applyMetadata(ActionSourceRule.java:104)
at com.sun.faces.facelets.tag.MetadataImpl.applyMetadata(MetadataImpl.java:81)
at javax.faces.view.facelets.MetaTagHandler.setAttributes(MetaTagHandler.java:129)
at javax.faces.view.facelets.DelegatingMetaTagHandler.setAttributes(DelegatingMetaTagHandler.java:102)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.doNewComponentActions(ComponentTagHandlerDelegateImpl.java:402)
and this is the bottom-most exception trace.
Question: how can I pass the value typed into of the input-field into the action of the Button when the button is clicked, so the browser navigates to the desired page passing the value in the input as a parameter, without resorting to a backing bean.
I don't need to communicate with the server, just forward the page.
any solution using jQuery or plain javascript in tandem with JSF is acceptable too.
using mojarra, primefaces 3.3.1
use <f:param> It's explained in this article from BalusC http://balusc.blogspot.in/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters
I do not need a bazooka to kill a mouse. The answer is very simple.
bind a javascript function to the onclick of the button, and in that function, retrieve the value of the input field by its id, then assemble URL with the parameters and navigate away from within the javascript function.
JSF code (assume they are inside a form with myForm as its id):
<p:inputText id="myInput" style="width:75px;" />
<p:commandButton id="myButton" value="Ir" onclick="navega();" title="Ir" ajax="false" proces="#none" />
Javascript script, declared on a separate file or later on in the xhtml document:
function navega() {
var submittedInputValue = $('#myForm\\:myInput').val();
window.location.href = "/site/mypage.xhtml?param1=whatever&id=" + submittedInputValue ;
}
Take note of the prepend id (myForm:myInput), of using \\ to escape the : in jQuery, and using & instead of & in the xhtml so its not treated as an entity.
Note: probably not all of those commandButton attributes are required, feel free to edit this answer and remove the useless ones.
EDIT: removed the submit and changed process to #none on the command button.

UIComponent#getValue() obtained via binding is not available in validator of another component

I'm trying to figure out why an f:attribute tag's value isn't passed when attached to h:inputSecret tag. I'm quite new to jsf, but as far as I know attributes can be attached to any kind of component. Here is the code:
<h:inputSecret id="passw" value="#{advertAdder.userPass}"
required="true" validator="#{advertAdder.validatePasswords}">
<f:attribute name="confirmedPass" value="#{advertAdder.passConfirmator.value}"/>
</h:inputSecret>
<h:inputSecret id="passwConfirm" required="true"
binding="#{advertAdder.passConfirmator}"/>
and the method that wants to acces this attribute:
public void validatePasswords(FacesContext context, UIComponent component, Object value)
{
if (!value.equals(component.getAttributes().get("confirmedPass")))
{
FacesMessage mess = new FacesMessage("Password and it's confirmation are not the same!");
context.addMessage(component.getClientId(context), mess);
((UIInput) component).setValid(false);
}
}
In above code component.getAttributes() always returns map with only two attributes:
javax.faces.component.VIEW_LOCATION_KEY and com.sun.faces.facelets.MARK_ID.
I've added attribute tag to a h:commandButton to check it, and then everything was fine. Am I missing something or it's not possible to add an attribute to non-action tag?
I'm using Mojarra 2.0.2 and Glassfish 3.0.1.
Thanks in advance.
Input components are processed in the order as they appear in the component tree. The UIInput#getValue() is only available when the component is already been processed. Otherwise you need to use UIInput#getSubmittedValue() instead.
<f:attribute name="confirmedPass" value="#{advertAdder.passConfirmator.submittedValue}"/>
Note that this gives you the unconverted and unvalidated value back. It would make somewhat more sense to put the validator on the confirm password field instead and pass the value of the first password field along. See also JSF Validator compare to Strings for Equality and JSF doesn't support cross-field validation, is there a workaround?
Alternatively, you can also try out the OmniFaces <o:validateEqual> component. You can find a concrete example in this article.
Unrelated to the concrete problem, it's unnecessary to bind the component to the bean this way. Replace all occurrences of #{advertAdder.passConfirmator} by #{passConfirmator}. Keep the controller free of properties which are never internally used.

Populate by code SelectOneMenu based on custom meta-data in attributes

I need a solution to populate by code SelectOneMenu using some meta-data specified as an attribute to this component.
Here is the detail of my requirement.
1) The developer would specify some thing like this:
<h:selectOneMenu id="someComponent" value="#{someController.someModel.someField}">
<f:attribute name="entity" value="somepackage.SomeEntity" />
</h:selectOneMenu>
2) When the page containing the above is requested for the first time, the server should be able to read the 'entity' attribute
3) Once the 'entity' is read, the server will do the needful to populate dynamically 'someComponent'.
I have no issue with the code that should use the 'entity' attribute and generate the content to be show in 'someComponent'. My issue is to found the appropriate place to call efficiently this code.
I have tried the PhaseEventListener for 'After Render Response Phase' but with no luck. It looks like I'm missing something fundamental as I'm new to JSF.
Have someone went through the same experiment?
Thank you in advance.
Younes Ouadi
If you target an EL 2.2 container which supports invoking methods with arguments and/or supply JBoss EL with your webapp so that it works on EL 2.1 as well, then it should be possible with the following construct:
<h:selectOneMenu id="someComponent" value="#{someController.someModel.someField}">
<f:selectItems value="#{someProvider.selectItems('somepackage.SomeEntity')}" />
</h:selectOneMenu>
with
public List<SelectItem> getSelectItems(String className) {
// ...
}
I'd introduce some lazy loading and/or request-based caching mechanism as well as a getter can be called more than once during bean's life.

Resources