【问题标题】:Upgrading web-app from Spring 3.2.2 to Spring 5.1.5 (context initialization failed - BeanCreationException)将 web-app 从 Spring 3.2.2 升级到 Spring 5.1.5(上下文初始化失败 - BeanCreationException)
【发布时间】:2020-01-17 12:21:32
【问题描述】:

我正在升级一个在 Java6 + Spring 3.2.2 + Jersey 1.19 + Tomcat6 上正常工作的旧 Web 应用程序,以便使用每个组件的更新版本(Java8 + Spring 5.1.5 + Jersey 2.28 + Tomcat9),但是当我尝试启动它时出现问题。该应用在Tomcat启动过程中失败,特别是在Spring ApplicationContext的初始化过程中,我收到了以下消息:

INFO: Initializing Spring root WebApplicationContext
org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean': Invocation of init method failed; nested exception is java.lang.NullPointerException
org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean': Invocation of init method failed; nested exception is java.lang.NullPointerException
....
Caused by: 
at my.package.utils.AppAssets.getContext()

出现错误的部分代码如下:

public static ApplicationContext getContext() {
    if (ctx == null) {
      ctx = ApplicationContextProvider.getApplicationContext();
    }
    return ctx;
}

特别是,ApplicationContextProvider 是一个在应用程序中获取 ApplicationContext 的有用类,如下所示:

package my.package.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware {

  private static ApplicationContext ctx = null;

  public static ApplicationContext getApplicationContext() {
    return ctx;
  }

  public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    this.ctx = ctx;
  }
}

applicationContext.xml 是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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-2.5.xsd">


    <bean id="applicationContextProvider" class="my.package.utils.ApplicationContextProvider">
    </bean>

    <bean id="Resources" class="my.package.resources.Resources">
        <property name="iniFile" value="/WEB-INF/properties/config.properties">
        </property>
    </bean>

</beans>

我的 web.xml 配置是:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>MYWEBAPP</display-name>

    <!-- PATH SERVER - CONFIGURATION -->
  <context-param>
    <param-name>realPathName</param-name>
    <param-value>rootPath</param-value>
  </context-param>

    <!-- LOG4J - CONFIGURATION -->
  <context-param>
    <param-name>log4j-config-location</param-name>
    <param-value>WEB-INF/properties/log4j.properties</param-value>
  </context-param>

    <!-- LISTENER CONTEXT CONFIGURATION -->
  <listener>
    <listener-class>my.package.context.ContextListener</listener-class>
  </listener>

    <!-- SPRING - CONFIGURATION -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext*.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- JERSEY - CONFIGURATION - FILTER FOR SPRING AND JSPs -->
  <filter>
    <filter-name>jersey</filter-name>
    <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>my.package.rest</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
      <param-value>/WEB-INF/pages</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.server.mvc.jsp.JspMvcFeature</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.servlet.filter.staticContentRegex</param-name>
      <param-value>/(images|js|styles|resources|(WEB-INF/pages))/.*</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>jersey</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

如果有用的话,我还附上previous web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID"
    version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    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">

    <display-name>MYWEBAPP</display-name>


    <!-- PATH SERVER - CONFIGURATION -->
    <context-param>
        <param-name>realPathName</param-name>
        <param-value>rootPath</param-value>
    </context-param>

    <!-- LOG4J - CONFIGURATION -->
    <context-param>
        <param-name>log4j-config-location</param-name>
        <param-value>WEB-INF/properties/log4j.properties</param-value>
    </context-param>

    <!-- LISTENER CONTEXT CONFIGURATION -->
    <listener>
        <listener-class>my.package.context.ContextListener</listener-class>
    </listener>

    <!-- RESTFUL WEB APPLICATION -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext*.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- JERSEY - FILTER FOR SPRING AND JSPs -->
    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</filter-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>my.package.rest</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
            <param-value>/WEB-INF/pages</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
            <param-value>/(images|js|styles|resources|(WEB-INF/pages))/.*</param-value>
        </init-param>
    </filter>
        <filter-mapping>
            <filter-name>jersey</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

最后,Spring 似乎未能初始化 ApplicationContext,因为 util 类的 getter 返回 null 但我不明白为什么:使用旧版本成功初始化了上下文,这要归功于 ApplicationContextAware 功能。我的怀疑是 Spring 和 Jersey 之间的交互配置错误,这会阻止 ApplicationContextAware 正常工作。我做错了什么?

感谢您的帮助

【问题讨论】:

  • 您一次完成了很多事情。一次做一件事并采取小步骤。不要立即从 Spring 3.x 转到 5.x,采取中间步骤。请记住,您有一个正在运行的应用程序,每个小的更改都应该导致一个正在运行/工作的应用程序。一次性完成所有这些操作不会让您知道究竟是什么东西出了问题。

标签: java spring web.xml tomcat9


【解决方案1】:

首先我要说的是之前的配置已经包含了扫描包和使用注解的设置(我只在sn-ps中省略了报告)。所以,我找到了一个在 ApplicationContextProvider 上使用 @Component 注释的解决方案,而不是在 applicationContext.xml 中定义它

package my.package.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

  private static ApplicationContext context = null;

  public static ApplicationContext getApplicationContext() {
    return context;
  }

  public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    System.out.println("ApplicationContextProvider - SETTING SPRING CONTEXT!!!");
    context = ctx;
    System.out.println("ApplicationContextProvider - APP GOT SPRING CONTEXT!!!");
  }
}

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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">


    <bean id="Resources" class="it.wmg.gambling.commons.base.resources.Resources">
        <property name="iniFile" value="/WEB-INF/properties/config.properties">
        </property>
    </bean>

</beans>

现在服务器可以正常启动并正常工作,但我还不明白为什么这个解决方案可以解决问题。有人有想法吗?

【讨论】:

    【解决方案2】:

    尝试如下更改 bean 属性:

    旧值

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        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-2.5.xsd">
    
    

    新价值:

    <?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:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
    

    【讨论】:

    • 感谢您的错误报告@bytingbee。这只是我写帖子时的打字错误。即使我改正了问题也没有解决
    • 尝试根据更新后的答案更改 bean 属性。抱歉,我无法在此处将代码作为评论发布,因此我编辑了原始答案。
    【解决方案3】:

    您是否尝试过将 spring-beans-2.5.xsd 制作为 spring-beans.xsd。
    建议使用无版本。

    【讨论】:

    • 我刚刚尝试过,但我仍然收到同样的错误
    猜你喜欢
    • 2017-03-17
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    相关资源
    最近更新 更多