我正在尝试编写一个动态选择创建和呈现现有复合组件的JSF 自定义组件。到目前为止,除了将属性传递给复合材料外,其他工作正常。
这是我的自定义组件类(错误处理等被剥离以便更好地阅读):
@FacesComponent(createTag = true)
public class ChooseEZComp extends UIComponentBase {
@Override
public void encodeBegin(FacesContext context) throws IOException {
Object value = getAttributes().get("value");
String ezCompName = value.getClass().getSimpleName().toLowerCase();
// ezCompName is something like "freelink" or "treenode"
Map<String, Object> params = new HashMap<>();
params.put("node", value);
// log.debug(params.get("node").getClass().getName()) -> yields correct class name
ViewDeclarationLanguage viewDeclarationLanguage = context
.getApplication()
.getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId());
UIComponent component = viewDeclarationLanguage
.createComponent(context,
"http://xmlns.jcp.org/jsf/composite/ezcomp",
ezCompName,
params);
component.encodeAll(context);
}
}
一个复合组件(我有几个),由这个类选择并呈现:
<cc:interface>
<cc:attribute name="node" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputText value="The class of node is: #{cc.attrs.node.class.name}"/>
</cc:implementation>
这就是我在JSF页面中使用标签的方式:
<test:chooseEZComp value="#{treeView.selectedNode.data}"/>
所以&#34;价值&#34;始终保证不是 类型 java.lang.String (它是一些JPA @Entity)。
但是JSF页面中的结果输出始终是:
节点类是:java.lang.String
我哪里错了?是不是可以将除String之外的东西作为参数传递给复合材料?
我使用Java EE 7运行wildfly-8.2.0-final(和Primefaces 5,但这里没有使用)
欢迎任何提示!
编辑:当然我也试图强制cc:interface
中的属性类型<cc:interface>
<cc:attribute name="node" required="true" type="some.package.type"/>
</cc:interface>
但是这导致了IllegalArgument异常:
IllegalArgumentException:无法将类型类java.lang.String转换为类
答案 0 :(得分:0)
原来我误解了API ... Map&lt; String,Object&gt;在签名让我觉得我可以通过一个对象。但Javadoc对此更加准确:
属性 - 任何名称=值对,否则将在标记上给出会导致创建此组件[...]
因此,您不会将值传递给createComponent,而是将用于计算指定属性或属性名称的值的表达式:
Map<String, Object> attributes = new HashMap<>();
ValueExpression valueExpression = getValueExpression("value");
attributes.put("node", valueExpression.getExpressionString());
有趣的一面阅读: 找到我通过jsf-imp-2.2.8-jbossorg调试的解决方案,并偶然发现了创建组件的代码。基本上它的作用是:
至少在找到它之后,很明显为什么你需要传递值表达式而不是值本身。