I am trying to insert multiple IPs in a List<String>
using a simple example. But I am getting following error.
javax.el.PropertyNotFoundException: Target Unreachable, 'BracketSuffix' returned null
Here is my JSF 2.2 page:
<h:form id="form">
<ui:repeat value="#{exampleBean.ipAddresses}" var="s"
varStatus="status">
<h:inputText value="#{exampleBean.ipAddresses[status.index]}" />
</ui:repeat>
<h:inputText value="#{exampleBean.newIp}" />
<h:commandButton value="Add" action="#{exampleBean.add}" />
<h:commandButton value="Save" action="#{exampleBean.save}" />
</h:form>
And here is my backing bean:
@ManagedBean
@ViewScoped
public class ExampleBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> ipAddresses;
private String newIp;
@PostConstruct
public void init() {
ipAddresses= new ArrayList<String>();
}
public String save() {
System.out.println(ipAddresses.toString());
return null;
}
public void add() {
ipAddresses.add(newIp);
newIp = null;
}
public List<String> getIpAddresses() {
return ipAddresses;
}
public String getNewIp() {
return newIp;
}
public void setNewIp(String newIp) {
this.newIp = newIp;
}
}
How is this caused and how can I solve it?
javax.el.PropertyNotFoundException: Target Unreachable, 'BracketSuffix' returned null
The exception message is wrong. This is a bug in the EL implementation being used by the server. What it really meant here in your specific case is:
javax.el.PropertyNotFoundException: Target Unreachable, 'ipAddresses[status.index]' returned null
In other words, there's no such item in the array list. This suggests that the bean got recreated on form submit and therefore reinitializes everything to default. It thus behaves like a @RequestScoped
one. Most likely you imported the wrong @ViewScoped
annotation. For a @ManagedBean
, you need to make sure that the @ViewScoped
is imported from the very same javax.faces.bean
package, and not thus the JSF 2.2-introduced javax.faces.view
one which is specifically for CDI @Named
beans.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
Update: as per the comments, you're using WebSphere 8.5 which usually ships with an ancient MyFaces 2.0.x version. I reproduced your problem with MyFaces 2.0.5. Its <ui:repeat>
failed to remember its view state for iteration status, that's why your construct still fails even though you're properly using a @ViewScoped
bean. I could work around it by using <c:forEach>
instead.
<c:forEach items="#{exampleBean.ipAddresses}" var="s" varStatus="status">
...
</c:forEach>
The alternate solution (apart from upgrading MyFaces to a more recent/decent version, obviously) would be to wrap the immutable String
in a mutable javabean such as
public class IpAddress implements Serializable {
private String value;
// ...
}
so that you can use List<IpAddress>
instead of List<String>
and thus you don't need the varStatus
anymore which triggered the MyFaces bug.
private List<IpAddress> ipAddresses;
private IpAddress newIp;
@PostConstruct
public void init() {
ipAddresses= new ArrayList<IpAddress>();
newIp = new IpAddress();
}
<ui:repeat value="#{exampleBean.ipAddresses}" var="ipAddress">
<h:inputText value="#{ipAddress.value}" />
</ui:repeat>
<h:inputText value="#{exampleBean.newIp.value}" />