Attribute "var" invalid for tag selectItems according to TLD - jsf

I'm working with h:selectOneMenu and want to set label and value for it then the UI option list will display label and in my Bean can get the selected value. I have this code working fine:
<h:selectOneMenu value="#{myBean.selected}">
<f:selectItems value="#{myBean.myList}"/>
</h:selectOneMenu>
But problem appear when I try to add var to set label and value by adding the code below:
<h:selectOneMenu value="#{myBean.selected}">
<f:selectItems value="#{myBean.myList}" var="field"
itemLabel="#{field.label}" itemValue="#{field.value}"/>
</h:selectOneMenu>
The error show Attribute var invalid for tag selectItems according to TLD.
My question are:
Can I resolve this?
If "YES" then "HOW"?
If "NO" then any other way for me to done this?
Thanks

Attribute var invalid for tag selectItems according to TLD
The <f:selectItems var> attribute was introduced in JSF 2.0 for Facelets. This error suggests either you're using legacy JSF 1.x instead of the newer JSF 2.x where <f:selectItems> lacks the var attribute, or you're using legacy JSP instead of its successor Facelets as JSP is deprecated since JSF 2.0 and didn't get any of new JSF 2.0 tags/attributes. The exact error message is due to the JSP-specific term "TLD" however recognizable to come from JSP parser, which in turn confirms more that you're actually using JSP instead of Facelets.
In order to use <f:selectItems var>, you need to make sure of the following:
You're using JSF 2.x instead of JSF 1.x.
You're using Facelets instead of JSP.
If you can't upgrade/migrate, then you need to fall back to legacy SelectItem approach in backing bean. You can convert from your List<Field> to a List<SelectItem> as below:
private List<Field> fields;
private List<SelectItem> selectItems; // +getter
#PostConstruct
public void init() {
fields = yourFieldService.list();
selectItems = new ArrayList<>();
for (Field field : fields) {
selectItems.add(new SelectItem(field.getValue(), field.getLabel()));
}
}
<f:selectItems value="#{bean.selectItems}" />
See also:
Migrating from JSF 1.2 to JSF 2.0
Why Facelets is preferred over JSP as the view definition language from JSF2.0 onwards?
Our selectOneMenu wiki page

Related

JSF 2.2: Passing bean attribute as ValueExpression to composite

I want to pass a non-managed (non-String) object as an attribute on a dynamically added composite component, and have it survive the session.
The JSF 2.2 ViewDeclarationLanguage#createComponent handles dynamic non-string attribute values to composite components differently than the older Mojarra dependent code (Application#createComponent). I can't find the approach that works completely with the JSF 2.2 technique, but it's probably me.
[I'm trying to remove Mojarra dependencies by converting to MyFaces (and also working around some other Mojarra issues). I'm using JSF 2.2, CDI Weld 2.2.16, Tomcat v8.0]
I'm instantiating different composite components like these programmatically (notice the bean attribute):
<cc:interface>
<cc:attribute name="bean" required="true" type="com.aadhoc.cvc.spikes.extensionsapproach.ExtensionBeanInterface"/>
</cc:interface>
<cc:implementation>
<h:panelGrid columns="2">
<h:outputText value="Title:"/>
<h:inputText value="#{cc.attrs.bean.title}"/>
</h:panelGrid>
</cc:implementation>
In the older Mojarra dependent approach, I instantiate the non-managed bean object, and add it directly to the composite component as an attribute and it works great (I'm using #BalusC's great but Mojarra dependent sample code from OmniFaces Component#includeCompositeComponent):
ExtensionBeanInterface bean = Class.forName(className).newInstance();
attributes = new HashMap<String, Object>();
attributes.put("bean", bean); // Using bean object itself
[..]
UIComponent composite = application.createComponent(context, resource);
composite.getAttributes().putAll(attributes);
[..]
In JSF 2.2, I've found that I must pass a String ValueExpression instead of my bean object directly. I'm currently using this technique, and can't get it quite right:
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
ValueExpression beanValExp = context.getApplication().getExpressionFactory()
.createValueExpression(elContext, "#{customBeanVE}", ExtensionBeanInterface.class);
beanValExp.setValue(elContext, bean);
String beanValExpStr = beanValExp.getExpressionString();
attributes = new HashMap<String, Object>();
attributes.put("bean", beanValExpStr); // Using VE instead of bean object
UIComponent composite = context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId())
.createComponent(context, taglibURI, tagName, attributes);
[..]
This works great on the first "add composite", but on any following form submit, I get:
/resources/com/aadhoc/cvc/spikes/extensionsapproach/components/House.xhtml
#16,49 value="#{cc.attrs.bean.title}": Target Unreachable, 'bean'
returned null
I've verified that the composite's required and type attributes are working fine, and that the #{cc.attrs.bean.title} is initially showing the bean's title. I verified with a static use of the composite component that refreshes work fine.
What's the deal, and how can I handoff the bean object so that it survives with the composite across the session?
I had this working great in Mojarra. I could put the bean object in the attribute value, and all was wonderful. Trying MyFaces, I needed to change/update my approach, and I now needed to use EL strings instead of direct object references.
Since all was working with just putting bean object into attributes Map, I wanted a magical yet elegant place to put bean objects and have them survive. I could have put them into the "global" session Map (like this: How to save an object into JSF Session), but it wasn't clean enough. I then put them into my one main session state bean (modelerBean), and it was right. This is how I saved the bean, and how I pointed to it with an EL string. No need to create ValueExpression or MethodExpression objects or register special mappings. This JSF 2.2 compatible approach worked for me in both Mojarra and MyFaces.
public void onAdd(ActionEvent ev) {
[..]
ChosenBean chosenBean = new ChosenBean();
chosenBean.setComponentId(id);
chosenBean.setBean(bean);
modelerBean.addChosen(chosenBean);
[..]
String el = "#{modelerBean.getChosen('"+id+"').bean}"
attributes.put(MODELER_EXTENSION_BEAN_ATTRIBUTE_NAME, el);
[..]
I decided on this after reading #BalusC's post: How do I get and set an object in session scope in JSF?
Note, my experience with #BalusC's two "add composites dynamically" approaches (How to programmatically or dynamically create a composite component in JSF 2) is that you should definitely use the JSF 2.2 approach if you can. The old Mojarra approach does work if you aren't in JSF 2.2. Once I modified my code to have the JSF 2.2 approach work, the old Mojarra approach would break in strange ways.

Primefaces Binding Page attributes

I'm new for Primefaces .Now I'm migrating RichFaces to Primefaces 5.1. In RichFaces every form has binding initForm to bind Page Attributes.In same form binding use PrimeFaces or any other attribute to bind page attributes.
I'm use below code in Richfaces:
<f:subview id="testSubView">
<h:form id="testForm" binding="#{test.initForm}">
........
</h:form>
<f:subview>
Test.java
public HtmlForm initForm()
{
fetchIntialPageAttributes();
return initForm
}
private void fetchIntialPageAttributes()
{
userTextbox="";
messagePanelRender=true;
userCommandButton=true;
userCommanButtonValue="save";
}
Now doubt initially bind when form load same binding attribute use in Primefaces.
Use <f:event type="postAddToView">, or perhaps <f:event type="preRenderView">, instead to trigger a managed bean listener method right after the component was added to view during view build time, or perhaps right before the view render time.
<h:form id="testForm">
<f:event type="postAddToView" listener="#{test.fetchIntialPageAttributes}" />
...
</h:form>
Do note that this all is not specific to PrimeFaces (nor RichFaces), but just to JSF itself. The binding attribute was during the JSF 1.x era actually a hack/workaround for this. That's one of reasons why JSF 2.0 added those new component system events and the <f:event> tag. An ideal JSF 2.x page does not use binding on a backing bean property anywhere.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?

How to use component binding in JSF right ? (request-scoped component in session scoped bean)

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());
}

