Java Spring 应用程序在一个系统上运行,但在几乎相同的系统上却死亡

Java Spring 应用程序在一个系统上运行,但在几乎相同的系统上却死亡

介绍

我在 RHEL 上运行第三方 Java Spring 应用程序,该应用程序拒绝在从某个 RHEL 6.5 模板克隆的机器上运行。它在启动时会因虚假异常而死机(见下文)。

所讨论的软件版本:

RHEL 6.5 
Tomcat 7.0.41 (rolled our own, almost vanilla)
Spring 3.1.4.RELEASE (shipped with application)
java version "1.7.0_65"
OpenJDK Runtime Environment (rhel-2.5.1.2.el6_5-x86_64 u65-b17)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)
SELinux Status: Permissive

我已经更改了类名以保护无辜者,但我非常怀疑实际软件是否重要。

将 tomcat 和实例目录从损坏的盒子原样复制到我的 Linux 桌面并运行它作品

虽然我描述的设置被视为测试环境,但我确实在我们的生产机上遇到了这个问题,我必须从 DVD 干净地安装它才能使问题消失。提到的设置是我在 puppet 模块开发期间再次遇到问题的设置,并设法保存并重现了这个问题。

设置

应用程序使用的数据库保存在本地(h2)并在 tomcat 中设置server.xml

2 个 RHEL 6.5 模板,均为 vagrant 设置。

  • 损坏的模板:直接从 DVD 进行最小安装。采取手动设置步骤来设置 Puppet 自动签名模板,以及 Vagrant 模板检查表步骤。
  • 工作模板:从 DVD 启动 Kickstart 最小设置,通过 Shellscripts 自定义 Vagrant/VirtualBox(已完成packer

每个模板中的 1 个盒子是通过设置的vagrant,都应用了我们木偶大师的完全相同的木偶目录。

问题

应用程序在损坏的模板中启动时死亡,并出现以下异常:

[17.09.2014 19:34:00,290] ERROR                  ContextLoader ( 318) | Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'soaFormFolderService' defined in file [/var/www/apps/content/tomcat/afs-forms/webapps/formserver/WEB-INF/classes/com/aforms2web/afs/formserver/service/
SoaFormFolderService.class]: Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)
[...]
Caused by: java.lang.ExceptionInInitializerError
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990)
        ... 26 more
Caused by: java.lang.NullPointerException
        at com.corp.Application.getMessageSource(Application.java:234)
        at com.corp.FooService.<clinit>(FooService.java:23)
        ... 33 more

有问题的代码如下所示:

com.corp.FooService

@Service
public class FooService
{
  protected static MessageSource messageSource = Application.getInstance().getMessageSource();

com.corp.应用程序

public class Application
{
  private static Application instance = null;

  public static Application getInstance()
  {
    if (instance == null) {
      instance = new Application();
    }
    return instance;
  }
  [...]
  public MessageSource getMessageSource()
  {
    return ((MessageSource)this.applicationContext.getBean("messageSource", MessageSource.class));
  }

它在第二个盒子里顺利运行。

什么原因可能导致这种情况发生?

调查状态

差异样式yum list installed输出:

--- pkgs.broken
+++ pkgs       
-b43-openfwwf.noarch-5.2-4.el6
-dkms.noarch-2.2.0.3-25.el6
-efibootmgr.x86_64-0.5.4-11.el6
+gcc-c++.x86_64-4.4.7-4.el6
-kernel-devel.x86_64-2.6.32-431.23.3.el6
+kernel-devel.x86_64-2.6.32-431.el6
-kernel.x86_64-2.6.32-431.23.3.el6
+libstdc++-devel.x86_64-4.4.7-4.el6
-puppet.noarch-3.7.0-1.el6
+puppet.noarch-3.7.1-1.el6

我将这些系统与 rsync 进行了比较(来自正在运行的系统):

rsync \
   --checksum -ani \
   --exclude log \
   --exclude /vagrant \
   --exclude /root \
   --exclude /proc \
   --exclude /sys \
   --exclude /selinux \
   --exclude /dev \
   --exclude /lib/modules \
   --exclude /usr/src \
   --exclude /boot \
   --delete / \
   root@broken:/ \
| grep -ve "^." \
| grep -vEie "puppet|vbox|virtualbox|var/lib/yum|/var/run|sss|var/lib/rpm|logs" 

在这里查看结果: http://paste.ubuntu.com/8367930/

我无法弄清楚弹出的哪些更改可能会对 Java Spring 应用程序产生影响。

编辑:看一下添加的有问题的代码。

答案1

您混淆了静态上下文和运行时上下文:在此初始化静态变量期间调用方法 getMessageSource。但 applicationContext 是在此之后初始化的。这就是您收到 NPE 的原因 - applicationContext 尚未初始化。

相关内容