I am learning JSF 1.2 and I have a scenario where a view "profile.jsf" is rendered using a request bean BeanProfile. The bean "BeanProfile" is a request bean because I need updated data in every request and refresh of the view. The view have a <h:commandButton/> that triggers a method in a session bean LoginBean and which should update the user profile before persisting it. So, I need to pass all the information in the profile view to the method in the session bean. I tried using the <f:attribute/> in the <h:commandButton/> like this:
<h:commandButton id="submit" actionListener="#{beanLogin.updateUser}" value="Update">
<f:attribute name="ttt" value="789"/> <!-- just for debug -->
<f:attribute name="name" value="#{name}" /> <!-- I will pass just that one for the moment -->
</h:commandButton>
and the component:
<h:inputText id="name"
binding="#{name}"
value="#{beanProfile.name}"
required="true" />
in my method i have:
public void updateUser(ActionEvent event) {
/*Debug*/
System.err.println("size: "+event.getComponent().getAttributes().size());
System.err.println("--"+(String) event.getComponent().getAttributes()
.get("ttt")+"--");;
UIInput input = (UIInput) event.getComponent().getAttributes().get("name");
String text = (String) input.getSubmittedValue();
System.err.println("++"+text+"++");
}
As a result I get:
2014-12-20T01:43:25.850+0100|Severe: size: 1
2014-12-20T01:43:25.850+0100|Severe: --789--
java.lang.NullPointerException ...
So I passed 2 parameters and I only got one in the method in the session bean and that's what caused the java.lang.NullPointerException. I don't know what i am doing wrong. I am working in Eclipse 4.4.1 SR1 using a dynamic web module 3.0 and GlassFish Server Open Source Edition 4.1 which includes Mojarra 2.2.7.
Update:
I tried the same code using tomcat 8.0.15, MyFaces 1.2.12 and JSTL 1.2 which I was already using with GlassFish and Mojarra. I have the same problem and I found that the bean injection thought the managed-property in faces-config.xml does not work either (null value) in both configurations I used.
Related
Updating to mojarra 2.3.18 following f:attribute inside a component is not send to the server on ajax request.
<f:attribute name="foo" value="#{null}"/>
Is this by design?
As a workaround i am passing value="null" now and catching this String in the bean to convert it back to null.
Mojara 2.1.21
I've updated my question based on comments. I have two situation where a component is bound to server session bean. (Additional links with information: Binding attribute causes duplicate component ID found in the view and https://stackoverflow.com/a/12512672/2692917)
Version 1:
single.xhtml:
<h:outputText value=... binding="#{mysessionbean.out}" />
java:
#SessionScoped #Named public class Mysessionbean {
UIOutput out;
//getter and setter ....
}
Version 2:
template.xhtml:
<h:outputText value=... binding="#{mysessionbean.out}"
view1.xhtml:
<ui:composition template="template.xhtml" />
view2.xhtml:
<ui:composition template="template.xhtml" />
java:
#SessionScoped #Named public class Mysessionbean {
UIOutput out;
//getter and setter ....
}
Version 1 is ok. (At least I've not encounter any errors so far). But in version 2 the duplicate id error is occured if I navigate from one page to another. Why does it happen ?
Is it safe to use (request-scoped) component (in version 1) with session scoped binding ?
Are there another use cases to consider ?
Edit:
Functional requirement 1:
I want to use Primefaces datatable in a view. I need some info from this datatable. (Such as selected row or row index). So binding the datatable helps me to retrieve this info.
Functional requirement 2:
Components binding in composite components. They will be bound to session scoped bean. (And used mainly on one page, but what if I used it on another page ?
Requirements 3
The situation as in "Version 2". Template with primefaces menu and session scoped binding. For this I've used the EL-Binding.
In JSF 2.x, unless you want to manipulate components programmatically (which is at its own also rather fishy), there is no sensible real world use case to bind components to a backing bean. For sure not if they are further not been used in the backing bean itself, or if it are solely their attributes which are been flattened out.
As to the functional requirement of getting the current row of the data table, there are much better ways listed here, How can I pass selected row to commandLink inside dataTable?, for example if your environment supports EL 2.2:
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:commandLink value="Foo" action="#{bean.foo(item)}" />
The two last requirements are totally unclear. At least, if you're doing something like:
<x:someComponent binding="#{bean.someComponent}" />
with in bean
someComponent.setSomeAttribute(someAttribute);
someComponent.setOtherAttribute(otherAttribute);
then you should instead be doing
<x:someComponent someAttribute="#{bean.someAttribute}" otherAttribute="#{bean.otherAttribute}" />
Or, if you intend to be able to use the component somewhere else in the view like so
<h:inputText ... required="#{not empty param[bean.save.clientId]}" />
...
<h:commandButton binding="#{bean.save}" ... />
and the instance is further nowhere been used in the bean, then just get rid of the unnecessary property altogether:
<h:inputText ... required="#{not empty param[save.clientId]}" />
...
<h:commandButton binding="#{save}" ... />
If there is really, really no way for some unclear reason, then split all request scoped properties of the session scoped bean out into a separate request scoped bean which you in turn bind to form actions. The session scoped one can just be injected as a #ManagedProperty of the request scoped one.
See also:
Binding attribute causes duplicate component ID found in the view
How does the 'binding' attribute work in JSF? When and how should it be used?
We ran into a similar problem and I just want to share our solution:
Problem:
In a view there was a (extended largely customized) datatable.
<x:dataTable binding="#{bean.someSomeDataTable}" />
After navigating to another page and back we wanted the datatable to have the exact same state. Previously we solved that by binding the datatable to to backing bean. This worked fine with JSPs. With Facelets we could not do that (Duplicate ID errors). So we used the binding, but only saved/restored the state of the datatable component.
public HtmlDataTable getSomeDataTable()
{
HtmlDataTable htmlDataTable = new HtmlDataTable();
if (tableState != null)
htmlDataTable.restoreState(FacesContext.getCurrentInstance(), tableState);
return htmlDataTable;
}
public void setSomeDataTable(HtmlDataTable table)
{
tableState = table.saveState(FacesContext.getCurrentInstance());
}
From web pages like this one,
http://www.jsftutorials.net/components/step5.html
I understand that the binding attribute in JSF tag/view component is to bind the view component to a Java instance of the UI component in the backing bean.
E.g., that's what is done in the following code:
<h:inputText value="#{ myBean.someProperty}" binding="#{ myBean.somePropertyInputText}"/>
But sometimes I see code like this:
<h:commandButton id="t1" binding="#{foo}" value="Hello, World!" onclick="alert('I am #{id:cid(foo)}'); return false;" />
where id:cid is a taglib function which is defined as follow:
public static String cid(UIComponent component) {
FacesContext context = FacesContext.getCurrentInstance();
return component.getClientId(context);
}
In the above code, binding="#{foo}" does not bind to "a Java instance of the UI component in the backing bean".
So what is the meaning of expressions such as binding="#{foo}" ?
It just binds the component to the current Facelet scope. This is particularly useful if you don't need it in the backing bean at all. This saves your backing bean code from useless properties which aren't been used in any of the other methods at all. Note that it also works that way in JSF 1.2. Not sure about JSF 1.0/1.1 though as it uses a different and JSF-proprietary EL API.
See also:
JSF component binding without bean property
Is it possible to call bean methods & directly pass parameters to them from the view instead of requiring to first set the bean properties and then call methods without arguments using the commandButton or similar ?
I have a list of items with each item having a list of actions. To reduce the state, I am using a single primefaces remoteCommand, in place of several commandButton(s). On getting a action trigger from the view, I would call the remoteCommand from javascript but since the remoteCommand is one but used for multiple items thus I need to pass the id of the item as well. I am wondering if there is a way to pass the id of the item to the bean method directly as an argument instead of first setting it as a bean property ? Is there any way to do so ?
Actually I am looking at a better way to deal with multiple commandButtons on a page when there's a long list of items on the page.
Suggestions ? Thanks.
Using JSF 2.1.6 Mojarra with Primefaces 3.0RC1
Passing method arguments is supported since EL 2.2 which is part of Servlet 3.0. So if your webapp runs on a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, etc) with a web.xml declared conform Servlet 3.0 spec (which is likely true as you're using JSF 2.1 which in turn implicitly requires Servlet 3.0), then you will be able to pass method arguments to bean action methods in the following form:
<h:commandButton value="Submit" action="#{bean.submit(item.id)}" />
with
public void submit(Long id) {
// ...
}
You can even pass fullworthy objects along like as:
<h:commandButton value="Submit" action="#{bean.submit(item)}" />
with
public void submit(Item item) {
// ...
}
If you were targeting a Servlet 2.5 container, then you could achieve the same by replacing the EL implementation by for example JBoss EL which supports the same construct. See also Invoke direct methods or methods with arguments / variables / parameters in EL.
Yes, it is.
<h:commandButton action="#{bean.method(object)}" />
See this http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/
You can call ManagedBean methods with arguments like this.
<h:commandButton actionListener="#{stateBean.delete(row.stateID)}"
value="Delete" id="btnDeleteS">
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>
The corresponding ManagedBean would be like this.
#ManagedBean
#RequestScoped
public class StateBean
{
#EJB
private RemoteInterface obj=null;
public void delete(String stateID)
{
//Code stuff here.
}
}
You can also directly set the value of ManagedBean properties using <f:setPropertyActionListener></f:setPropertyActionListener> like this.
<h:commandButton value="Delete" id="btnDeleteS">
<f:setPropertyActionListener target="#{stateBean.someProperty}"
value="#{someValue}"/>
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>
The <h:inputText> value is not been set in a request scoped bean. If the value is preserved from DB, it works fine.
view:
<h:inputText id="receipient" size="90" styleClass="text" readonly="#{!bean.enable}" value="#{bean.recipient}" />
bean:
public class Bean {
private String recipient;
Bean(){
recipient = //load from db
}
//set
//get
}
What is the problem and how can I solve this?
Ensure that readonly="#{!bean.enable}" evaluates the same as it was in initial view. If it evaluates true during apply request values phase of the form submit, then the component's value won't be processed (because it is marked as read only).
An easy test is to put the bean in session scope. If that fixes it, then you know the culprit. If you're using JSF 2.0, just put bean in view scope by using #ViewScoped instead of #RequestScoped. If you're still on JSF 1.x, use Tomahawk's <t:saveState> component to let the bean act like the JSF 2.0 view scoped one.
<t:saveState value="#{bean}" />