I created a simple HtmlInputText
<h:inputText binding="#{IndexBean.objUIInput}" />
Then in my managed bean, it is :-
private UIInput objUIInput;
public UIInput getObjUIInput() {
objUIInput.setValue("laala");
return objUIInput;
}
public void setObjUIInput(UIInput objUIInput) {
System.out.println("Set!!");
this.objUIInput = objUIInput;
}
But i always get NullpointerException. Do i need to do anything extra on my JSF page? like we do jsp:usebean setproperty? Please help me.
Whenever you'd like to change the component's default state/behaviour prior to display, then you need to instantiate it yourself. I.e. during declaration:
private UIInput objUIInput = new HtmlInputText();
or during construction:
public Bean() {
this.objUIInput = new HtmlInputText();
}
or, as Bozho suggested, using #PostConstruct:
#PostConstruct
public void init() {
this.objUIInput = new HtmlInputText();
}
(which will take place after construction of the bean and initialization/setting of all managed properties).
And indeed, you should preferably not do any business logic in getters/setters. They are to be used to access bean properties and they can be called more than once during bean's life.
As per the comments, you can alternatively also move the UIInput#setValue() call to the setter method. JSF will call it once directly after precreating the component.
public void setObjUIInput(UIInput objUIInput) {
this.objUIInput = objUIInput;
this.objUIInput.setValue("laala");
}
When you bind a component, the getter and setter are supposed to be simple - only get/set - no logic inside them.
Perhaps the JSF lifecycle is calling the getter to check whether it needs to instantiate the component, and the getter initially would throw a NPE.
Remove all logic from your getter, or at least add a null check.
Actually, I'd advice for not using binding at all.
If you want to set an initial value to your component, use a method annotated with #PostConstruct and assign the value there, then use the value attribute.
Related
I'm trying to understand the working principles of UIInput component and EL-expressions in JSF. Here is the code fragment of UIInput component source code:
public void updateModel(FacesContext context) {
if (context == null) {
throw new NullPointerException();
}
if (!isValid() || !isLocalValueSet()) {
return;
}
ValueExpression ve = getValueExpression("value");
if (ve != null) {
Throwable caught = null;
FacesMessage message = null;
try {
ve.setValue(context.getELContext(), getLocalValue()); //1
setValue(null);
setLocalValueSet(false);
}
//catch clause
Now, I have a simple bean and the input component binded to its property:
<h:inputText value="#{myBean.hello}" />
#ManagedBean
#SessionScoped
public class MyBean{
private String hello;
//getter,setter
}
As far as I understand, the updateModel method is called by the inherited from the UIComponentBase class processUpdates(FacesContext) method which is a standard callback for the Update Model Values phase. So, after setting breakpoint at //1 and performing step next the flow's stopped at the corresponding bean property setter method.
My question is about of purpose of javax.el.ValueExpression. Is it resposible for all interatctions (incapsulates) between the component class and the bean's property in order for getting/setting values to bean's properties?
EL is like a "path" and is needed to navigate the bean. The UIInput is the MVC "view" to the MVC "model" represented by your bean. EL links the two together. It only encapsulates the traversal itself. It identifies the subject of the interaction, but the interactions are defined by the component class. Compare h:outputText to h:inputText: both basically take a value="#{some.el}" attribute; the fact that one allows the user to modify it is a fact about the component, not the path to the bean property itself.
Some components define attributes that should be populated by references to methods rather than bean properties, but again, the EL is just the traversal—invoking those methods is something the component does. And in that case you would be dealing with a MethodExpression instead of a ValueExpression.
The JSF lifecycle dictates that things happen in a certain overall order, but the component author still has ample opportunity to be creative (or wreak havoc) by doing things their own way.
Imagine this situation:
I have a SessionScoped bean (named TheSessionBean) that is a ManagedProperty of another bean (named AnotherBean).
#ManagedBean
#ViewScoped
public class AnotherBean implements Serializable {
#PostConstruct
public void init() {
//Evaluate here!
}
#ManagedProperty(value = "#{theSessionBean}")
private TheSessionBean theSessionBean;
//Getter and Setter...
}
I need to evaluate the value of the ManagedProperty (theSessionBean) in order to know if a page can be showed without the user interaction and before the page is shown.
As I understand this must be evaluated in the PostConstruct method (so I can get the value of the Session of the ManagedProperty).
TheSessionBean has only a String property named permission.
So first of all I need to know if:
theSessionBean.getPermission() == null in order to redirect to a page named one
theSessionBean.getPermission().equals("two") in order to redirect to a page named two
More evaluations...
The problem is that the PostConstruct method must be void and I need to redirect to the corresponding page.
How can I do that?
You can use ExternalContext.redirect in your PostConstruct method.
if (someCondition)) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/one");
}
Best practice is to use JSF system events- PreRenderViewEvent PostConstructApplicationEvent PreDestroyApplicationEvent
JSF events
What is the difference between using value and binding with JavaServer Faces, and when would you use one as opposed to the other? To make it clearer what my question is, a couple of simple examples are given here.
Normally with JSF in the XHTML code you would use "value" as here:
<h:form>
<h:inputText value="#{hello.inputText}"/>
<h:commandButton value="Click Me!" action="#{hello.action}"/>
<h:outputText value="#{hello.outputText}"/>
</h:form>
Then the bean is:
// Imports
#ManagedBean(name="hello")
#RequestScoped
public class Hello implements Serializable {
private String inputText;
private String outputText;
public void setInputText(String inputText) {
this.inputText = inputText;
}
public String getInputText() {
return inputText;
}
// Other getters and setters etc.
// Other methods etc.
public String action() {
// Do other things
return "success";
}
}
However, when using "binding", the XHTML code is:
<h:form>
<h:inputText binding="#{backing_hello.inputText}"/>
<h:commandButton value="Click Me!" action="#{backing_hello.action}"/>
<h:outputText value="Hello!" binding="#{backing_hello.outputText}"/>
</h:form>
and the correspondibg bean is called a backing bean, and is here:
// Imports
#ManagedBean(name="backing_hello")
#RequestScoped
public class Hello implements Serializable {
private HtmlInputText inputText;
private HtmlOutputText outputText;
public void setInputText(HtmlInputText inputText) {
this.inputText = inputText;
}
public HtmlInputText getInputText() {
return inputText;
}
// Other getters and setters etc.
// Other methods etc.
public String action() {
// Do other things
return "success";
}
}
What practical differences are there between the two systems, and when would you use a backing bean rather than a regular bean? Is it possible to use both?
I have been confused about this for some time, and would most appreciate having this cleared up.
value attribute represents the value of the component. It is the text that you see inside your text box when you open the page in browser.
binding attribute is used to bind your component to a bean property. For an example in your code your inputText component is bound to the bean like this.
#{backing_hello.inputText}`
It means that you can access the whole component and all its properties in your code as a UIComponent object. You can do lot of works with the component because now it is available in your java code.
For an example you can change its style like this.
public HtmlInputText getInputText() {
inputText.setStyle("color:red");
return inputText;
}
Or simply to disable the component according to a bean property
if(someBoolean) {
inputText.setDisabled(true);
}
and so on....
Sometimes we don't really need to apply the value of UIComponent to a bean property. For example you might need to access the UIComponent and work with it without applying its value to the model property. In such cases it's good to use a backing bean rather than a regular bean. On the other hand in some situations we might need to work with the values of the UIComponent without any need of programmatic access to them. In this case you can just go with the regular beans.
So, the rule is that use a backing bean only when you need programmatic access to the components declared in the view. In other cases use the regular beans.
I have a navigation managed bean for each user.
and I need it to initialize first before any other bean because a value is required from the bean.
May I know how do I perform that?
I have tried eager="true" but it doesn't work.
any quick and easy solution via faceconfig would be greatly appreciated.
Just perform the desired initialization job in bean's #PostConstruct.
#PostConstruct
public void init() {
// Here.
}
It'll be invoked when the bean is injected/referenced from another bean for the first time.
The eager=true works only on application scoped beans.
From what I see you should reference the other bean. Let's assume a have a utility class that can pull a bean from the context.
Basically ->
//Bean A
public void doSomething()
{
String required = Utility.getBeanB().getRequiredValue();
use(required);
}
...
//Bean B
public String getRequiredValue()
{
return "Hi, I'm a required value";
}
I have several large web apps that have a "Session Bean" that stores stuff like user preferences, shared objects etc... and this method works perfectly. By using a reference to the bean you eliminate the need to chain the initialization. That method will always DEPEND on the method in the other bean, thus guaranteeing the order of initialization.
There's a variety of ways to access the bean but I usually go through the EL route ->
Get JSF managed bean by name in any Servlet related class
Best of luck, I try to stay "functionally pure" when I can--and I hope that get's a laugh considering the language!
Here's some cool hax for ya, in case other solutions aren't working for you due to various circumstances...
Let's say I have a class Alpha that I want initialized first:
public class Alpha {
#PostConstruct
public void init() {
}
}
I can put the following method in Alpha:
#ManagedBean(name = "Alpha", eager = true)
public class Alpha {
public static void requireAlpha() {
FacesContext context = FacesContext.getCurrentInstance();
Object alpha = context.getApplication().evaluateExpressionGet(context, "#{Alpha}", Object.class);
System.out.println("Alpha required: " + alpha.toString());
}
#PostConstruct
public void init() {
}
}
Then, in any classes that are initializing too early, simply call:
Alpha.requireAlpha();
// ...
// (Code that requires Alpha to be initialized first.)
And if there's a ChildAlpha class that extends Alpha that you really want to be initialized (rather than the parent), make sure to use "ChildAlpha" instead, in both the name="" and the EL Expression ("#{}").
See here for more infos: Get JSF managed bean by name in any Servlet related class
I'm looking for some piece of code for setting a property in a JSF managed bean. My first idea was something like that:
<c:set var="#{loginBean.device}" value="mobil"></c:set>
That means I want to set the attribute device to the value "mobil" without a button have to been clicked.
Yes, you can use c:set for this purpose.
<c:set value="mobil" target="#{loginBean}" property="device" />
Doc: http://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/pdldocs/facelets/c/set.html
However, setting a static value rarely makes sense. You might consider to set a default value directly in your managed bean class. Also in terms of maintainability since you can handle constants better in the Java code than in the view layer.
I think you want the JSF tag child tag setPropertyActionListener. You can set this as a child tag in any ActionComponent.
<h:anyActionComponent id="component1">
<f:setPropertyActionListener target="#{loginBean.device}" value="mobil" />
</h:anyActionComponent>
UPDATE:
I originally misunderstood the users problem. They have a page, and they want a property to be set when the page loads. There is a couple ways to do this, but both are a little different. If you want to set a property to a value after every postback then you can use the #PostConstruct annotation on a ManagedBean method.
#PostConstruct
public void initializeStuff() {
this.device = "mobil";
}
Now if I have a ViewScoped or SessionScope bean that needs to be initialized with a default value just once when the page loads then you can set a phase lifecycle event that will run after every postback and check to see if the page should be initialized or not.
mah.xhmtl:
<f:event listener="#{loginBean.initialize()}" type="preRenderView" />
LoginBean:
public void initialize() {
if (this.device == null)
this.device = "mobil";
}
I am not able to Comment: If you need the value to be ready on page on load, you could use Managed Bean to directly initialize value or use its constructor or #PostConstruct to do the same.
#ManagedBean
#ResquestScoped
public class LoginBean {
private String device = "some value";
//Using Constructor
public LoginBean() {
device = getvalueFromSomewhere();
}
//Using PostConstruct
#PostConstruct
public void init() {
device = getvalueFromSomewhere();
}
}
Instead of setting the value in the xhtml file you can set via another ManagedBean. For instance if you have managedBean1 which manages page1.xhtml and managedBean2 which manages page2.xhtml. If page1.xhtml includes page2.xhtml like:
<ui:include src="page2.xhtml"/>
in managedBean1 you can have at the top
#ManagedProperty(value = "#{managedBean2}")
private ManagedBean2 managedBean2;
and in the PostConstruct
#PostConstruct
public void construct() {
managedBean2.setProperty(...);
}
worked for me anyway...