springspring-bootclassloaderresin

Spring Boot application WAR deployment to Resin 4: is there a way to use app (WEB-INF/lib) classloader first?


I'm trying to deploy Spring Boot app as a WAR to Caucho Resin 4. I'm getting an error on hitting the app:

org.springframework.context.ApplicationContextException: Unable to
start embedded container; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name
'org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration'
: Bean instantiation via constructor failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate
[org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration$
$EnhancerBySpringCGLIB$$58b91c9d]: Constructor threw exception; nested
exception is
org.springframework.beans.factory.UnsatisfiedDependencyException: Error
creating bean with name 'dashboardResource' defined in file
[/var/resin/webapps/itasng-0.8.5/WEB-INF/classes/gov/nih/cit/itasng/
rest/DashboardResource.class]: Unsatisfied dependency expressed through
constructor parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException: Error
creating bean with name 'payPeriodRepository' defined in file
[/var/resin/webapps/itasng-0.8.5/WEB-INF/classes/gov/nih/cit/itasng/
persistence/PayPeriodRepository.class]: Unsatisfied dependency
expressed through constructor parameter 0; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name
'org.springframework.orm.jpa.SharedEntityManagerCreator#0': Cannot
resolve reference to bean 'entityManagerFactory' while setting
constructor argument; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'entityManagerFactory' defined in class path resource
[org/springframework/boot/autoconfigure/orm/jpa/
HibernateJpaAutoConfiguration.class]: Invocation of init method failed;
nested exception is java.lang.NoSuchMethodError:
javax.persistence.Table.indexes()[Ljavax/persistence/Index; at
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext
.onRefresh(EmbeddedWebApplicationContext.java:137)
~[spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
...

It's obvious that this is a typical class-loading issue: classes loaded by the parent class-loader from Resin lib (e.g. lib/javaee-16.jar) cause issues for the app built with newer versions (e.g. WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar).

Most app servers that I used before have a setting somewhere in a vendor specific –web.xml descriptor to switch the classloader order so that WEB-INF/lib classes load first. However, the Resin docs don't really have an easy answer if such an option exists.

Is there a way to switch class loading order in Resin 4 or what would be an alternative solution?


Solution

  • In Resin 4.0 there is no way to use app classloader first.

    Potential workarounds for related classloading issues could involve using the <jvm-classpath> which has precedence over Resin's classpath.

    An example use case is to use later versions of JPA instead of JPA 2.0, which is deployed out-of-the-box.

    Documentation reference:

    http://www.caucho.com/resin-4.0/admin/cluster-config.xtp#jvm-classpath