Any way to list request header names with JSF EL -- without backing bean? - jsf

Is there any way to use JSF EL (Java EE 7) to list all the request's header names and corresponding values in a 2-column table, without introducing a backing bean? I can do it if I create a bean and access that from EL, so I do have a means to the end -- but the thing I'm trying to figure out is if it can be done entirely with "out of the box" EL. "That's not possible" would be a fine answer -- I'm still learning.
I thought something like this:
<table>
<ui:repeat value="#{request.getHeaderNames()}" var="hdr">
<tr>
<td>#{hdr}</td>
<td>#{headerValues[hdr]}</td>
</tr>
</ui:repeat>
</table>
But that gives a 1-row table, something like this:
org.apache.catalina.util.Enumerator#2dbf763b [Ljava.lang.String;#74eb32f3
I suspect that because request.getHeaderNames() is giving an enumerator instead of a list of some kind that ui:repeat wants, this approach won't work at all, and I need to do something fundamentally different.

You can just iterate over #{headerValues} itself. You only need either JSTL <c:forEach>,
<dl>
<c:forEach items="#{headerValues}" var="entry">
<dt>#{entry.key}</dt>
<c:forEach items="#{entry.value}" var="headerValue">
<dd>#{headerValue}</dd>
</c:forEach>
</c:forEach>
</dl>
or to make use of EL 2.2 feature to convert Map to Entry[] as follows, as <ui:repeat> doesn't support maps but only lists and arrays:
<dl>
<ui:repeat value="#{headerValues.entrySet().toArray()}" var="entry">
<dt>#{entry.key}</dt>
<ui:repeat value="#{entry.value}" var="headerValue">
<dd>#{headerValue}</dd>
</ui:repeat>
</ui:repeat>
</dl>
Note that each value of #{headerValues} represents a String[], so I've fixed that for you as well, with a proper data structure.

Related

I can't use varStatus value to get index in p:repeat [duplicate]

I'm trying to assign an id to a component inside a <ui:repeat> like that:
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}"
styleClass="#{column.id} dashboard_column">
The thing is that #{column.id} value is being placed properly inside the styleClass value but its not being set inside the id attribute. All that is being set inside the id attribute is the automatically generated id by the JSF + my hard coded value column_.
If I remove the hard coded column_ I get an exception:
java.lang.IllegalArgumentException: component identifier must not be a zero-length String
at
Any Ideas?
This is not possible with a render-time tag such as <ui:repeat>. The <ui:repeat> will however by itself already ensure the uniqueness of the generated client ID by prepending it with the row index. So just remove the EL part from the ID attribute of the component.
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column">
With a view build time tag such as <c:forEach> (which will basically generate multiple <h:panelGroup> components instead of only one which is rendered multiple times), it is possible to specify a dynamic ID like that.
<c:forEach items="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}">
(you should only be well aware of how JSTL works in Facelets)
An alternative is to use a static <div> element instead of a JSF <h:panelGroup layout="block"> component.
<ui:repeat value="#{bean.columns}" var="column">
<div id="column_#{column.id}">
See also:
JSTL in JSF2 Facelets... makes sense?
JSF prefixes the id automatically. If you simply write id="column" the generated HTML will contain such identifiers:
myForm:0:column
myForm:1:column
myForm:2:column
and so on.
Anyway: Do never use JSTL tags (like c:foreach and c:if) in JSF templates. They cause random behaviour, very difficult to debug. And if they work, the slow down the application a lot.
Use ui:repeat for loops, and ui:fragment for conditional blocks. Note that there is no replacement for c:set, such a construct does not exist anymore in JSF 2.

Dynamic id for primefaces datatable [duplicate]

I'm trying to assign an id to a component inside a <ui:repeat> like that:
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}"
styleClass="#{column.id} dashboard_column">
The thing is that #{column.id} value is being placed properly inside the styleClass value but its not being set inside the id attribute. All that is being set inside the id attribute is the automatically generated id by the JSF + my hard coded value column_.
If I remove the hard coded column_ I get an exception:
java.lang.IllegalArgumentException: component identifier must not be a zero-length String
at
Any Ideas?
This is not possible with a render-time tag such as <ui:repeat>. The <ui:repeat> will however by itself already ensure the uniqueness of the generated client ID by prepending it with the row index. So just remove the EL part from the ID attribute of the component.
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column">
With a view build time tag such as <c:forEach> (which will basically generate multiple <h:panelGroup> components instead of only one which is rendered multiple times), it is possible to specify a dynamic ID like that.
<c:forEach items="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}">
(you should only be well aware of how JSTL works in Facelets)
An alternative is to use a static <div> element instead of a JSF <h:panelGroup layout="block"> component.
<ui:repeat value="#{bean.columns}" var="column">
<div id="column_#{column.id}">
See also:
JSTL in JSF2 Facelets... makes sense?
JSF prefixes the id automatically. If you simply write id="column" the generated HTML will contain such identifiers:
myForm:0:column
myForm:1:column
myForm:2:column
and so on.
Anyway: Do never use JSTL tags (like c:foreach and c:if) in JSF templates. They cause random behaviour, very difficult to debug. And if they work, the slow down the application a lot.
Use ui:repeat for loops, and ui:fragment for conditional blocks. Note that there is no replacement for c:set, such a construct does not exist anymore in JSF 2.

