【问题标题】:JSF, Composite Component: method call with default attribute value as parameterJSF,复合组件:以默认属性值作为参数的方法调用
【发布时间】:2012-10-21 06:54:51
【问题描述】:

我是 JSF 的新手,还在学习。我尝试为下面描述的特定问题寻找解决方案,但我找不到任何东西。如果是因为我在寻找错误的东西,请指出我正确的方向,但希望这是尚未回答的问题,并且答案可以使每个人受益。

以下示例说明了我遇到的问题。该示例被简化以关注问题并隐藏发生问题的实际项目的复杂性。

考虑以下页面/类:

  1. /resources/test/custom.xhtml;
  2. /test/CharsetProvider.java;
  3. /test/CharsetHello.java;
  4. /testWith.xhtml;
  5. /testWithout.xhtml;

/resources/test/custom.xhtml

这是一个复合组件,具有一个具有默认值的属性。该组件只需获取属性值并将其作为参数传递给下面描述的 CDI bean 以获得用于输出的模型对象。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html">

    <cc:interface>
        <cc:attribute name="charset"
                      default="#{charsetProvider.defaultCharset}"
                      type="java.nio.charset.Charset" />
    </cc:interface>

    <cc:implementation>
        <h:outputText value="#{charsetProvider.createCharsetHello(cc.attrs.charset).hello}"/>
    </cc:implementation>
</html>

test/CharsetProvider.java

这是一个 CDI bean,它只包含一个在整个应用程序中使用的默认值,并具有一个创建用作组件模型的对象的方法。我使用 CDI bean 而不是支持 bean 的原因是因为在我的特定项目中,需要在运行时注入默认值,但支持 bean 不是注入的候选对象。

package test;

import java.nio.charset.Charset;
import javax.annotation.PostConstruct;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class CharsetProvider {

    private Charset defaultCharset;

    @PostConstruct
    protected void postConstruct() {
        this.defaultCharset = Charset.forName("UTF-8");
    }

    public Charset getDefaultCharset() {
        return defaultCharset;
    }

    public Charset getCharsetForName(String name) {
        return Charset.forName(name);
    }

    public CharsetHello createCharsetHello(Charset cs) {
        return new CharsetHello(cs);
    }
}

test/CharsetHello.java

这是“模型”对象。它只是转换“Hello world!”到一个字节数组并使用给定的字符集返回。

package test;

import java.nio.charset.Charset;

public class CharsetHello {

    private static final String HW = "Hello World!";
    private final byte[] data;
    private final Charset cs;

    public CharsetHello(Charset cs) {
        this.cs = cs;
        this.data = CharsetHello.HW.getBytes(this.cs);
    }

    public String getHello() {
        return new String(this.data, this.cs);
    }
}

testWith.xhtml

这是一个测试页面,它通过为组件的属性指定一个值来使用上面定义的复合组件。页面正确呈现,即“Hello World!”打印在屏幕上。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:test="http://java.sun.com/jsf/composite/test">
    <h:head>
        <title>Test</title>
    </h:head>
    <h:body>
        <test:custom charset="#{charsetProvider.getCharsetForName('UTF-16')}" />
    </h:body>
</html>

testWithout.xhtml

这是一个测试页面,没有将自定义值传递给组件的属性,打算使用默认值。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:test="http://java.sun.com/jsf/composite/test">
    <h:head>
        <title>Test</title>
    </h:head>
    <h:body>
        <test:custom />
    </h:body>
</html>

上面的页面会导致一个带有以下消息的 JSF 错误页面:

/resources/test/custom.xhtml @14,94 value="#{charsetProvider.createCharsetHello(cc.attrs.charset).hello}": Cannot convert UTF-8 of type class java.lang.String to class java.nio.charset.Charset

似乎在最后一种情况下,默认值在传递给方法之前被转换为 java.lang.String。

首先,这是预期的行为吗?为什么?

如果这是预期的行为,您能否建议不同的实现方式?

提前谢谢你!

【问题讨论】:

  • 我能够重现它。不确定这是否是指定的行为,我必须先查看规范。至少我直觉上并没有预料到。不过,它适用于 EL 具有内置强制转换的类型,例如 NumberBooleanEnum(只要您不使用将被解释为 LongInteger)。

标签: jsf-2 composite-component


【解决方案1】:

这个问题和这个问题有着完全相同的基础:FacesConverter forClass don't work with Composite Componet。复合属性值类型在 Mojarra 中被错误地评估为 java.lang.Object 而不是实际模型类型。

报告为Mojarra issue 2568。它适用于 MyFaces 2.1.9。

【讨论】:

  • 再次感谢@BalusC 跟踪并报告问题。希望他们尽快修复它。同时,我只需要使用上面testWith.xhtml 中描述的组件即可。
猜你喜欢
  • 2012-03-13
  • 2012-07-20
  • 2011-10-09
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-27
  • 1970-01-01
相关资源
最近更新 更多