javax.el.PropertyNotFoundException: Target Unreachable, 'BracketSuffix' returned null

4.7k Views Asked by At

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?

1

There are 1 best solutions below

11
On BEST ANSWER

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;

See also:


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}" />