访问 ResourceBundle 作为 ManagedProperty 序列化问题
Accessing ResourceBundle as ManagedProperty Serialization Issue
首先,抱歉我的英语不好!
在以下托管 Bean (ApplicationScoped) 中,我将 ResourceBundle(.properties) 作为 @ManagedProperty 进行访问。 ResourceBundle 对象不可序列化,所以我在 Eclipse/Tomcat 控制台中收到一个错误,指出该对象不能 serialized/de-serialized.. 等等
Exception loading sessions from persistent storage
java.io.WriteAbortedException: writing aborted;
java.io.NotSerializableException: java.util.PropertyResourceBundle
我对这个问题有 2 个问题:
- 我认为,JSF 将预定义的(in faces-config.xml)
ResourceBundles
处理为 ApplicationScoped bean。这意味着(如果我理解正确的话),这个 Object/Bean (ResourceBundle) 以某种方式存储在文件中的某个地方(持久存储)。现在,由于 ResourceBundle
不可序列化,那么它以哪种格式存储?以及 JSF 如何提供这样的服务 "Beans"?序列化对象以字节形式存储在文件中,那么不可序列化对象如何存储?
- 在下面的示例中,我会将我的
@ManagedProperty ResourceBundle
声明为 transient(由于序列化问题),但瞬态对象不会存储在持久存储中(无状态),这是否意味着每次调用方法 getConfigurationAttribute
(我使用此 resourceBundle 的地方)都会 recreate/reload ManagedPropery ResourceBundle 因为它被标记为瞬态?
非常感谢您的帮助。
@ManagedBean(name="facesResource",eager=true)
@ApplicationScoped
public class FacesResource implements Serializable{
private static final long serialVersionUID = 2454454363100273885L;
@ManagedProperty("#{FACES_CONFIG}")
private ResourceBundle facesConfig;
//private transient ResourceBundle facesConfig;
....
private Map<String,Language> languagesMap;
private Map<String,Theme> themesMap;
....
public FacesResource(){
}
@PostConstruct
public void init(){
System.out.println("*** FacesResource init ....");
try{
....
this.initLanguages();
this.initThemes();
....
}catch(Exception ex){
ex.printStackTrace();
}
}
public String getConfigurationAttribute(String attributeKey){
return this.facesConfig.getString(attributeKey);
}
// ... other methods & getter/setter ...etc
}
更新:
FacesResource Bean 中的 ResourceBundle 独立于 Request Locale
,所以在 ApplicationScoped Bean 中加载它不是问题,但是
因为我access/inject(作为@ManagedProperty)这个ApplicationScoped Bean在其他SessionScoped Bean中,应该被序列化,这意味着所有属性(包括resourceBundle)也应该被序列化,在这里我遇到了 Serialization/Deserializazion
的问题
@BalusC:如果我喜欢你在回答中的建议:ResourceBundle.getBundle("com.example.text")
,我必须提供 Bundle 的 baseName。但这正是我想要避免的。我不想在 java 源代码中硬编码静态路径),因此当路径更改时(最不可能,但对于案例),我不想更改 Java 源代码中的路径代码但仅在面孔中-config.xml.
并且我不能使用 FacesContext.getCurrentInstance().getApplication().getResourceBundle(facesContext, "bundleVarName");
因为我的 Bean 标记为 eager=true,这意味着 facesContext
是 NULL此刻!
不能在不可序列化的类型上使用@ManagedProperty。
它是本地化字符串的资源包吗?
读这个:http://www.mkyong.com/jsf2/jsf-2-0-and-resource-bundles-example/
FacesContext facesContext = FacesContext.getCurrentInstance();
ResourceBundle resourceBundle = facesContext.getApplication()
.getResourceBundle(facesContext, "bundleName");
i think, JSF handles pre-defined(in faces-config.xml) ResourceBundles as ApplicationScoped beans.
没有。它们由 ResourceBundle
API 本身管理。 JSF 只是根据请求的区域设置在每个请求的基础上解析它们(否则它会影响访问 Web 应用程序的任何用户的语言!)。因此,它们本质上是请求范围的。但这一切都与序列化无关。 ResourceBundle
class 根本就没有打算序列化。它只是懒惰地将包加载到 Java 的内存中。
你最好也这样做。如果它在反序列化后变为 null
则延迟加载它。您只是不应该评估 #{FACES_CONFIG}
,因为它取决于请求区域设置。如果你只能使用 JSF <resource-bundle><var>
,那么你最好通过 Application#getResourceBundle()
加载它们。提供了 FACES_CONFIG
的资源包 var 名称,这是一个示例:
private transient ResourceBundle facesConfig;
public ResourceBundle getFacesConfig() {
if (facesConfig == null) {
FacesContext context = FacesContext.getCurrentInstance();
facesConfig = context.getApplication().getResourceBundle(context, "FACES_CONFIG");
}
return facesConfig;
}
顺便说一句,变量名facesConfig
很容易混淆。即表示代表faces-config.xml
.
的内容
另请参阅:
- java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException
首先,抱歉我的英语不好!
在以下托管 Bean (ApplicationScoped) 中,我将 ResourceBundle(.properties) 作为 @ManagedProperty 进行访问。 ResourceBundle 对象不可序列化,所以我在 Eclipse/Tomcat 控制台中收到一个错误,指出该对象不能 serialized/de-serialized.. 等等
Exception loading sessions from persistent storage java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.util.PropertyResourceBundle
我对这个问题有 2 个问题:
- 我认为,JSF 将预定义的(in faces-config.xml)
ResourceBundles
处理为 ApplicationScoped bean。这意味着(如果我理解正确的话),这个 Object/Bean (ResourceBundle) 以某种方式存储在文件中的某个地方(持久存储)。现在,由于ResourceBundle
不可序列化,那么它以哪种格式存储?以及 JSF 如何提供这样的服务 "Beans"?序列化对象以字节形式存储在文件中,那么不可序列化对象如何存储? - 在下面的示例中,我会将我的
@ManagedProperty ResourceBundle
声明为 transient(由于序列化问题),但瞬态对象不会存储在持久存储中(无状态),这是否意味着每次调用方法getConfigurationAttribute
(我使用此 resourceBundle 的地方)都会 recreate/reload ManagedPropery ResourceBundle 因为它被标记为瞬态?
非常感谢您的帮助。
@ManagedBean(name="facesResource",eager=true)
@ApplicationScoped
public class FacesResource implements Serializable{
private static final long serialVersionUID = 2454454363100273885L;
@ManagedProperty("#{FACES_CONFIG}")
private ResourceBundle facesConfig;
//private transient ResourceBundle facesConfig;
....
private Map<String,Language> languagesMap;
private Map<String,Theme> themesMap;
....
public FacesResource(){
}
@PostConstruct
public void init(){
System.out.println("*** FacesResource init ....");
try{
....
this.initLanguages();
this.initThemes();
....
}catch(Exception ex){
ex.printStackTrace();
}
}
public String getConfigurationAttribute(String attributeKey){
return this.facesConfig.getString(attributeKey);
}
// ... other methods & getter/setter ...etc
}
更新:
FacesResource Bean 中的 ResourceBundle 独立于 Request
Locale
,所以在 ApplicationScoped Bean 中加载它不是问题,但是因为我access/inject(作为@ManagedProperty)这个ApplicationScoped Bean在其他SessionScoped Bean中,应该被序列化,这意味着所有属性(包括resourceBundle)也应该被序列化,在这里我遇到了 Serialization/Deserializazion
的问题
@BalusC:如果我喜欢你在回答中的建议:
ResourceBundle.getBundle("com.example.text")
,我必须提供 Bundle 的 baseName。但这正是我想要避免的。我不想在 java 源代码中硬编码静态路径),因此当路径更改时(最不可能,但对于案例),我不想更改 Java 源代码中的路径代码但仅在面孔中-config.xml.并且我不能使用
FacesContext.getCurrentInstance().getApplication().getResourceBundle(facesContext, "bundleVarName");
因为我的 Bean 标记为 eager=true,这意味着facesContext
是 NULL此刻!
不能在不可序列化的类型上使用@ManagedProperty。
它是本地化字符串的资源包吗?
读这个:http://www.mkyong.com/jsf2/jsf-2-0-and-resource-bundles-example/
FacesContext facesContext = FacesContext.getCurrentInstance();
ResourceBundle resourceBundle = facesContext.getApplication()
.getResourceBundle(facesContext, "bundleName");
i think, JSF handles pre-defined(in faces-config.xml) ResourceBundles as ApplicationScoped beans.
没有。它们由 ResourceBundle
API 本身管理。 JSF 只是根据请求的区域设置在每个请求的基础上解析它们(否则它会影响访问 Web 应用程序的任何用户的语言!)。因此,它们本质上是请求范围的。但这一切都与序列化无关。 ResourceBundle
class 根本就没有打算序列化。它只是懒惰地将包加载到 Java 的内存中。
你最好也这样做。如果它在反序列化后变为 null
则延迟加载它。您只是不应该评估 #{FACES_CONFIG}
,因为它取决于请求区域设置。如果你只能使用 JSF <resource-bundle><var>
,那么你最好通过 Application#getResourceBundle()
加载它们。提供了 FACES_CONFIG
的资源包 var 名称,这是一个示例:
private transient ResourceBundle facesConfig;
public ResourceBundle getFacesConfig() {
if (facesConfig == null) {
FacesContext context = FacesContext.getCurrentInstance();
facesConfig = context.getApplication().getResourceBundle(context, "FACES_CONFIG");
}
return facesConfig;
}
顺便说一句,变量名facesConfig
很容易混淆。即表示代表faces-config.xml
.
另请参阅:
- java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException