繁体   English   中英

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

[英]JSF 2.2: Passing bean attribute as ValueExpression to composite

我想将非托管(非字符串)对象作为属性传递给动态添加的复合组件,并使其在会话中幸存下来。

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 Component#includeCompositeComponent @BalusC很棒但与Mojarra相关的示例代码) :

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中,我发现必须直接传递String 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对象,以便它在整个会话中与复合对象一起生存?

我在Mojarra的工作很棒。 我可以将bean对象放在属性值中,一切都很棒。 尝试MyFaces时,我需要更改/更新方法,现在需要使用EL字符串而不是直接对象引用。

由于所有人都只是在将bean对象放入属性Map中,所以我想要一个神奇而优雅的地方来放置bean对象并使它们存活。 我本可以将它们放到“全局”会话映射中(例如: 如何将对象保存到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的帖子后,我决定了这一点: 如何在JSF的会话范围内获取和设置对象?

注意,我对@BalusC的两种“动态添加复合”方法( 如何在JSF 2中以编程方式或动态创建复合组件 )的经验是,如果可以的话,您绝对应该使用JSF 2.2方法。 如果您不在JSF 2.2中,那么旧的Mojarra方法确实可以工作。 一旦我修改了代码以使JSF 2.2方法能够工作,旧的Mojarra方法就会以奇怪的方式破坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM