how is the bean accessed first time? - jsf

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)

Related

Setting f:setPropertyActionListener value with a f:param value

I'm trying to use the setPropertyActionListener tag to set a value in my backing bean. However, it doesn't work as I expected.
Context: userService is an instance of my backing bean, which contains an int member, reqID. This, in turn, is the key to a map of objects that belong to a class called User. I'm trying to create a page that will list all instances of User, and provide a button to visit a separate view that shows that particular User's information. To do this, I'm attempting to set userService.reqID to the id of the chosen User so it can generate a reference to that user for the next view (which is done in the call userService.toUserInfo).
If I use the xhtml snippet below:
<ui:define name="content">
<h:form>
<h:panelGrid>
<ui:repeat value="#{userService.UserList.getUserList()}" var="user">
<li>
<h:outputText value="#{user.name}" />
<h:commandButton value="View details of #{user.name}" action="#{userService.toUserInfo}">
<f:param name="id" value="#{user.id}" />
<f:setPropertyActionListener target="#{userService.reqID}" value="#{id}"/>
</h:commandButton>
</li>
</ui:repeat>
</h:panelGrid>
</h:form>
</ui:define>
The tag does not appear to evaluate id correctly and I get a Null Pointer Exception.
Earlier, I tried changing my setPropertyActionListenerTag so it read out as:
<f:setPropertyActionListener target="#{userService.reqID}" value="id"/>
which gave me an error, because the tag was sending the string "id" as opposed to the int value of the parameter.
Is there some way to force f:setPropertyActionListener to evaluate the expression under value? Or is there another tag that will allow me to do this?
Also, is ui:param used appropriately here?
The <f:param> (and <ui:param>) doesn't work that way. The <f:param> is intented to add HTTP request parameters to outcome of <h:xxxLink> and <h:xxxButton> components, and to parameterize the message format in <h:outputFormat>. The <ui:param> is intented to pass Facelet context parameters to <ui:include>, <ui:decorate> and <ui:define>. Mojarra had the bug that it also behaves like <c:set> without a scope. This is not the intented usage.
Just use <c:set> without a scope if it's absolutely necessary to "alias" a (long) EL expression.
<c:set var="id" value="#{user.id}" />
Put it outside the <h:commandLink> though. Also in this construct, it's kind of weird. It doesn't make the code better. I'd just leave out it.
<f:setPropertyActionListener ... value="#{user.id}" />
See also:
Setting ui:param conditionally
what is the scope of <ui:param> in JSF?
Defining and reusing an EL variable in JSF page
Unrelated to the concrete problem, if you're using EL 2.2 (as you're using JSF 2.2, you undoubtedly are as it requires a minimum of Servlet 3.0, which goes hand in hand with EL 2.2), then just pass it as bean action method argument without <f:setPropertyActionListener> mess. See also a.o. Invoke direct methods or methods with arguments / variables / parameters in EL and How can I pass selected row to commandLink inside dataTable?
<h:commandButton ... action="#{userService.toUserInfo(user.id)}">
On again another unrelated note, such a "View user" or "Edit user" request is usually idempotent. You'd better use <h:link> (yes, with <f:param>) for this. See also a.o. Creating master-detail pages for entities, how to link them and which bean scope to choose and How to navigate in JSF? How to make URL reflect current page (and not previous one).
Oh, that <h:panelGrid> around the <ui:repeat><li> doesn't make sense in HTML perspective. Get rid of it and use <ul> instead. See also HTMLDog HTML Beginner tutorial.

Setting Managed Bean attribute's value from JSF page and using it in bean's methods

I have a ViewScoped Managed Bean. In my .xhtml page I want to set bean's attribute's value and use it in methods in the same bean.
I managed to set the value from jsf page, but when i want to use it in some method the value of an attribute is not the value i have set before.
Description (xhtml):
In this form there is a command link which sets the value of an attribute. And it is working fine. Also, as command link is clicked, second form is being showed.
<h:form>
<h:commandLink value="Set" >
<f:setPropertyActionListener target="#{bean.attribute}" value="true" />
<f:ajax execute="#this" />
</h:commandLink>
</h:form>
This form executes method that uses attribute's value set before, but the value is not true, its false.
<h:form>
<h:commandButton id="submit" value="Execute" action="#{bean.execute}" />
</h:form>
Bean:
public void execute(){
if(isAttribute())
---do something---
}
The question is: Why execute() is not reading attribute's value right?
When I use one form, it's working fine. But I need them to be in separated forms.
The scope of your bean is incorrect. ViewScoped means that the minute the view is changed, the bean is discarded and re-created for the next view. So, in your case, the original data you had for the first view is lost.
I'm going to refer you to BalusC's blog:
http://balusc.blogspot.co.uk/2010/06/benefits-and-pitfalls-of-viewscoped.html
which states:
A #ViewScoped bean will live as long as you're submitting the form to the same view again and again. In other words, as long as when the action method(s) returns null or even void, the bean will be there in the next request. Once you navigate to a different view, then the bean will be trashed
I can't determine of you stay on the same page with both requests. If you do, viewScope should work even in two different forms. If you are navigating from 1 view to another, another viewScope will be created and you will loose the current one.
You could set the value in the sessionScope with java or by annotating the backingNean. But then everything in your backingBean becomes sessionScoped and that might not be needed.
You could also use a spring-like flow scope.
Example to do it with java:
public void callThisAfterFirstClick() {
Faces.setSessionAttribute(attribute, true)
}
public void callThisAfterSecondClick() {
Faces.getSessionAttribute(attribute);
}

