【问题标题】:Spring DispatcherServlet context instantiation error in liferay 6.1.1Liferay 6.1.1中的Spring DispatcherServlet上下文实例化错误
【发布时间】:2013-07-31 15:10:04
【问题描述】:

我正在将我的 webapp 的 liferay 版本从 6.1.0 迁移到 6.1.1(使用来自 liferay patchers community 的 6.1.1-ga2 版本,并且我的 web 服务在以前工作的地方有一点问题.

我使用PortalDelegateServlet 来实例化一个spring DispatcherServlet。

我遇到的问题是我的 servlet (myWS-servlet.xml) 的 spring 上下文是在 PortletContextLoaderListener 的应用程序上下文之前实例化的(也尝试使用 spring 中的 ContextLoaderListener,同样的问题) 而且,由于我的控制器使用来自主要应用程序上下文的服务(在实例化 DispatcherServlet 时未加载),因此 spring 无法自动装配它们。

奇怪的是,如果我重新部署我的 portlet,问题就解决了。

你知道我该如何解决这个问题吗?


我的 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>banner-portlet</display-name>
<jsp-config>
    <taglib>
        <taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>
        <taglib-location>/WEB-INF/tlds/liferay-portlet.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://liferay.com/tld/theme</taglib-uri>
        <taglib-location>/WEB-INF/tlds/liferay-theme.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://liferay.com/tld/portlet</taglib-uri>
        <taglib-location>/WEB-INF/tlds/liferay-portlet-ext.tld</taglib-location>
    </taglib>
</jsp-config>

<servlet>
    <servlet-name>liferayWSdispatcher</servlet-name>
    <servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
    <init-param>
        <param-name>servlet-class</param-name>
        <param-value>org.springframework.web.servlet.DispatcherServlet</param-value>
    </init-param>
    <init-param>
        <param-name>sub-context</param-name>
        <param-value>rest-api</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>liferayWSdispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<listener>
    <listener-class>com.liferay.portal.spring.context.PortletContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:applicationContext.xml</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>
<context-param>
    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
</context-param>
<!-- Instruct Mojarra to utilize JBoss-EL instead of the EL implementation
    provided by the servlet container. -->
<!-- was used only for admin portlets but make calendar portlet crash
<context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
-->
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

<listener>
    <listener-class>com.liferay.faces.portal.listener.StartupListener</listener-class>
</listener>


<!-- MyFaces will not initialize unless a servlet-mapping to the Faces Servlet
    is present. -->
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>



<context-param>
    <param-name>portalContextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext-velocity-tool.xml</param-value>
</context-param>

我的 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<context:component-scan base-package="be.maximede">
    <context:exclude-filter type="regex" expression="be.maximede.webservice.*"/>
</context:component-scan>

我的 myWS-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<context:component-scan base-package="be.maximede.webservice"/>

<mvc:annotation-driven />

【问题讨论】:

    标签: spring spring-mvc liferay liferay-6


    【解决方案1】:

    我知道这个帖子已经有一年多了。但我想帮助人们省去一些麻烦。我和我的同事花了一周的时间试图弄清楚为什么我们不能在使用 spring 和 PortalDelegateServlet + DispatcherServlet 的 portlet 控制器之前加载 spring 服务。

    正如另一位发帖人评论的那样,这与问题http://issues.liferay.com/browse/LPS-29103 有一些但没有直接关系。它确实与在 liferay 中初始化 Servlet 的方式以及 Liferay 如何处理 web.xml 重写有关。

    Liferay 重写在 web.xml 中定义的所有侦听器,并将它们放入如下上下文参数中:

    <context-param>
        <param-name>portalListenerClasses</param-name>
        <param-value>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener,org.springframework.web.context.ContextLoaderListener</param-value>
    </context-param>
    

    然后创建自己的侦听器(或未显示,PluginContextListener):

    <listener>
        <listener-class>com.liferay.portal.kernel.servlet.SecurePluginContextListener</listener-class>
    </listener>
    

    这个 SecurePluginContextListener 然后加载上下文并连接起来。问题是,有时,SecurePluginContextListener 会首先使用 Web 应用程序上下文初始化 PortalDelegateServlet,然后它会转到 portalListenerClasses 中的 init 方法。因此,portlet 控制器中的任何 AutoWired 内容都缺少它们的所有依赖项(来自应用程序上下文的服务)。

    为了解决这个问题,我们放弃了在 web.xml 中声明 PortalDelegateServlet,并创建了一个自定义的 ServletContextListener,它会新建一个 PortalDelagateServlet 和 ServletConfig,将相同的参数传递给 spring 的 DispatcherServlet。之所以如此,是因为,我们让 Liferay 在 portalListenerClasses 中完成所有加载。重写后的 web.xml 如下所示:

    <context-param>
        <param-name>portalListenerClasses</param-name>
        <param-value>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener,org.springframework.web.context.ContextLoaderListener, com.domain.CustomContextListener</param-value>
    </context-param>
    

    CustomContextListener 将实现 ServletContextListener 中的方法。 在 CustomContextListener 的 contextInitialized(...) 方法中,我们只是以编程方式创建与 web.xml 中相同的 ServletConfig(实现 ServletConfig 的内部类)。然后我们创建一个 pds = new PortalDelegateServlet() 并调用 pds.init(customServletConfig)

    【讨论】:

    • 谢谢!它解决了我的问题!生产环境中不再有双重部署;)
    • 您好,您有机会发布 CustomContextListener 和 CustomServletConfig 类的实现吗?我没有运气实施这些。谢谢。
    【解决方案2】:

    对于 Liferay 6.1.1,这是一个已知问题:

    http://issues.liferay.com/browse/LPS-29103

    【讨论】:

    • 我看到了这个问题,但是,我正在使用来自 Icepatchers 的修补 Liferay 版本,其中包含修复程序
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多