How to set a Map value in h:inputText

I'm struggling to implement a fairly trivial functionality with JSF which involves dynamically displaying the content of a nested map on a page and editing capabilities for its values. But it has turned out that the MappedValueExpression$Entry that you get when iterating over a map with c:forEach is not writable!
<c:forEach items='#{inflectionBean.word.inflectionalForms}' var="number" >
<p:fieldset legend="#{number.key}">
<c:forEach items="#{number.value}" var="case" >
<p:panel header="#{case.key}">
<h:inputText value="#{case.value}" />
</p:panel>
</c:forEach>
</p:fieldset>
</c:forEach>
When I am trying to submit the above form I'm getting:
javax.el.PropertyNotWritableException: /inflection.xhtml #39,56 value="#{case.value}": The class 'com.sun.faces.facelets.tag.jstl.core.MappedValueExpression$Entry' does not have a writable property 'value'.
I wonder if there are reasonable workarounds or if I am approaching the problem in a wrong way. Thanks!
Basically, what your code is attempting is invoking Map.Entry#setValue(value). This is indeed not possible in EL. Instead, you should be referencing the map value directly on the map itself by key, so that EL can do Map#put(key, value).
<c:forEach items="#{number.value}" var="case">
...
<h:inputText value="#{number.value[case.key]}" />

Displaying the values of a nested array list in JSF data table

Its been quite some time since i have started developing web pages using JSF but i am still learning most of the stuff. Now I have an interesting question
When I have the values those to be displayed in a data table in the ArrayList and I am adding those ArrayList objects in another array list , so now how will i be able to display them in a data table.
I am doing this since , i need my table to be so dynamic so that i dont know how many columns will i be getting in the result set to be displayed in the page, hece i cannot have a Bean obj for storing my variable values. So i have decided to have something like
ArrayList<ArrayList<String>>
ArrayList<String> - Values for Each row
Does this have a solution that can be provided int he jsf page
Use either plain HTML with a nested <ui:repeat>
<table>
<ui:repeat value="#{bean.rows}" var="row">
<tr>
<ui:repeat value="#{row}" var="column">
<td>#{column}</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
or grab a 3rd party component library which has sort of a <x:columns> tag like PrimeFaces with <p:columns> and Tomahawk with <t:columns>.
<p:dataTable value="#{bean.rows}" var="row">
<p:columns value="#{row}" var="column">
#{column}
</p:columns>
</p:dataTable>
Either way, you can even keep the columns in a separate list.

How can I set id of a component/tag inside ui:repeat

I'm trying to assign an id to a component inside a <ui:repeat> like that:
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}"
styleClass="#{column.id} dashboard_column">
The thing is that #{column.id} value is being placed properly inside the styleClass value but its not being set inside the id attribute. All that is being set inside the id attribute is the automatically generated id by the JSF + my hard coded value column_.
If I remove the hard coded column_ I get an exception:
java.lang.IllegalArgumentException: component identifier must not be a zero-length String
at
Any Ideas?
This is not possible with a render-time tag such as <ui:repeat>. The <ui:repeat> will however by itself already ensure the uniqueness of the generated client ID by prepending it with the row index. So just remove the EL part from the ID attribute of the component.
<ui:repeat value="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column">
With a view build time tag such as <c:forEach> (which will basically generate multiple <h:panelGroup> components instead of only one which is rendered multiple times), it is possible to specify a dynamic ID like that.
<c:forEach items="#{bean.columns}" var="column">
<h:panelGroup layout="block" id="column_#{column.id}">
(you should only be well aware of how JSTL works in Facelets)
An alternative is to use a static <div> element instead of a JSF <h:panelGroup layout="block"> component.
<ui:repeat value="#{bean.columns}" var="column">
<div id="column_#{column.id}">
See also:
JSTL in JSF2 Facelets... makes sense?
JSF prefixes the id automatically. If you simply write id="column" the generated HTML will contain such identifiers:
myForm:0:column
myForm:1:column
myForm:2:column
and so on.
Anyway: Do never use JSTL tags (like c:foreach and c:if) in JSF templates. They cause random behaviour, very difficult to debug. And if they work, the slow down the application a lot.
Use ui:repeat for loops, and ui:fragment for conditional blocks. Note that there is no replacement for c:set, such a construct does not exist anymore in JSF 2.

Resources