Avoiding null point exception in el in JSF [duplicate] - jsf

This question already has an answer here:
JSF: h:outputText; how to show a dash when the value is empty string?
(1 answer)
Closed 5 years ago.
I am developing a JSF application with JPA(EclipseLink 2.0) and Primefaces.
I want to know is there any way to avoid null point exception when el calls a property of a null object. I have described the situation.
I have Bill class. There may be no or more BillItem objects with a Bill objects. Each BillItem object have Objects like Make, Country, Manufacturer, etc objects. I am displaying several properties of a bill within a single JSF file like this.
"#{billControlled.bill.billItem.modal.name}"
But if a bill is not selected, or when there are no bill items for a selected bill, the properties accessing in the el are null. I can avoid this by creating new objects for every bill, for example, new make for a new bill item, etc or by creating new properties in the controller itself for all the properties. But that is a very long way and feel like rudimentory.
Is there any good practice to avoid this null point exception in el in JSF?

Solution is checking for null (and you can also check for empty) and use with render attribute.
Empty can work well with Collections (check for both empty and null), and also with null.
For example:
<h:outputText rendered="#{not empty myBean.myData}" value="..." />

I got the solution. Before every el, I can check null.
JSF: h:outputText; how to show a dash when the value is empty string?
<h:outputText value="#{userHandler.user.phoneNumber != null
? userHandler.user.phoneNumber : '-'}" />
Or
<h:outputText rendered="#{userHandler.user.phoneNumber ne null}" value="#{userHandler.user.phoneNumber}" />

Related

Refactoring a DataTable with a large number of attributes

I've got a data table with 17 attributes. The table can be rendered in two modes: with row selection enabled and without it.
<p:dataTable selection="#{isDefaultSelectionMode ? null : widget.selected}" />
It doesn't work because selection expects a reference to a property to be able to set/get it.
I could create a dummy property widget.ignored and it's going to work. I don't like this for the obvious reason.
<p:dataTable selection="#{isDefaultSelectionMode ? widget.ignored : widget.selected}" />
I could split the table into two separate templates. I would exclude selection from one and duplicate 16 other attributes. It's not a good one, either.
I am looking for an elegant solution to either make the attribute optional (not to render it under some condition) or to avoid defining a dummy property.
I am new to JSF and PrimeFaces, feel free to correct. Any help would be welcomed.
Fortunately, I didn't have to apply any of my terrible workarounds.
As suggested by #Kukeltje (thank you) and the links he provided, I defined the attribute conditionally
<c:if test="#{isDefaultSelectionMode}">
<f:attribute name="selection" value="#{widget.selected}"/>
</c:if>
For more details, visit these questions:
JSF 2.0 dynamic attributes without creating new components
How not to set an attribute of a component inside a composite component if it is empty?
What is f:attribute used for in this example?

get the list of element in <ui:repeat> already checked in JSF [duplicate]

This question already has answers here:
How to use <h:selectBooleanCheckbox> in <h:dataTable> or <ui:repeat> to select multiple items?
(3 answers)
Closed 5 years ago.
I have an <ui:repeat> in which I has a list of object , next to each of those object I need to have a checkbox ( to check this element).
I want to know how could I integrate those checkboxes inside the <ui:repeat> in order to have many rows and each rows needs to has the object.getName() and next to it I need to have the checkbox ?
If this is feasible, Please how could I obtain those checked objects in the backing bean ?
<ui:repeat var="myObject" varStatus="status"
value="#{Bean.getListObjects}">
<b>#{status.index+1} .</b>
<h:outputLabel value="#{myObject.name}" />
//need the checkbox here for example
</ui:repeat>
Just create a map with the object UID as the key and a boolean as the value. Then value-bind each checkbox to a map entry.
Assuming your names are unique, you could use them. So, in you bean create a Map<String,Boolean>, and initialize the map with each object.
You can use the map to in the checkbox value like value="#{bean.map[object.name]}".
See also:
Dynamic value binding of JSF component

How to pre-select data in h:selectManyListbox [duplicate]

