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}
.
#{hello.name}
will receive the value, returned by Hello.getName()
method.Hello.setName(param)
will be called with param
equals to value
of element, bound to #{hello.name}
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
@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:
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:
UIViewRoot
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:
Hello.java
, instantiating it and gives to FacesServlet.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
.<input>
without value
to response and on index.xhtml you see an empty input....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).
...has <h3>Hello, #{hello.name}</h3>
, so, again, FacesServlet must resolve it as described earlier.
But in current request the Hello
have 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.
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
)