commandLink is not fired in a page with a param in its URI

When I call a method in a page with a param in its URI, the method is not invoked unless I pass the parameters of the uri again. For example if I have:
http://maywebsite/myapp/mypage.xhtml?mykey=myvalue
This method results in error (obviously because it renders the page again without params, but the method foo is never invoked):
<h:commandLink value="Do Action" actionListener="#{mybean.foo}"/>
So I added an ajax to only update the component, but the button is not getting fired:
<h:commandLink value="Do Action" actionListener="#{mybean.foo}">
<f:ajax render="somecomponent"/>
</h:commandLink>
When I passed the param values again, the button invokes the method just fine:
<h:commandLink value="Do Action" actionListener="#{mybean.foo}">
<f:param name="mykey" value="myvalue"/>
<f:ajax render="somecomponent"/>
</h:commandLink>
However, this button is included (ui:include) in many pages with different param keys and values. How can I invoke the method without passing the param values?
Im using glassfish 3.1.2, jsf 2.0
Apparently the bean is request scoped and the parameter plays a role in the way how the command link is rendered (e.g. by the rendered attribute on one of its parent components, or by a dynamic include of the template containing the command link).
All those conditions are namely re-evaluated during apply request values phase of the form submit. The developer has to make sure that all those conditions are exactly the same as when the form was presented to the enduser. So, when the bean is request scoped and the parameter is absent, then the command link appears as non-rendered in the component tree and this way its action won't be invoked.
Putting the bean in the view scope is the easiest way to fix this (unless you're using a dynamic <ui:include>, this is then more complicated, you'd need to turn off partial state saving for the particular view).
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5

<ui:include> with dynamic src does not invoke setters on backingbean

I have a first.jsf in which I include second.xhtml in the following way:
<ui:include src="#{firstBean.srcForSecond}" />
This works fine and renders the contents of second.jsf. I included it using EL as the included content changes based on some conditions.
My second.xhtml contains a simple input text box:
<h:inputText id="firstname" value="#{secondBean.firstName}" />
When I load the page the value for firstname is rendered properly. However, when I change the value in the text box and submit, the setter on the backing bean is never invoked.
However if I change the ui:include in the following way, it works:
<ui:include src="second.xhtml" />
But, I require to use EL expression as it could be second.xhtml or third.xhtml based on some conditions.
Can anybody explain whats going on and how to fix it?
You need to make the #{firstBean} a #ViewScoped bean instead of a #RequestScoped one. This way you ensure that #{firstBean.srcForSecond} evaluates the same in the subsequent request. It's namely re-evaluated during apply request values phase of the form submit. If it evaluates differently, then the originally included components can't be located and nothing will be set/invoked.

What is the JSF behaviour, if you bind the same backing bean property to two input fields in the same form?

Is there a defined behaviour in JSF, if two input fields are bound to the same session scoped Backing Bean property.
Here is my code snippet
<h:form id="myForm">
<h:inputText id="field1" value="#{TheBackingBean.theProperty}" />
<h:inputText id="field2" value="#{TheBackingBean.theProperty}" />
<h:commandButton id="continueButton" action="#{TheBackingBean.doSomething}" />
</h:form>
My question: If field1 and field2 receive different values, what will be bound to the backing bean property? Is this even allowed?
I know this is a crude scenario. My motivation is, that we have htmlunit tests running for our application. In our JSF application we want to use a cool ajaxified custom component. This doesnt work together very well with htmlunit. So my idea was, I just put in a hidden field that binds to the same property. The unit test then fills the hidden field instead of the "real" thing.
Regards
I think this kind of code is allowed, but I am not sure of the value of theProperty after the submission. What I think is that JSF will do the following:
TheBackingBean.setTheProperty(field1.value);
TheBackingBean.setTheProperty(field2.value);
However, nothing - as far as I know - specifies the order of the setter calls. Thus, after the update values JSF phase, you will not be sure if theProperty will be equal to field1.value or field2.value.
Concerning your scenario, you say that you want to bind the same property to an inputText and an hiddenText. As the hiddenText will not submit its value, unlike the inputText, this problem will not occur. Indeed, if you have this kind of JSF code:
<h:inputText id="field1" value="#{TheBackingBean.theProperty}"/>
<h:inputHidden id="field2" value="#{TheBackingBean.theProperty}"/>
then JSF will only do:
TheBackingBean.setTheProperty(field1.value);
during the submission phase.

Resources