【发布时间】:2016-01-22 12:19:09
【问题描述】:
我想将非托管(非字符串)对象作为属性传递给动态添加的复合组件,并让它在会话中存活。
JSF 2.2 ViewDeclarationLanguage#createComponent 处理复合组件的动态非字符串属性值与旧的 Mojarra 相关代码 (Application#createComponent) 不同。我找不到完全适用于 JSF 2.2 技术的方法,但可能是我。
[我正在尝试通过转换为 MyFaces 来删除 Mojarra 依赖项(并且还解决了一些其他 Mojarra 问题)。我正在使用 JSF 2.2、CDI Weld 2.2.16、Tomcat v8.0]
我正在以编程方式实例化不同的复合组件(注意 bean 属性):
<cc:interface>
<cc:attribute name="bean" required="true" type="com.aadhoc.cvc.spikes.extensionsapproach.ExtensionBeanInterface"/>
</cc:interface>
<cc:implementation>
<h:panelGrid columns="2">
<h:outputText value="Title:"/>
<h:inputText value="#{cc.attrs.bean.title}"/>
</h:panelGrid>
</cc:implementation>
在较旧的 Mojarra 依赖方法中,我实例化了非托管 bean 对象,并将其作为属性直接添加到复合组件中,它工作得很好(我正在使用来自 OmniFaces 的 @BalusC 很棒但依赖于 Mojarra 的示例代码@ 987654324@):
ExtensionBeanInterface bean = Class.forName(className).newInstance();
attributes = new HashMap<String, Object>();
attributes.put("bean", bean); // Using bean object itself
[..]
UIComponent composite = application.createComponent(context, resource);
composite.getAttributes().putAll(attributes);
[..]
在 JSF 2.2 中,我发现我必须直接传递一个字符串 ValueExpression 而不是我的 bean 对象。我目前正在使用这种技术,但不能完全正确:
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
ValueExpression beanValExp = context.getApplication().getExpressionFactory()
.createValueExpression(elContext, "#{customBeanVE}", ExtensionBeanInterface.class);
beanValExp.setValue(elContext, bean);
String beanValExpStr = beanValExp.getExpressionString();
attributes = new HashMap<String, Object>();
attributes.put("bean", beanValExpStr); // Using VE instead of bean object
UIComponent composite = context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId())
.createComponent(context, taglibURI, tagName, attributes);
[..]
这在第一次“添加复合”时效果很好,但在任何以下表单提交中,我得到:
/resources/com/aadhoc/cvc/spikes/extensionsapproach/components/House.xhtml @16,49 value="#{cc.attrs.bean.title}": 目标不可达,'bean' 返回null
我已经验证了组合的 required 和 type 属性工作正常,并且 #{cc.attrs.bean.title} 最初显示了 bean 的标题。我使用刷新的复合组件的静态使用进行了验证。
这是怎么回事,我如何切换 bean 对象,以便它在整个会话中与组合一起存在?
【问题讨论】:
-
我假设我的新 ValueExpression EL 映射仅在请求期间存在。我猜我必须创建一个到实际会话值的“真实映射”......所以映射将继续跨请求工作。例如,如果我使用唯一键将值放入 sessionMap,我可以在 EL 中使用该键,它将在会话中继续工作。我还可以使用一个会话 bean,我已经必须保存具有唯一 ID 的对象。旧方法效果很好,我没有意识到我被锁定在 Mojarra 中:-(
-
顺便说一句,使用旧的 Mojarra 依赖方法,当我切换到 MyFaces 时,我在添加复合材料时得到了这个:
java.lang.NullPointerException - java.lang.NullPointerException at org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl.generateUniqueId(FaceletCompositionContextImpl.java:1048)
标签: jsf jsf-2.2 composite-component