美文网首页
Spring Boot部署到Resin遇到的问题

Spring Boot部署到Resin遇到的问题

作者: 邹极客 | 来源:发表于2016-01-24 00:53 被阅读0次

    Spring-boot-1.3.1

    Resin-4.0.47

    部署Spring Boot到Resin后,出现异常:

    2016-01-23 23:41:02,334 [WARN ] o.s.b.f.s.DefaultListableBeanFactory - Bean creation exception on FactoryBean type check: org.springframework.beans.factory.U

    nsatisfiedDependencyException: Error creating bean with name 'userWoundedArmyMapper' defined in URL [jar:file:/opt/resin-test/webapps/rabbit-webapp/WEB-INF/l

    ib/rabbit-dao-0.0.1-SNAPSHOT.jar!/com/qiyun/persistence/UserWoundedArmyMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFacto

    ry': : Error creating bean with name 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration': Injection of autowired dependencies failed; nested exc

    eption is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.mybatis.spring.boot.autoconfigure.MybatisProperties

    org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration.properties; nested exception is org.springframework.beans.factory.BeanCreationException: Error

    creating bean with name 'mybatis.CONFIGURATION_PROPERTIES': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not ini

    tialize class org.hibernate.validator.internal.engine.ConfigurationImpl; nested exception is org.springframework.beans.factory.BeanCreationException: Error c

    reating bean with name 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration': Injection of autowired dependencies failed; nested exception is org.

    springframework.beans.factory.BeanCreationException: Could not autowire field: private org.mybatis.spring.boot.autoconfigure.MybatisProperties org.mybatis.sp

    ring.boot.autoconfigure.MybatisAutoConfiguration.properties; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean

    with name 'mybatis.CONFIGURATION_PROPERTIES': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class

    org.hibernate.validator.internal.engine.ConfigurationImpl

    -  -

    2016-01-23 23:41:02,894 [WARN ] o.s.b.f.s.DefaultListableBeanFactory - Bean creation exception on FactoryBean type check: org.springframework.beans.factory.U

    nsatisfiedDependencyException: Error creating bean with name 'userWoundedArmyMapper' defined in URL [jar:file:/opt/resin-test/webapps/rabbit-webapp/WEB-INF/l

    ib/rabbit-dao-0.0.1-SNAPSHOT.jar!/com/qiyun/persistence/UserWoundedArmyMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFacto

    ry': : Error creating bean with name 'sqlSessionFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested excep

    tion is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sqlSessionFactory': Requested bean is currently in

    creation: Is there an unresolvable circular reference?

    异常的大概问题就是,创建'userWoundedArmyMapper'时失败,因为无法注入sqlSessionFactory失败。

    而sqlSessionFactory在MybatisAutoConfiguration中创建的,故需要先创建MybatisAutoConfiguration,在创MybatisAutoConfiguration时失败,因为无法注入MybatisProperties。

    创建MybatisProperties后,初始化MybatisProperties失败,因为它的初始化是由ConfigurationPropertiesBindingPostProcessor进行初始化的,在ConfigurationPropertiesBindingPostProcessor中,使用了Javax Validation,在应用中使用了Hibernate的Validation实现,找不到ConfigurationImpl的定义。

    进行远程Debug,并结合jvminspect.jar,发现Resin/lib目录下存在validation-api和hibernate-validator,且版本与项目引用的版本不一致。

    ConfigurationImpl类,发现静态代码块

    static{

    Version.touch();

    }

    private static final Log log = LoggerFactory.make();

    LoggerFactory类的make方法:

    public static Log make() {

    Throwable t =newThrowable();

    StackTraceElement directCaller = t.getStackTrace()[1];

    returnLogger.getMessageLogger( Log.class, directCaller.getClassName() );

    }

    其中使用了jboss的logging,很有可能是jboss logging存在多个版本导致ConfigurationImpl静态代码块执行失败,发现Resin/lib下存在jboss-logging,于是问题明朗了。

    由于重复的validation-api、hibernate-validator、jboss-logging,导致加载ConfigurationImpl后进行静态代码块执行时,引用jboss logger错误,导致ConfigurationImpl出现NoClassDefFoundError。

    解决方法:删除Resin/lib下的validation-api、hibernate-validator、jboss-loggingjar包。

    之后,又出现了另外的问题:

    java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

    at java.util.ArrayList.rangeCheck(ArrayList.java:635) ~[na:1.7.0_67]

    at java.util.ArrayList.get(ArrayList.java:411) ~[na:1.7.0_67]

    at com.caucho.server.webapp.WebApp.hasListener(WebApp.java:2197) ~[resin.jar:4.0.47]

    at com.caucho.server.webapp.WebApp.addListenerObject(WebApp.java:2148) ~[resin.jar:4.0.47]

    at com.caucho.server.webapp.WebApp.addListener(WebApp.java:2108) ~[resin.jar:4.0.47]

    经过查看Resin源码,发现这是resin-4.0.45版本中引入的bug:

    /**

    * Returns true if a listener with the given type exists.

    */

    public boolean hasListener(ArrayList listeners, Class listenerClass)

    {

    for (int i = 0; i < listeners.size(); i++) {

    Object listener = _listeners.get(i);

    if (listener.getClass().equals(listenerClass)) {

    return true;

    }

    }

    return false;

    }

    其中Object listener = _listeners.get(i);的_listeners使用了类属性,而不是参数listeners,导致异常,这个BUG只能等后续版本修复。

    于是,我下载了未引入这个BUG的Resin-4.0.44版本,运行之后,又发现了新的问题:

    Custom bean class '{0}' is not public.  Bean classes must be public, concrete, and have a zero-argument constructor.

    经过查看Resin源码,发现com.caucho.server.dispatch.FilterConfigImpl的setFilterClass方法:

    @DisableConfig

    public void setFilterClass(Class filterClass)

    {

    this._filterClass = filterClass;

    Config.validate(this._filterClass, Filter.class);

    }

    这又是Resin的一个BUG,当直接添加Filter对象到ServletContext时,Resin还会去验证Filter的CLass是不是public的类。这个Bug在Resin-4.0.46中修复了。

    servlet: drop instantiation check for instances of servlets and filters (#5934)

    @DisableConfig

    public void setFilterClass(Class filterClass)

    {

    _filterClass = filterClass;

    if (_filter == null)

    Config.validate(_filterClass, Filter.class);

    }

    为了解决这个问题,必须使用Resin-4.0.46以后的版本。

    综合Resin上诉2个BUG,导致Resin目前没有一个版本可以完美支持Spring Boot,只能换Tomcat和Jetty了。

    相关文章

      网友评论

          本文标题:Spring Boot部署到Resin遇到的问题

          本文链接:https://www.haomeiwen.com/subject/euprkttx.html