3
使用JSF 2.1,钻嘴鱼科2.1.3,3.1.1的Glassfish和PrimeFaces 3.3.1副本ID
我试图在JSF处理加工场级别的安全性,在preRenderView事件上,并在需要将动态组件添加到JSF组件树时遇到问题。在第一次渲染时,一切正常,并且字段级安全性被处理。然而,在任何形式的更新之后,即使通过打印到控制台,我的添加代码也只会在每次更新时运行一次,但Mojarra会抱怨重复的ID。
看起来就好像Mojarra没有清除组件树的回发,因此每个后续的呈现更新都会将附加版本的组件添加到树中。
感谢任何人都可以提供的帮助。这是一些简单的示例代码。在commandButton上单击错误被引发。
的index.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
>
<f:event listener="#{lifeCycle.event}" type="preRenderView" />
<h:body>
<h:form id="form" prependId="false">
<h:panelGroup id="testPanel">
<h:inputText id="viewSec" value="viewSec node"/><br/>
</h:panelGroup>
<p:commandButton update="testPanel"/>
</h:form>
</h:body>
</html>
LifeCycle.java:
package com.dynamic.test;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
@ManagedBean
@RequestScoped
public class LifeCycle implements Serializable {
public void event(ComponentSystemEvent event){
FacesContext facesContext = FacesContext.getCurrentInstance();
UIViewRoot root = facesContext.getViewRoot();
NodeInspector visitCallback = new NodeInspector();
root.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), visitCallback);
List<UIComponent> securityEnabledComponents = visitCallback.getSecurityEnabledComponents();
for (UIComponent securityEnabledComponent : securityEnabledComponents) {
if(securityEnabledComponent.getClientId().equals("viewSec")){
List<UIComponent> childList = securityEnabledComponent.getParent().getChildren();
int targetPosition = securityEnabledComponent.getParent().getChildren().indexOf(securityEnabledComponent);
HtmlOutputText outputTextComponent = new HtmlOutputText();
outputTextComponent.setId(securityEnabledComponent.getId());
outputTextComponent.setValue(securityEnabledComponent.getAttributes().get("value"));
childList.set(targetPosition, outputTextComponent);
}
}
}
}
NodeInspector.java
package com.dynamic.test;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
public class NodeInspector implements VisitCallback {
private List<UIComponent> securityEnabledComponents = new ArrayList<UIComponent>();
FacesContext facesContext = FacesContext.getCurrentInstance();
@Override
public VisitResult visit(final VisitContext context, final UIComponent target) {
if(target.getClientId().equals("viewSec")){
securityEnabledComponents.add(target);
}
return VisitResult.ACCEPT;
}
public List<UIComponent> getSecurityEnabledComponents() {
return securityEnabledComponents;
}
}
错误:
SEVERE: JSF1007: Duplicate component ID viewSec found in view.
... +id: j_idt2
type: <html xmlns="http://www.w3.org/1999/xhtml">
+id: j_idt3
type: [email protected]
+id: form
type: [email protected]
+id: testPanel
type: [email protected]
+id: viewSec <===============
type: [email protected]
+id: viewSec <===============
type: [email protected]
+id: j_idt4
type: <br/>
+id: j_idt5
type: [email protected]
+id: j_idt6
type:
</html>...
SEVERE: Error Rendering View[/index.xhtml]
java.lang.IllegalStateException: Component ID viewSec has already been found in the view.
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:821)...
今天早上我刚才知道是什么导致了我的问题 - 我正在运行的Mojarra版本有一些bug,与动态修改树相关,后来大部分版本已经解决了这个bug [这里报道](http://java.net/jira/browse/JAVASERVERFACES-1826))。在修复错误的过程中,他们似乎遇到了我所做的同样的问题。修改树会导致大量的孤立节点闲置。这些节点实际上并不在呈现的HTML中,但是检查id唯一性不会更低。 –
你应该发表评论作为答案。知道这很有用。 – KidTempo