I have Spring Boot (1.5.7.RELEASE) web application, which contains spring-boot-starter-web dependency, which transitively pulls in org.hibernate:hibernate-validator:5.3.5.Final
I have Spring MVC mapping {code:java} public ... processEvent(@Valid @RequestBody UpstreamEvent event) {} {code}
When the application is deployed to Tomcat, validation works. When the application is deployed to Weblogic, the application throws ClassCastException
When the web request comes in, the input gets validated by Validator and uses hibernate validator (HV) to get the job done. HV calls {code:java} Persistence.getPersistenceUtil().isLoaded( traversableObject, traversableProperty.getName() ); {code} in {code:java} JPATraversableResolver.isReachable {code} Then {code:java} Persistence.getProviders(); {code} is called, whereas in Tomcat there is only 1 Hibernate provider, in weblogic there are 4 (hibernate one kept atop): * org.hibernate.jpa.HibernatePersistenceProvider * org.eclipse.persistence.jpa.PersistenceProvider * org.apache.openjpa.persistence.PersistenceProviderImpl * kodo.persistence.PersistenceProviderImpl
Code in Persistence#PersistenceUtil
{code:java} new PersistenceUtil() { public boolean isLoaded(Object entity, String attributeName) { List<PersistenceProvider> providers = Persistence.getProviders(); for ( PersistenceProvider provider : providers ) { final LoadState state = provider.getProviderUtil().isLoadedWithoutReference( entity, attributeName ); if ( state == LoadState.UNKNOWN ) continue; return state == LoadState.LOADED; } for ( PersistenceProvider provider : providers ) { final LoadState state = provider.getProviderUtil().isLoadedWithReference( entity, attributeName ); if ( state == LoadState.UNKNOWN ) continue; return state == LoadState.LOADED; } return true; } {code}
tries to iterate through all providers, but second one blows up with exceptions:
{noformat} javax.validation.ValidationException: HV000041: Call to TraversableResolver.isReachable() threw an exception. at org.hibernate.validator.internal.engine.ValidatorImpl.isReachable(ValidatorImpl.java:1652) at org.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1628) at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:612) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:583) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:527) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:495) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:460) at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:410) at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:207) at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:118) at org.springframework.boot.autoconfigure.web.WebMvcValidator.validate(WebMvcValidator.java:69) at org.springframework.validation.DataBinder.validate(DataBinder.java:891) {noformat}
{noformat} Caused by: java.lang.ClassCastException: org.eclipse.persistence.jpa.PersistenceProvider cannot be cast to javax.persistence.spi.PersistenceProvider at javax.persistence.Persistence$1.isLoaded(Persistence.java:110) at org.hibernate.validator.internal.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:47) at org.hibernate.validator.internal.engine.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:128) at org.hibernate.validator.internal.engine.resolver.CachingTraversableResolverForSingleValidation.isReachable(CachingTraversableResolverForSingleValidation.java:36) at org.hibernate.validator.internal.engine.ValidatorImpl.isReachable(ValidatorImpl.java:1643) {noformat}
The prioritization of classes in weblogic.xml doesn't help out here. For the sake of completeness, I also provide my weblogic.xml content:
{noformat} <?xml version='1.0' encoding='UTF-8'?> <weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<container-descriptor> <prefer-web-inf-classes>false</prefer-web-inf-classes> <prefer-application-packages> <package-name>com.google.*</package-name> <package-name>javax.persistence.*</package-name> <package-name>javax.persistence.spi*</package-name> <package-name>org.apache.commons.*</package-name> <package-name>org.hibernate.*</package-name> <package-name>javax.validation.*</package-name> <package-name>org.jboss.logging.*</package-name> <package-name>com.fasterxml.classmate.*</package-name> <package-name>org.joda.*</package-name> <package-name>org.springframework.*</package-name> <package-name>org.slf4j.*</package-name> <package-name>ch.qos.logback.*</package-name> <package-name>org.objectweb.asm.*</package-name> <package-name>antlr.*</package-name> <package-name>javassist.*</package-name> </prefer-application-packages> </container-descriptor>
<context-root>/mer-web/</context-root>
<charset-params> <input-charset> <resource-path>*</resource-path> <java-charset-name>UTF-8</java-charset-name> </input-charset> </charset-params>
</weblogic-web-app> {noformat}
I added similar issue on StackOverflow: https://stackoverflow.com/questions/46894495/hibernate-validator-weblogic-12c-classcastexception-when-validating-spring-mvc
Do you happen to know how to overcome this issue? My assumption is that HV could look up persistence providers in different way. |
|