JSF 2.2:将bean属性作为ValueExpression传递给复合

时间:2015-10-23 03:09:44

标签: jsf jsf-2.2 composite-component

我想在动态添加的复合组件上传递一个非托管(非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对象以使其在整个会话期间以复合形式存活?

1 个答案:

答案 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方法就会以奇怪的方式破解。