accessing native query list using ui:repeat - jsf

lets say i have a table test with columns id and name
on my bean i got this query
public List getTestList(){
Query q = em.createNativeQuery("select * from test");
List list = q.getResultList();
return list;
}
and on my jsf page i have:
<ul>
<ui:repeat id="resulta" value="#{testController.testList}" var="item">
<li>#{item.id}</li>
</ui:repeat>
</ul>
why do i get a SEVERE: javax.el.ELException: /test.xhtml: For input string: "id"

why do i get a SEVERE: javax.el.ELException: /test.xhtml: For input string: "id"
Because a native query returns a List<Object[]>, not a List<Test>. You're basically attempting to access an Object[] array using a string such as "id" as index instead of an integer such as 0. If you look closer to the stack trace, then you should have noticed the presence of ArrayELResolver a little further in the stack after the exception, which should already have hinted that #{item} is actually been interpreted as an array.
So, if you absolutely can't obtain it as a fullworthy List<Test> (you can easily do inner joins using #ManyToOne and so on), then this should do to obtain the first column from the SELECT query:
<li>#{item[0]}</li>

The SELECT clause queries more than one column or entity, the results
are aggregated in an object array (Object[]) in the java.util.List
returned by getResultList().
In the first place, native query isn't required in your case. The result of native query returns a list of object array. You have to create JPQL query instead of native query.
Query q = em.createQuery("select t from Test t", Test.class);
List<Test> list = q.getResultList();

Related

PrimeFaces datatable default sortBy from backing bean

I have a data table with a POJO object:
<p:dataTable id="table" var="object" sortBy="#{object.name}" sortOrder="DESCENDING">
object has fields id, name, date, size for example. I am able to set default sort field using xhtml, but I want set it from backing bean.
I am able to parse column id when user creates sort request for example name.
public void sortEventListener(AjaxBehaviorEvent actionEvent) {
String id = ((SortEvent) actionEvent).getSortColumn().getColumnKey();
String[] idPath = id.split(":");
sortBy = idPath[idPath.length - 1];
sortOrder = ((SortEvent) actionEvent).isAscending();
}
My task detects which column user wants to sort and persists it to db. After reload the data table should be sorted by this column.
When I set
sortBy="#{bean.sortBy}" // sortBy = name
it's not working and data table is not sorted after rendering the page.
Please help.
If you bind your data table to a org.primefaces.component.datatable.DataTable object in your bean or find the table component in your bean, you can use the table object to set the sortBy value expression programmatically.
To get an idea how PrimeFaces is handling sorting, you can have a look at the source code at GitHub.
When you have the sort column, you can easily get the sort value expression. So, in your listener you could use something like:
UIColumn sortColumn = sortEvent.getSortColumn();
ValueExpression sortByVE = sortColumn.getValueExpression("sortBy");
By the way, you can replace the parameter type AjaxBehaviorEvent with SortEvent in your sort listener method.
Now, store the sortByVE expression, and set it as the sortBy value expression of the bound table when needed:
dataTable.setValueExpression("sortBy", sortByVE);
If you want to create the value expression from scratch, use something like:
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory ef = context.getApplication().getExpressionFactory();
ValueExpression ve = ef.createValueExpression(context.getELContext(),
"#{object.name}",
Object.class);
dataTable.setValueExpression("sortBy", ve);
In this example "#{object.name}" is fixed. You should construct it based on the value you get from your sort listener.
If you want to find your table in your bean, OmniFaces Components might be helpful. It also offers a shortcut method to create value expressions.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
Programmatically getting UIComponents of a JSF view in bean's constructor
How do I set the value of HtmlOutputTag in JSF?

Primefaces datatable: multiple selection list is in another list

I have a question, how do I map the datatable multiple selecion in a list that is an element of another list:
<p:dataTable id="subDataTable#{index}" value="#{objectBean.subDataModels.get(index)}"
selection="#{objectBean.selectedLists.get(index)}" var="subRowTable"
rowKey="#{subRowTable.primaryKeyObj.toString()}">
With index is a int variable, and in my objectBean
private List<List<Object>> subDataModels; // and getter, setter
private List<List<Object>> selectedLists; // and getter, setter
I got error:
javax.faces.FacesException: Multiple selection reference must be an Array or a List for datatable
I need the solution for this case or the related topic about it.
Thanks for your help.

Is it possible to use custom JSF converter for UISelectOne, depending on value of Bean property or UIInputText value?

