You are right. I am using it inside datatable.
Then this can happen if the #{bean}
represents the currently iterated object as declared in var
attribute like so:
<h:dataTable value="#{someBean.beans}" var="bean">
<h:column>
<h:outputText id="#{bean.id}" value="#{bean.value}" />
The id
(and binding
) attribute of a JSF component is evaluated during view build time, that moment when the JSF component tree needs to be composed. However, the #{bean}
is only available during view render time, that moment when <h:dataTable>
needs to iterate over all objects and generate HTML table rows for each of them. The #{bean}
is thus not available during view build time and evaluates to null
which ultimately gets EL-coerced to an empty string. And hence the exception java.lang.IllegalArgumentException: Empty id attribute is not allowed
.
You've basically 3 options:
Use a view build time tag instead to iterate over a collection. You'd only need to write all HTML boilerplate yourself:
<table>
<c:forEach items="#{someBean.beans}" var="bean">
<tr>
<td>
<h:outputText id="#{bean.id}" value="#{bean.value}" />
Use a plain HTML element:
<h:dataTable value="#{someBean.beans}" var="bean">
<h:column>
<span id="#{bean.id}">#{bean.value}</span>
Don't set a dynamic ID, but a fixed ID. JSF will ensure of uniqueness in HTML output by prepending it with row index of the table:
<h:dataTable value="#{someBean.beans}" var="bean">
<h:column>
<h:outputText id="id" value="#{bean.value}" />
See also: