【问题标题】:SEAM localeSelector not injectingSEAM localeSelector 未注入
【发布时间】:2013-04-12 14:49:40
【问题描述】:

我正在使用 SEAM 2 的 LocaleSelector 在我的应用程序中设置区域设置,它可以正常工作

我还使用 JAWR 的 i18n 消息生成器将消息作为 Javascript 变量提供,按照说明 here 我创建了一个解析当前语言环境的类,以便 JAWR 加载正确的消息包,这是我的代码

@Name("localeResolver")
public class LocaleResolver implements net.jawr.web.resource.bundle.locale.LocaleResolver {

    @In private LocaleSelector localeSelector;

    public LocaleResolver() {}

    @Override
    public String resolveLocaleCode(HttpServletRequest request) {
        if(localeSelector!=null){
            System.out.println("locale selector is not null setting jawr locale to "+localeSelector.getLocaleString());
            return localeSelector.getLocaleString();
        }else{
            System.out.println("locale selector is null setting jawr locale to "+request.getLocale().toString());
            return request.getLocale().toString();
        }   
    }
}

但 localeSelector 始终为 null,因此它使用 request.getLocale 进行设置,这似乎是浏览器的默认语言环境(如果用户希望手动覆盖则不好)

为什么注入的localeSelector会为null,我已经成功注入到其他组件了?

谢谢

