Spring-boot-1.3.1
Resin-4.0.47
部署Spring?Boot到Resin后,出現(xiàn)異常:
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?
異常的大概問題就是菊匿,創(chuàng)建'userWoundedArmyMapper'時失敗跌捆,因為無法注入sqlSessionFactory失敗抄瓦。
而sqlSessionFactory在MybatisAutoConfiguration中創(chuàng)建的煞额,故需要先創(chuàng)建MybatisAutoConfiguration栈顷,在創(chuàng)MybatisAutoConfiguration時失敗,因為無法注入MybatisProperties漓概。
創(chuàng)建MybatisProperties后漾月,初始化MybatisProperties失敗,因為它的初始化是由ConfigurationPropertiesBindingPostProcessor進行初始化的胃珍,在ConfigurationPropertiesBindingPostProcessor中梁肿,使用了Javax?Validation,在應(yīng)用中使用了Hibernate的Validation實現(xiàn)觅彰,找不到ConfigurationImpl的定義吩蔑。
進行遠(yuǎn)程Debug,并結(jié)合jvminspect.jar填抬,發(fā)現(xiàn)Resin/lib目錄下存在validation-api和hibernate-validator烛芬,且版本與項目引用的版本不一致。
ConfigurationImpl類飒责,發(fā)現(xiàn)靜態(tài)代碼塊
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存在多個版本導(dǎo)致ConfigurationImpl靜態(tài)代碼塊執(zhí)行失敗,發(fā)現(xiàn)Resin/lib下存在jboss-logging宏蛉,于是問題明朗了遣臼。
由于重復(fù)的validation-api、hibernate-validator檐晕、jboss-logging暑诸,導(dǎo)致加載ConfigurationImpl后進行靜態(tài)代碼塊執(zhí)行時,引用jboss?logger錯誤辟灰,導(dǎo)致ConfigurationImpl出現(xiàn)NoClassDefFoundError个榕。
解決方法:刪除Resin/lib下的validation-api、hibernate-validator芥喇、jboss-loggingjar包西采。
之后,又出現(xiàn)了另外的問題:
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]
經(jīng)過查看Resin源碼继控,發(fā)現(xiàn)這是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使用了類屬性械馆,而不是參數(shù)listeners,導(dǎo)致異常武通,這個BUG只能等后續(xù)版本修復(fù)霹崎。
于是,我下載了未引入這個BUG的Resin-4.0.44版本冶忱,運行之后尾菇,又發(fā)現(xiàn)了新的問題:
Custom?bean?class?'{0}'?is?not?public.??Bean?classes?must?be?public,?concrete,?and?have?a?zero-argument?constructor.
經(jīng)過查看Resin源碼,發(fā)現(xiàn)com.caucho.server.dispatch.FilterConfigImpl的setFilterClass方法:
@DisableConfig
public?void?setFilterClass(Class?filterClass)
{
this._filterClass?=?filterClass;
Config.validate(this._filterClass,?Filter.class);
}
這又是Resin的一個BUG,當(dāng)直接添加Filter對象到ServletContext時派诬,Resin還會去驗證Filter的CLass是不是public的類劳淆。這個Bug在Resin-4.0.46中修復(fù)了。
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,導(dǎo)致Resin目前沒有一個版本可以完美支持Spring?Boot缆八,只能換Tomcat和Jetty了曲掰。