How ManagedBeans figure out to which facelet or xhtml file they belong? - jsf

In JSF, I wonder how a ManagedBean understands that it should be available to an xhtml or facelet ?

To bind component values and objects to managed bean properties or to reference managed bean methods from component tags, page authors should use the Expression Language syntax.
When user make request to the page that contains EL, that refers to specific manage bean, this bean will be instantiated by JSF framework (except managed beans that have attribute eager="true", that means that managed bean is created before it is requested for the first time).
So the fact is that managed bean will be instantiated by JSF container and works as a model for the appropriate UI Component so the Facelet will know about the Bean, not vice versa

Related

Saving a Composite Component bean attribute in ViewScoped

I would like some technique/pattern advice on retaining each single bean I bind to my Composite Components.
I am adding composite components to a form pragmatically based on user actions, and when the user is finished I want to harvest the single bean behind each composite component they added. Ex: If user selects & adds 4 composite components, that's one bean for each, so when the user is finished I want the 4 beans with the user's entered values.
This seems a bit hairy in the JSF world, but I continue to dig through stackoverflow and experiment. I'm relatively new to JSF details, but having fun.
I've got the composite components loading, each being given a bean to be used as "cc.attrs.bean" and it properly adds the control to the form. Here is what I am currently doing and what I expected:
Load Composite Component
Instantiate its Bean
Save Bean reference in a separate list in a ViewScoped bean (my hook to the bean for later)
Give Bean to Composite Component (as an attribute)
Add Composite Component to form
...User interacts with form and Composite Components adding/editing values...
User finally pushes "Done" (now I need the modified beans).
Thought I could get all the user's values from the "separate list in a ViewScoped bean" from #3 above.
My preliminary experiments tell me that if I instantiate the bean, save the bean reference in a separate ViewScoped list then give the bean to the Composite Component, the bean I saved won't have the Composite Component's values. Between all the build/render phases it seems to lose the connection between the bean I saved and the bean the Composite Component is bound to.
I don't know if I should be following this path, or if I should use a FacesComponent event technique to intercept the bean attribute being passed along, or if I should be using filters, or maybe even magical pixie dust etc...
This seemed promising: I already wrap each of my user selectable Composite Components in a single common Wrapper Composite Component (lets me put a nice PrimeFaces collapsible panel frame around them). For example, I put "Composite Component A" into "Wrapper", then I add "Wrapper" to the form. If I passed the single bean as an attribute to both those Composite Components, I was hoping that the FacesComponent event "init" technique on the Wrapper could nicely capture the "real bound bean" in my separate list in the ViewScoped bean. In my attempts on this today I'm having trouble finding the right event type and getting access to the bean... and getting lots of strange errors (probably due to my lack of detailed understanding of the lifecycle).
Stack: Eclipse Mars, JSF 2.2, Mojarra 2.2, Tomcat 8.0

JSF Managed bean and managed property both necessary?

I'm new to JSF and was wondering:
If I have a controller that handles all the work for a given page and a bean that holds all the data for said page, is It necessary to have both the
#ManagedProperty(value="#{myBean}")
annotation on the controller and the
#ManagedBean(name="myBean")
#SessionScoped
annotations on the form bean?
Managed beans in JSF are used to store the state of a web page. The JSF implementation is responsible for creating and discarding the bean objects( hence the name managed bean).
For every class you write #ManagedBean, the bean object is created by the JSF implementation as and when it detects an usage of the bean with the name(you can either sepcify a bean name or leave it to JSF to use the default name-class name with the first character changed to lowercase). The object created is placed in a map of the specified scope. Each scope has a map that it uses to store bean objects which have that scope specified.
Now if you need the values of these beans in your controller, you have to inject it using the ManagedProperty annotation. Note that you would need to provide the controller with a setter method for the managedProperty.
So to answer your question, the managedBean annotation is required to tell the JSF implementation to manage the bean instance and store the values in the table specific to the session scope. And the ManagedProperty annotation is needed to use that bean stored in the current session so that you can access all of its values.
We use #ManagedBean annotation to register a java bean with a JSF framework. This is a replacement for a faces-config.xml <managed-bean> element. We typically do not use name attribute because it already defaults to a simple class name camel cased.
We use #RequestScope and other scope annotations to explicitly specify the scope we want via annotation. This is equivalent to specifying<managed-bean-scope> xml entry. If you don't specify the scope it will be defaulted to #NoneScoped.
We use #ManagedProperty and specify an EL-expression in its value attribute to use JSF-provided dependency injection engine for JSF artifacts like other managed beans with broader scopes and EL-defined variables like param. We do it in case we need the injected values in other JSF artifacts, most typically beans. The injected values are available in bean's #PostConstruct-annotated method. This is an alternative to <managed-property> xml entry.
To sum it up. Use #ManagedBean #RequestScoped to register a bean with JSF framework. Use #ManagedProperty inside this bean to be able to reference among others other JSF beans with the same or broader scopes in this bean. In case you don't need to reference other beans in the created bean you don't need to use the #ManagedProperty annotation as it's purely optional.

View-scoped bean recreated on POST when URL parameters not used

