JSF2.2:将bean属性作为ValueExpression传递给composite

JSF2.2:将bean属性作为ValueExpression传递给composite,jsf,jsf-2.2,composite-component,Jsf,Jsf 2.2,Composite Component,我希望将非托管(非字符串)对象作为属性传递给动态添加的复合组件,并使其在会话中存活 JSF2.2ViewDeclarationLanguage#createComponent处理复合组件的动态非字符串属性值的方式不同于旧的依赖于Mojara的代码(应用程序#createComponent)。我找不到完全适用于JSF2.2技术的方法,但可能是我 [我正试图通过转换为MyFaces来删除Mojarra依赖项(同时也解决了一些其他Mojarra问题)。我正在使用JSF2.2、CDIWeld 2.2.1

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

JSF2.2
ViewDeclarationLanguage#createComponent
处理复合组件的动态非字符串属性值的方式不同于旧的依赖于Mojara的代码(
应用程序#createComponent
)。我找不到完全适用于JSF2.2技术的方法,但可能是我

[我正试图通过转换为MyFaces来删除Mojarra依赖项(同时也解决了一些其他Mojarra问题)。我正在使用JSF2.2、CDIWeld 2.2.16、TomcatV8.0]

我以编程的方式实例化了不同的组合组件(注意bean属性):

在JSF2.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);
[..]
FacesContext context=FacesContext.getCurrentInstance();
ELContext=context.getELContext();
ValueExpression beanValExp=context.getApplication().getExpressionFactory()
.createValueExpression(elContext,“#{customBeanVE}”,ExtensionBeanInterface.class);
setValue(elContext,bean);
字符串beanValExpStr=beanValExp.getExpressionString();
attributes=newhashmap();
attributes.put(“bean”,beanValExpStr);//使用VE代替bean对象
UIComponent composite=context.getApplication().getViewHandler()
.getViewDeclarationLanguage(上下文,context.getViewRoot().getViewId())
.createComponent(上下文、taglibURI、标记名、属性);
[..]
这在第一个“添加组合”中非常有效,但在任何以下表单提交中,我都会得到:

/resources/com/aadhoc/cvc/spikes/extensionapproach/components/House.xhtml @16,49 value=“#{cc.attrs.bean.title}”:无法访问目标,“bean” 返回空值

我已经验证了组合的required和type属性工作正常,并且
{cc.attrs.bean.title}
最初显示的是bean的标题。我通过静态使用复合组件进行了验证,该组件可以很好地刷新工作


这是怎么一回事,我怎样才能切换bean对象,使它在整个会话中与组合一起生存?

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

因为所有的工作都是将bean对象放入属性映射,所以我想要一个神奇而优雅的地方来放置bean对象并让它们存活下来。我本可以把它们放到“全局”会话映射中(如下所示),但它不够干净。然后,我将它们放入我的一个主要会话状态bean(modelerBean)中,结果是正确的。这就是我如何保存bean,以及如何用EL字符串指向它。无需创建ValueExpression或MethodExpression对象或注册特殊映射。这种与JSF2.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的帖子后决定:


注意,我对@BalusC的两种“动态添加复合材料”方法()的经验是,如果可以的话,一定要使用jsf2.2方法。如果您不在JSF2.2中,旧的Mojarra方法就可以工作。一旦我修改代码使JSF2.2方法工作,旧的Mojarra方法就会以奇怪的方式中断。

我假设我的新ValueExpression EL映射只在请求期间存在。我猜我必须创建一个到实际会话值的“真实映射”。。。因此,映射将在请求之间继续工作。例如,如果我用一个唯一的键将一个值放入sessionMap,我可以在EL中使用该键,它将在整个会话中继续工作。我还可以使用一个会话bean,因为我已经用它来保存具有唯一ID的对象。旧方法非常有效,我没有意识到我被锁在莫哈拉:-(顺便说一句,使用旧的依赖于Mojara的方法,当我切换到MyFaces时,我在添加复合时得到了这一点:
java.lang.NullPointerException-java.lang.NullPointerException位于org.apache.MyFaces.view.facelets.impl.FaceletCompositionContextImpl.generateUniqueId(FaceletCompositionContextImpl.java:1048)
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);
[..]
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);
    [..]