我想在动态添加的复合组件上传递一个非托管(非String)对象作为属性,并让它在会话中存活。
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对象,并将其作为属性直接添加到复合组件中,并且效果很好(我使用@BalusC很棒但是Mojarra来自OmniFaces Component#includeCompositeComponent
的依赖示例代码):
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);
[..]
这对第一个&#34;添加复合&#34;非常有用,但在以下任何表格提交中,我得到:
/resources/com/aadhoc/cvc/spikes/extensionsapproach/components/House.xhtml @ 16,49 value =&#34;#{cc.attrs.bean.title}&#34;:目标无法访问,&#39; bean&#39; 返回null
我已经验证了复合的必需属性和类型属性工作正常,而#{cc.attrs.bean.title}
最初显示的是bean的标题。我通过静态使用复合组件进行验证,刷新工作正常。
这笔交易是什么,以及如何切换bean对象以使其在整个会话期间以复合形式存活?
答案 0 :(得分:1)
我在Mojarra工作得很好。我可以将bean对象放在属性值中,一切都很棒。尝试MyFaces,我需要更改/更新我的方法,现在我需要使用EL字符串而不是直接对象引用。
由于所有人都只是将bean对象放入属性Map中,我想要一个神奇但优雅的地方放置bean对象并使它们存活下来。我本可以把它们放到“全局”会话Map中(就像这样:How to save an object into JSF Session),但它不够干净。然后我将它们放入我的一个主会话状态bean(modelerBean)中,它是正确的。这就是我保存bean的方式,以及我如何使用EL字符串指向它。无需创建ValueExpression或MethodExpression对象或注册特殊映射。这种兼容JSF 2.2的方法在Mojarra和MyFaces中都适用于我。
public void onAdd(ActionEvent ev) {
[..]
ChosenBean chosenBean = new ChosenBean();
chosenBean.setComponentId(id);
chosenBean.setBean(bean);
modelerBean.addChosen(chosenBean);
[..]
String el = "#{modelerBean.getChosen('"+id+"').bean}"
attributes.put(MODELER_EXTENSION_BEAN_ATTRIBUTE_NAME, el);
[..]
我在阅读@ BalusC的帖子How do I get and set an object in session scope in JSF?
之后决定了这一点请注意,我使用@BalusC的两个“动态添加复合”方法(How to programmatically or dynamically create a composite component in JSF 2)的经验是,如果可以,您绝对应该使用JSF 2.2方法。如果你不在JSF 2.2中,那么旧的Mojarra方法确实有效。一旦我修改了我的代码以使JSF 2.2方法有效,旧的Mojarra方法就会以奇怪的方式破解。