I need to get help with a problem.
I have an application, which displays data from database.
In database I am using one column for identifying an object with changes in time (version of object).
I mean that rows have different IDs, but same OBJECT_ID.
They are also differentiated by validity DATE columns (VALID_FROM and VALID_TO), so i can find the proper version of object in selected time.
When page is shown to user, he sets DATE for displaying data.
There is form on page, with Select Boxes (their items are object from database).
I need to show only items, that satisfy the validity condition.
Everything is OK before form handling.
I am using custom converter, that converts String value (ID of row in database table) to Object of my model, but I need two values for row to find. (ID and DATE from user form).
Converter method getAsObject gets only one VALUE parameter (ID from Select Box).
How to get second parametr to work?
Can i find it from Bean or from JSF input object?
If there is some way that includes using <f:attribute/>, is there way to set <f:attribute/> by Java code in Bean? (Form is generated by bean method).
I am sorry for my English, i try my best :o)
P.S.: Date parameter is important in sqlMap because of JOIN used. I search by ID, but other tables are joined by OBJECT_ID (version) => and i need to get one row only
Thanks for answers and have a nice day
Worsik
Edit:
Select Boxes are generated by this code:
uiInput = new HtmlSelectOneMenu();
UISelectItems items = new UISelectItems();
items.setValueExpression("value", createValueExpression(
"#{myBean.referencedList." + item.getName() + "}",
List.class));
uiInput.getChildren().add(items);
Converter method looks like this:
public Object getAsObject(FacesContext context, UIComponent component, String value)
{
if (value.equals("")) {
return null;
}
Class entityType = component.getValueExpression("value").getType(
FacesContext.getCurrentInstance().getELContext());
// TODO: need to get date value from form
Date day = new Date();
return myService(context).findEntityById(entityType, Long.valueOf(value), day);
}
entityType is Class of model for object from database
myService calls Dao object and sqlMap is called
select * from object_table as t1
JOIN other_table as t2 ON t1.object_fk = t2.object_id // (or version_id)
where t1.id = #id:INTEGER#
and t2.valid_from <= #day:DATE#
and t2.valid_to >= #day:DATE#
I figured out how to do this by <f:attribute/> by code in converter:
Date day = (Date) component.getAttributes().get("dateForSearch");
and in bean method after generating SelectBox with code:
uiInput.getAttributes().put("dateForSearch", getSelectedDate());
and in pages without dynamic generating of forms i used:
<SelectOneMenu>
...
<f:attribute name="dateForSearch" value="#{myBean.selectedDate}" />
</SelectOneMenu>
I hope that this will not be only self answered question and will help somebody else

"ValueExpression Map" of a JSF component

I'm storing value expressions in a JSF component with the f:attribute tag, e.g.:
<h:inputText ...>
<f:attribute name="myId1" value="#{bean.prop1}" />
<f:attribute name="myId2" value="#{bean.prop2}" />
<f:attribute name="myId3" value="#{bean.prop3}" />
</h:inputText>
Is there a way to access all of those value expressions programmatically? (without knowlegde of the names myId1, myId2,...)
Section 9.4.2 of the JSF 2.1 specification says that those values are stored "in the component’s ValueExpression Map".
That's the only occurrence of the term "ValueExpression Map" in the complete spec.
How do I access that map?
In the UIcomponent's Method getValueExpression() of the Jboss/Mojarra implementation the map
getStateHelper().get(UIComponentBase.PropertyKeys.bindings)
is used to obtain a single value expression.
I guess that map is a super set of the "ValueExpression Map"?
Can I be sure that all implementations and all inherited (standard) components use that map to store ValueExpressions?
Thanks.
In theory you should be able to see them all by UIComponent#getAttributes():
Map<String, Object> attributes = component.getAttributes();
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
System.out.printf("name=%s, value=%s%n", entry.getKey(), entry.getValue());
}
However, that doesn't work the way as you'd expect. It only returns static attributes. This does not seem to ever going to be fixed/implemented. See also JSF issue 636. I'd suggest to stick to attribtues with predefinied prefix and an incremental numerical suffix, like as you've presented in your example. That's also what I've always used to pass additional information from the component on to custom validators and converters. You can just collect them as follows:
Map<String, Object> attributes = component.getAttributes();
List<Object> values = new ArrayList<Object>();
for (int i = 1; i < Integer.MAX_VALUE; i++) {
Object value = attributes.get("myId" + i);
if (value == null) break;
values.add(value);
}
System.out.println(values);
An alternative to the answer given by BalusC might be to use nested facets or UIParameter components. Facets can be retrieved as a map using getFacets but you probably need to put an additional UIOutput inside each facet to access its value expression.
Nested UIParameters can be accessed by iterating over the components children and checking for instanceof UIParameter. UIParameters have name and value attributes and so could be easily converted to a map.
I have used parameters in a custom component, but I'm not sure how a standard UIInput like in your example reacts to these.
BalusC is right. UIComponent#getAttributes().get(name) gets values from both places - at first from attributes map and then if not found from "value expression map". To put some value you have to call UIComponent#setValueExpression(name, ValueExpression). If value is literal, it gets stored into the attribute map, otherwise into the "value expression map". Everything is ok then.

Querying Sharepoint - Value does not fall within the expected range

I'm attempting to retrieve the value of a listitem but keep getting a ArgumentException - Value does not fall within the expected range.
My code is as follows:
if (resultList.Count > 0)
{
SPListItem result = resultList[0];
if (result[Column] != null)
{
return result[Column].ToString();
}
}
In the immediate window I can verify the column does exist and the value can be found in the object tree structure.
result.Fields.GetField(Column).Id
returns a Guid but using it to retrieve the value of the Field results in another ArgumentException:
result[result.Fields.GetField(Column).Id]
This could happen if you get your list item collection from view (list.GetItems(view)) or from query with ViewFields property set, in this case only the fields included in ViewFields are returned.
You need to use InternalName of the field to get its value from SPListItem
result[result.Fields.GetField(Column).InternalName]

Resources