我想创建一个Producer,它可以将java.util.ResourceBundle注入任何类,以便轻松获取本地化的Strings。我的ResourceBundle-Producer看起来像这样:
public class ResourceBundleProducer {
@Inject
public Locale locale;
@Inject
public FacesContext facesContext;
@Produces
public ResourceBundle getResourceBundle() {
return ResourceBundle.getBundle("/messages", locale )
}
}
Locale和FacesContext的注入工作(从Seam 3 Alpha Source中获取相应的生成器)。但不幸的是,ResourceBundle不是Serializable,因此无法以这种方式生成。当我尝试访问一个调用使用我的ResourceBundle的bean的JSF页面时,我从Weld得到以下错误:
Caused by: org.jboss.weld.IllegalProductException: WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: org.jboss.weld.bean-/D:/Program Files (x86)/GlassFish-Tools-Bundle-For-Eclipse-1.2/glassfishv3/glassfish/domains/teachernews/applications/teachernews/-ProducerMethod-services.producers.ResourceBundleProducer.getResourceBundle()\\nInjection Point\: field web.PersonHome.bundle
有没有办法让我的ResourceBundleResolver工作?或者是否有其他机制来获得类似的功能? 提前谢谢!
修改
好的,我会花一些难以获得的积分;) 对于这个问题,也会接受一个很好的解决方法!
我有另一个例子,创建一个Producer不起作用:一个FlashProducer。还无法生成FacesContext-Flash,因为Flash不可序列化。
答案 0 :(得分:25)
好吧,首先,ResourceBundle 不可序列化。见here。信息很明确
无法生成非序列化实例,以便注入钝化bean的非瞬态字段
钝化豆 ???我认为 web.PersonHome 是有状态会话Bean或@ConversationScoped bean。我对吗 ???如果是这样,您应将您的捆绑属性标记为瞬态
private transient @Inject ResourceBundle bundle;
答案 1 :(得分:3)
根据Arthur接受的答案中的评论主题。我跟着this blog以及this one进行了钝化/激活实验。实验证明MrD评论说,瞬态属性在激活时将为NULL。因此,为了处理具有钝化能力的bean的非可序列化成员属性(即,sessioncoped,conversationscoped和有状态会话bean),我建议采用以下解决方案:
private ResourceBundle bundle;
@PostConstruct
@PostActivate
public void getResourceBundle() {
bundle = ResourceBundle.getBundle("/messages", locale );
}
此解决方案确保每次进入READY状态时都会重新初始化非序列化属性成员。
要解决的最后一个问题是注入一个SLF4j Logger,它在slf4j 1.5.3和I quote之前是不可序列化的:
从SLF4J 1.5.3版开始,记录器实例在序列化后继续存在。 因此,主机类的序列化不再需要任何特殊的 即使将记录器声明为实例变量也是如此。
因此,只要您的slf4j依赖关系是1.5.3或更高版本,您就可以安全地注入SLF4j Logger,如下所示:
@Produces
@LogbackLogger
public Logger produceLogger(InjectionPoint injectionPoint){
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
假设你宣布了限定符:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LogbackLogger {
}
然后在具有钝化能力的bean中,注入如下:
@Inject
@LogbackLogger
private Logger logger;