I have a view-scoped JSF-managed bean that's backing an xhtml view where I read one parameter from the URL using f:viewParam.
The view presents a form to the user. However, when the user submits the form by pressing the p:commandButton it seems that the view-scoped bean is recreated (I added a #PostConstruct annotation to verify this) and so doesn't remember the instance variable read from the f:viewParam (invId in the code below).
I originally navigate to the view with a GET that includes a URL parameter but the POST message that's send when the user presses the p:commandButton doesn't include the URL parameter. So I am thinking that when the JSF runtime doesn't see the URL parameter on the POST it considers this to be a different view and is recreating the JSF-managed bean. When I change the view scope to session-scoped the code works.
Here's the code:
view
<f:metadata>
<f:viewParam name="invId" value="#{registerBean.invId}"/>
</f:metadata>
<h:form id="registrationForm">
....
<p:commandButton value="register" action="#{registerBean.register}"
icon="ui-icon ui-icon-newwin" ajax="false"/>
</h:form>
backing bean
#ManagedBean
#ViewScoped
public class RegisterBean implements Serializable {
#ManagedProperty(value="#{invId}")
private String invId;
...
update
It turns out that this wasn't related to the URL parameters at all. Following BalusC advice below I removed the c:when tags my view was using (relying on rendered attributes instead for the same effect), and now the view-scoped bean is no longer recreated and the invId field is properly retained.
The problem is not visible in the code posted so far, but it's for JSF 2.0/2.1 a known issue that a view scoped bean will be recreated when one of its properties is been bound to an attribute of a taghandler like JSTL <c:if> or Facelets <ui:include> or a view build time attribute of JSF component, such as id and binding, while partial state saving is enabled (as by default).
The background explanation is that any EL expressions in those attributes are executed during building and restoring the view. As view scoped beans are stored in the view and thus only available after restoring the view, such an EL expression evaluation would cause a brand new and separate view scoped bean to be created. This is basically a chicken-egg issue. It's fixed in the upcoming JSF 2.2.
There are basically 3 solutions:
Change the view accordingly so that those EL expressions are only evaluated during view render time. E.g. replace <c:if>/<c:choose> by rendered.
Or bind those attributes to a request scoped bean (design notice: you can just inject a view scoped bean as a managed property of a request scoped bean).
Turn off partial state saving, if necessary only for the particular view.
See also:
JSTL in JSF2 Facelets... makes sense?
#ViewScoped fails in taghandlers

bean and jsf validation annotation inisde managed bean vs entity bean

I'm new in JSF and not sure about a few fundamental issues.
I found i few ways for defining validation for my input fields, but i'm not sure which is the right way to do it.
I'm using bean validation and jsf validation by using ExtVal.
should I use the validation annotation like #Size , #Length inside my entity bean, or should it be inside the managed bean? what is the diffrence for each option?
This question leads me to a more basic one , that I still don't really understand -
I have an entity bean with fields and their setters and getters, also I have a managed bean and a xhtml file with a form that displays the fileds inside inputs.
should I define the same fields with their getters and setters inside the managed bean? and when approaching them from the xhtml file I do it by MBname.FiledName ? or is it better not to create the fields again in the managed bean and approch them from the xhtml by calling MBname.details.FiledName (when details return the object) ?
again what is the diffrence for each approch?
Thank's In Advance.
should I use the validation annotation like #Size , #Length inside my entity bean, or should it be inside the managed bean? what is the diffrence for each option?
Depends on the concrete functional requirement. Key point is: how reuseable should the validation be? If configured at entity level, it's reuseable for all frameworks other than JSF. If configured at JSF level, it's not reuseable for frameworks other than JSF which happen to use the same entity.
should I define the same fields with their getters and setters inside the managed bean? and when approaching them from the xhtml file I do it by MBname.FiledName ? or is it better not to create the fields again in the managed bean and approch them from the xhtml by calling MBname.details.FiledName (when details return the object) ? again what is the diffrence for each approch?
You should not duplicate/expand the data model in the controller. This makes no sense. This is not DRY and is thus only maintenance headache.

Difference between Apply Request Values and Update Model Values

I often get doubt on these two phases. The following is my understanding:
Apply Request Values
In this phase, the submitted values are coming from the request parameter. Then the request values are set into the backing bean ie.setting to components UIInput
Update Model Values
In this phase, processed values are transferred from backing bean (UIInput) to managed beans. (It is our custom defined JSF beans).
I am thinking that my understanding is correct. But, reading few articles made me confused. I want to make me more clear on these two phases. Please clarify me.
Apply Request Values
In this phase, the submitted values are coming from the request parameter. Then the request values are set into the backing bean ie.setting to components UIInput
That's not entirely correct. The values are not set into backing beans. They are set into components. Basically the following happens for each UIInput component in the component tree:
input.setSubmittedValue(request.getParameter(input.getClientId()));
Here input is UIInput and request is HttpServletRequest.
Update Model Values
In this phase, processed values are transferred from backing bean (UIInput) to managed beans. (It is our custom defined JSF beans).
Also not entirely correct. UIInput components are not backing beans. Basically the following happens for each UIInput component in the component tree:
bean.setProperty(input.getValue());
Here, the bean and property is based on the input's valuebinding, e.g. value="#{bean.property}".
All with all, your confusion is clearly in distinguishing between the JSF component tree, the JSF backing beans and the JSF managed beans. The JSF component tree is the one which you've definied in the JSP/Facelets page and as you can obtain by FacesContext#getViewRoot(). The JSF backing beans are Javabean classes whose properties are bound to the component tree using EL such as #{bean.property}. The JSF managed beans are concrete instances of those Javabean classes. They can be request, session or application scoped (and in JSF 2.0 also view scoped). It are the managed beans where the values are actually been set and retrieved.
See also
Debug JSF lifecycle

Resources