javax.el.PropertyNotFoundException:目标无法到达,'BracketSuffix' 返回 null

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

我正在尝试使用一个简单示例在 List<String> 中插入多个 IP。但是我收到以下错误。

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

这是我的 JSF 2.2 页面:

<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>

这是我的支持 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;
    }

}

这是怎么造成的,我该如何解决?

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

异常信息有误。这是服务器使用的 EL 实现中的错误。在您的具体情况下,真正 的意思是:

javax.el.PropertyNotFoundException: Target Unreachable, 'ipAddresses[status.index]' returned null

也就是说,数组列表中没有这样的项目。这表明该 bean 在表单提交时重新创建,因此将所有内容重新初始化为默认值。因此,它的行为类似于 @RequestScoped。您很可能导入了错误的 @ViewScoped 注释。对于 @ManagedBean,您需要确保 @ViewScoped 是从完全相同的 javax.faces.bean 包导入的,而不是 JSF 2.2 引入的 javax.faces.view对于 CDI @Named 个 bean。

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

另请参阅:

  • @ViewScoped bean recreated on every postback request when using JSF 2.2

更新:根据评论,您使用的是 WebSphere 8.5,它通常附带一个古老的 MyFaces 2.0.x 版本。我用 MyFaces 2.0.5 重现了您的问题。它的 <ui:repeat> 未能记住其迭代状态的视图状态,这就是为什么即使您正确使用了 @ViewScoped bean,您的构造仍然失败的原因。我可以通过使用 <c:forEach> 来解决它。

<c:forEach items="#{exampleBean.ipAddresses}" var="s" varStatus="status">
    ...
</c:forEach>

替代解决方案(除了将 MyFaces 升级到 recent/decent 版本之外,显然)是将不可变的 String 包装在可变的 javabean 中,例如

public class IpAddress implements Serializable {
    private String value;
    // ...
}

这样您就可以使用 List<IpAddress> 而不是 List<String>,因此您不再需要触发 MyFaces 错误的 varStatus

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