JSF 2 enum property lost after bean validation

Using JSF2 (MyFaces 2.1) and CDI (Weld) I use a selectOneMenu filled with an enum to conditionally render a second selectOneMenu (doublemenu in the code). There are several other fields in the form which are validated using bean validation.
The problem:
If there are validation errors after clicking on the commandButton and error messages are shown, the doublemenu will not reappear. It appears that bean.type =='double' is not true. But why? The selectOneMenu itself shows the option double as the selected item.
#javax.inject.Named
#javax.enterprise.context.RequestScoped
public class Bean {
private enum MyEnum {
Single, Double
}
private MyEnum type;
public MyEnum getType() {
return type;
}
public void setType(MyEnum type) {
this.type = type;
}
public MyEnum [] getTypes() {
return MyEnum.values();
}
<h:form>
<h:selectOneMenu value="#{bean.type}">
<f:selectItems value="#{bean.types}" />
<f:ajax render="doublemenu" />
</h:selectOneMenu>
<h:panelGroup id="doublemenu">
<h:panelGroup rendered="#{bean.type == 'double'}">
<h:selectOneMenu ...>
</h:selectOneMenu>
</h:panelGroup>
</h:panelGroup>
<h:inputText id="VALIDATED"/>
<h:commandButtonaction="#{bean.save}"
</h:form>
BTW: bean.save is not executed
It's because your bean is request scoped. Request scoped beans are garbaged by end of every request and newly created on begin of every request. This also applies to individual ajax requests on the same view.
The rendered attribute is also evaluated during collecting submitted values (the apply request values phase). However, at the point the submitted values are to be collected, the #{bean.type} is obviously not been set yet (it has still to be set based on the collected submitted value during update model values phase). As your bean is request scoped, it would return the default value, not the submitted value from a previous request.
There are basically 2 ways to fix this.
Put the bean in a bit broader scope. JSF offers the #ViewScoped for exactly this purpose. This is in the current JSF 2.1 version only not compatible with CDI. If switching to JSF #ManagedBean is not an option, then you'd need MyFaces CODI to bridge the JSF #ViewScoped transparently to CDI, or to wait for JSF 2.2 to get a CDI compatible #ViewScoped out the box.
Check a request parameter instead of a bean property.
<h:selectOneMenu binding="#{type}" ...>
...
</h:selectOneMenu>
<h:panelGroup rendered="#{param[type.clientId] == 'Double'}">
Please note that this all is completely unrelated to enums. You'd have had exactly the same problem when using e.g. a String. Also please note that I fixed a typo in your code example, an enum value of Double is definitely not the same as double.
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated

JSF component binding - some confusion

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

Resources