我的xhtml页面:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:c="http://java.sun.com/jstl/core"
>
<h:head>
<!-- <h:outputStylesheet library="css" name="table-style.css" /> -->
</h:head>
<h:body>
<h1>category</h1>
<h:form id="form">
<h:panelGrid columns="1">
<c:forEach items="#{categoryBean.parentCategoryList}" var="cat">
<h:panelGroup>
<h:outputText value="#{cat.name}"/>
<h:commandButton value="+" type="button" onclick="expand('#{cat.name}');"/>
</h:panelGroup>
<h:panelGroup>
<h:selectManyCheckbox id="#{cat.name}" style="display: none" value="#{categoryBean.selectedCategoryList}">
<f:selectItems value="#{categoryBean.getSubCategoryList(cat.id)}" var="sub" itemLabel="#{sub.name}" itemValue="#{sub.name}"/>
</h:selectManyCheckbox>
</h:panelGroup>
</c:forEach>
</h:panelGrid>
<h:commandButton value="Submit" action="result" />
<h:commandButton value="Reset" type="reset" />
</h:form>
<script type="text/javascript">
function expand(cat) {
var name = "form:" + cat;
alert(name);
var element = document.getElementById(name);
if(element.style.display == 'block') {
element.value = "-";
element.style.display = 'none';
} else {
element.value = "+";
element.style.display = 'block'
}
}
</script>
</h:body>
</html>
我的托管bean
package com.gtp.iqp.presentation.managedBeans;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.gtp.iqp.business.bo.Category;
import com.gtp.iqp.business.delegate.CategoryDelegate;
@SuppressWarnings("serial")
@Component
public class CategoryBean extends BaseManagedBean {
@Autowired
private CategoryDelegate categoryDelegate;
private List<Category> parentCategoryList;
private List<String> selectedCategoryList;
public CategoryDelegate getCategoryDelegate() {
return categoryDelegate;
}
public void setCategoryDelegate(CategoryDelegate categoryDelegate) {
this.categoryDelegate = categoryDelegate;
}
public List<Category> getParentCategoryList() {
parentCategoryList = categoryDelegate.getParentCategories();
return parentCategoryList;
}
public void setParentCategoryList(List<Category> parentCategoryList) {
this.parentCategoryList = parentCategoryList;
}
public List<String> getSelectedCategoryList() {
return selectedCategoryList;
}
public void setSelectedCategoryList(List<String> selectedCategoryList) {
this.selectedCategoryList = selectedCategoryList;
}
public List<Category> getSubCategoryList(long parent) {
return categoryDelegate.getSubCategories(parent);
}
}
我的问题
<f:selectItems value="#{categoryBean.getSubCategoryList(cat.id)}"/>
上面的selectItems语句能够从数据库中获取列表。我能够看到托管bean包含列表。但是,一旦控件转移到xhtml页面,它就不会显示出来。我看到以下异常:
Hibernate: select this_.id as id1_1_0_, this_.name as name2_1_0_, this_.parent as parent3_1_0_ from category this_ where this_.parent=?
Hibernate: select this_.id as id1_1_0_, this_.name as name2_1_0_, this_.parent as parent3_1_0_ from category this_ where this_.parent=?
Hibernate: select this_.id as id1_1_0_, this_.name as name2_1_0_, this_.parent as parent3_1_0_ from category this_ where this_.parent=?
Dec 13, 2013 2:56:06 PM com.sun.faces.context.ExceptionHandlerImpl log
FATAL: JSF1073: java.lang.IllegalArgumentException caught during processing of RENDER_RESPONSE 6 : UIComponent-ClientId=, Message=Release Management
Dec 13, 2013 2:56:06 PM com.sun.faces.context.ExceptionHandlerImpl log
FATAL: Release Management
java.lang.IllegalArgumentException: Release Management
at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:592)
at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:412)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.assignUniqueId(ComponentTagHandlerDelegateImpl.java:373)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:176)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at com.sun.faces.facelets.tag.jstl.core.ForEachHandler.apply(ForEachHandler.java:230)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93)
at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:87)
at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:161)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:980)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:99)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
有人可以告诉我我做错了什么,我该如何解决?
答案 0 :(得分:3)
仔细查看堆栈跟踪顶行中的类/方法名称,一个好的库具有相当自我解释的类/方法名称:
java.lang.IllegalArgumentException: Release Management
at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:592)
at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:412)
因此,它在设置UI组件的id
期间发生。该ID正在验证且不被视为有效。实际上,根据javadoc:
Release Management
内部空格无效
设置此UIComponent的组件标识符(如果有)。组件标识符必须遵守以下语法限制:
- 不得为零长度字符串。
- 第一个字符必须是字母或下划线(&#39; _&#39;)。
- 后续字符必须是字母,数字,下划线(&#39; _&#39;)或短划线(&#39; - &#39;)。
根据HTML spec,HTML元素ID中的空格也是无效的(你知道,JSF基本上只是一个HTML代码生成器,它当然应该尊重HTML规范):
ID和NAME令牌必须以字母([A-Za-z])开头,后面可以跟任意数量的字母,数字([0-9]),连字符(&#34; - &#34 ;),下划线(&#34; _&#34;),冒号(&#34;:&#34;)和句号(&#34;。&#34;)。
罪魁祸首在这里:
<h:selectManyCheckbox id="#{cat.name}" ...>
在这种特殊情况下,您基本上有2个选项可以解决它:
使用<h:dataTable>
代替<h:panelGrid><c:forEach>
,它会收到以行索引为前缀的自动生成ID:
<h:dataTable value="#{categoryBean.parentCategoryList}" var="cat">
<h:column>
<h:outputText value="#{cat.name}"/>
<h:commandButton value="+" type="button" onclick="expand('#{cat.name}');"/>
<br/>
<h:selectManyCheckbox id="name" style="display: none" value="#{categoryBean.selectedCategoryList}">
<f:selectItems value="#{categoryBean.getSubCategoryList(cat.id)}" var="sub" itemLabel="#{sub.name}" itemValue="#{sub.name}"/>
</h:selectManyCheckbox>
</h:column>
</h:dataTable>
使用带<c:forEach varStatus>
的增量数字后缀的固定前缀:
<h:panelGrid columns="1">
<c:forEach items="#{categoryBean.parentCategoryList}" var="cat" varStatus="loop">
<h:panelGroup>
<h:outputText value="#{cat.name}"/>
<h:commandButton value="+" type="button" onclick="expand('#{cat.name}');"/>
</h:panelGroup>
<h:panelGroup>
<h:selectManyCheckbox id="name_#{loop.index}" style="display: none" value="#{categoryBean.selectedCategoryList}">
<f:selectItems value="#{categoryBean.getSubCategoryList(cat.id)}" var="sub" itemLabel="#{sub.name}" itemValue="#{sub.name}"/>
</h:selectManyCheckbox>
</h:panelGroup>
</c:forEach>
</h:panelGrid>
如果有必要,不要忘记相应地更改expand()
JS函数的参数。