This question already has an answer here:
How do UISelectOne and UISelectMany components preselect defaults in f:selectItems
(1 answer)
Closed 7 years ago.
This is a common problem and I already saw the basic solution (populate the selectManyListBox). Here is the code of my JSF 1.2 page:
<h:selectManyListbox id="statusMenu" converter="statusConverter" value="#{aprvAction.ap.statuses}" >
<f:selectItems id="statusItem" value="#{action.ap.statusItens}"/>
<a:support event="onclick" ajaxSingle="true" immediate="true" eventsQueue="queueGeral" />
<a:support event="onchange" ajaxSingle="true" eventsQueue="queueGeral" process="statusMenu"/>
</h:selectManyListbox>
The thing is that #{aprvAction.ap.statuses} is an instance of List<Status> class. However, in tag <f:selectItems> the value: #{action.ap.statusItens} is an Instance of List<SelectItem>.
I populate the the #{aprvAction.ap.statuses} with the values that I want to pre-select the ListBox, but did not work. I think it's because they are different objects in <selectManyListBox> and <selectItems>.
How can I solve this, and show the pre-selected values in <selectManyListBox>?
JSF will use equals() method to compare available items with (pre)selected items.
In case of standard objects, such as String, this is already implemented.
In case of custom objects, such as your Status entity, it's your responsibility to make sure that you've properly implemented the equals() (and hashCode()) method in the class.
See also:
How to populate options of h:selectOneMenu from database?
Right way to implement equals contract
value in h:selectManyListbox should be subset of itemValue's in f:selectItems.
Create a method which return the List or Array of selected statuses. Use this method in value attribute of h:selectManyListbox. Any value from list/array returned in this method should match itemValue in set of {itemValue, itemLabel} pairs used in f:selectItems.

input component inside ui:repeat, how to save submitted values

I'm displaying a list of questions from database and for each question I have to display a list of options, in this case radio buttons.
<ui:repeat value="#{formData.questions}" var="question">
<div>
<p:outputLabel value="#{question.name}" />
<p:selectOneRadio value="#{formData.selectedOption}">
<f:selectItems value="#{formData.options}" />
</p:selectOneRadio>
</div>
</ui:repeat>
I need to save the checked option for each question.
How can I do this?
You need to associate the input value with the repeated variable var in some way. Right now you're not doing that anywhere and basically binding all input values to one and same bean property. So, when the form gets submitted, every iteration will override the bean property everytime with the value of the current iteration round until you end up getting the value of the last iteration round. This is definitely not right.
The simplest way would be to directly associate it with the object represented by var:
<p:selectOneRadio value="#{question.selectedOption}">
In your specific case, this only tight-couples the "question" model with the "answer" model. It's reasonable to keep them separated. A more proper solution in your specific case is to map it with currently iterated #{question} as key (provided that it has a proper equals() and hashCode() implementation, obviously):
<p:selectOneRadio value="#{formData.selectedOptions[question]}">
With:
private Map<Question, String> selectedOptions = new HashMap<>();
Regardless of the approach, in the action method, just iterate over it to collect them all.

Why is a dynamic created JSF EL value expression not resolved?

I got a simple setup (and a big issue): a JSP page with en empty panel grid item container and a binding to a bean.
<h:panelGrid binding="#{ bean.container }" id="container" />
When the getter of the bean will be called, the container is filled with a random number of columns with a command link inside. So far so good. The container is filled up with the right number of elements, and with the use of an ActionListener on the links, I get all click events.
Here comes the tricky part: I want to mark the 'selected' or 'pressed' column via a different style class. With a static setup, I would do this with an expression like:
<h:column styleClass="#{ bean.selectedColumn eq 'id' ? 'btnSelected' : 'btn' }">
<!-- command link and some blahblah -->
</h:column>
The bean contains a simple getter getSelectedColumn() , that returns an id. Straight forward, so this works perfect!
But when I try to do the same inside the bean,
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
String expression = "#{ bean.selectedColumn eq 'id' ? 'btnSelected' : 'btn' }";
new ExpressionFactoryImpl().createValueExpression(elContext, expression, String.class);
column.setValueExpression("styleClass", valueExpression);
the expression won't ever be resolved. To make myself clear: both the command links, the columns and the value expressions are generated inside the bean. Is that the cause?
Can anyone tell me why? Thanks in advance!
When the JSP is compiled the bean wont be called! This is done at runtime cause you want to see live data in the bean. Therefore the (later) generated EL is not visible at compilation. The EL would not be resolved at runtime.

Resources