私はJSFに不慣れで、まだ学んでいます。以下に説明する特定の問題の解決策を探してみましたが、何も見つかりませんでした。私が間違ったものを探していたことが原因である場合は、正しい方向に向けてください.
次の例は、私が遭遇した問題を示しています。この例は、問題に焦点を当て、問題が発生した実際のプロジェクトの複雑さを隠すために単純化されています。
次のページ/クラスを検討してください。
- /resources/test/custom.xhtml;
- /test/CharsetProvider.java;
- /test/CharsetHello.java;
- /testWith.xhtml;
- /testWithout.xhtml;
/resources/test/custom.xhtml
これは、デフォルト値を持つ 1 つの属性を持つ複合コンポーネントです。コンポーネントは単に属性値を取得し、それを以下で説明する 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 です。バッキング Bean の代わりに CDI 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);
}
}
テスト/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 に変換されているようです。
まず、これは予想される動作であり、その理由は何ですか?
これが予想される動作である場合、別の実装を提案できますか?
前もって感謝します!