更新:web.xml 内容

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <context-param>
  <param-name>facelets.DEVELOPMENT</param-name>
  <param-value>true</param-value>
 </context-param>
 <context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.xhtml</param-value>
 </context-param>
 <context-param>
  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
  <param-value>server</param-value>
 </context-param>
 <context-param>
  <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
  <param-value>com.sun.facelets.FaceletViewHandler</param-value>
 </context-param>
 <context-param>
  <param-name>org.jboss.jbossfaces.JSF_CONFIG_NAME</param-name>
  <param-value>Mojarra-1.2</param-value>
 </context-param>
 <context-param>
  <param-name>org.richfaces.SKIN</param-name>
  <param-value>plain</param-value>
 </context-param>
 <!-- Richfaces Global Ajax Que,
     added as getting concurrent conversation access exceptions
     from unknown locations -->
 <context-param>
  <param-name>org.richfaces.queue.global.enabled</param-name>
  <param-value>true</param-value>
 </context-param>

 <filter>
  <filter-name>Seam Filter</filter-name>
  <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
 </filter>

 <!-- Seam -->
 <listener>
  <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
 </listener>
 <servlet>
  <servlet-name>Seam Resource Servlet</servlet-name>
  <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
 </servlet>
 <!-- JSF -->
 <servlet>
  <servlet-name>Document Store Servlet</servlet-name>
  <servlet-class>org.jboss.seam.document.DocumentStoreServlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <!-- jawr Servlet -->

 <servlet>
    <servlet-name>JavascriptServlet</servlet-name>
    <servlet-class>net.jawr.web.servlet.JawrServlet</servlet-class>

    <!-- Location in classpath of the config file -->
    <init-param>
        <param-name>configLocation</param-name>
        <param-value>/jawr.properties</param-value>
    </init-param>
    <init-param>
        <param-name>mapping</param-name>
        <param-value>/jsJawrPath/</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>JavascriptServlet</servlet-name>
    <url-pattern>/jsJawrPath/*</url-pattern>
</servlet-mapping>


 <!-- Store item Servlet -->
 <servlet-mapping>
  <servlet-name>Document Store Servlet</servlet-name>
  <url-pattern>*.csv</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>Document Store Servlet</servlet-name>
  <url-pattern>*.xls</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>Document Store Servlet</servlet-name>
  <url-pattern>*.pdf</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.xhtml</url-pattern>
 </servlet-mapping>
 <!-- 120 min session timeout -->
 <session-config>
  <session-timeout>120</session-timeout>
 </session-config>
 <!-- Mime types -->
 <mime-mapping>
  <extension>htc</extension>
  <mime-type>text/x-component</mime-type>
 </mime-mapping>
 <!-- Index file def -->
 <welcome-file-list>
  <welcome-file>index.xhtml</welcome-file>
 </welcome-file-list>
 <!-- Server error page -->
 <error-page>
  <error-code>500</error-code>
  <location>/error.xhtml</location>
 </error-page>
 <!-- File not found page -->
 <error-page>
  <error-code>404</error-code>
  <location>/resourceNotFound.xhtml</location>
 </error-page>
 <!-- Unathorised pages -->
 <error-page>
  <error-code>401</error-code>
  <location>/notAuthorised.xhtml</location>
 </error-page>
 <error-page>
  <error-code>403</error-code>
  <location>/index.xhtml</location>
 </error-page>
</web-app>

【问题讨论】:

    标签: java jsf seam seam2 jawr


    【解决方案1】:

    您的LocaleResolver 被作为单独的Servlet 请求的一部分调用,该请求未通过标准JSF Servlet 进行路由。发生这种情况时,Seam 拦截器不会被触发,也不会发生双射。

    为了解决这个问题,你需要通知Seam关于传入的请求,以便它正确设置它的上下文(注意你需要关闭生命周期,所以返回获取的值是不行的):

    ServletLifecycle.beginRequest(request);
    String locale = LocaleSelector.instance().getLocaleString();
    ServletLifecycle.endRequest();
    return locale;
    

    或者,您可以使用提供的 ContextualHttpServletRequest 类,它以更简洁的方式执行相同的操作(在 finally 块中关闭生命周期等):

    final String[] locale = new String[1];
    new ContextualHttpServletRequest(request) {
        @Override
        public void process() throws ServletException, IOException {
            // Do the things that need to access Seam contexts within this function:
            locale[0] = LocaleSelector.instance().getLocaleString();
        }
    }.run();
    return locale[0];
    

    【讨论】:

    • 很好,有用的信息,你能解释一下为什么这比我目前正在做的手动查找更好吗? (然后我可以将其标记为正确)
    • 由于在您的代码中localeSelector 始终为null,因此您始终在请求中设置区域设置。该值不一定与应用程序的区域设置相同。例如,假设我的浏览器的默认语言环境为“it”,而您的应用程序不支持此设置,则默认为“en”。在这种情况下,localeSelector 将返回 enrequest.getLocale() 将返回 it。此外,我提供的解决方案允许您使用 any Seam 组件,而不仅仅是语言环境。
    • 我尝试了这两个建议,它们都导致页面加载时出现“无活动应用程序上下文”异常。另外要澄清的是,我的答案中的 localeSelector 并不总是空的,我只添加了 request.getLocale() 作为后备。不过我还是想正确获取LocaleSelector,您有什么建议吗?
    • 奇怪,你的web.xml是怎么组织的?
    【解决方案2】:

    好的,我通过手动查找组件而不是使用以下注入解决了这个问题

    public class LocaleResolver implements net.jawr.web.resource.bundle.locale.LocaleResolver {
    
        public LocaleResolver() {}
    
        public String resolveLocaleCode(HttpServletRequest request) {
            //Lookup component manually as not part of SEAM lifecycle
            LocaleSelector localeSelector = (LocaleSelector)Contexts.getSessionContext().get(LocaleSelector.class);
            if(localeSelector!=null){
                return localeSelector.getLocaleString();
            }else{
                return request.getLocale().toString();
            }   
        }
    }
    

    我相信这是因为实现的 LocaleResolver 不是接缝生命周期的一部分,因此不会被拦截,但我可能是错的......?

    【讨论】:

    • 不完全是,问题是LocaleResolver 没有被称为Seam 组件并且不会发生双射。如果它不在生命周期中,则在检索组件时会出现错误(Context is not active 行中的内容)。请注意,您可以使用静态帮助方法LocaleSelector.instance() 获取LocaleSelector 组件。这个特性是许多其他默认 Seam 组件共有的。
    • @EmirCalabuch 感谢您的提示,我尝试了以下方法: private static LocaleSelector localeSelector = LocaleSelector.instance();但我得到“没有活动的会话上下文”你能扩展我如何在我的 POJO 中使用 LocaleSelector.instance() 吗?还是必须是 SEAM 组件?
    • 这澄清了您的问题,作为答案发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 2011-01-25
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多