-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Thu Nov 13, 2014 10:53 pm 
Newbie

Joined: Thu Jan 04, 2007 8:22 am
Posts: 12
Hi,

I am running into some classpath issues with my application which led me to look into the code of the DefaultTraversableResolver class in Hibenate Validator 4.3.2. Specifically, I'm looking into the "detectJPA()" method, which doesn't seem to be able to differentiate between JPA 2 and 1. It seems to me that a "return" statement is missing that is causing this issue.

Here's the code from lines 98 to 110:
Code:
      // try to invoke the method to make sure that we are dealing with a complete JPA2 implementation
      // unfortunately there are several incomplete implementations out there (see HV-374)
      try {
         Object persistence = run( NewInstance.action( persistenceClass, "persistence provider" ) );
         ReflectionHelper.getValue( persistenceUtilGetter, persistence );
      }
      catch ( Exception e ) {
         log.debugf(
               "Unable to invoke %s.%s. Inconsistent JPA environment. All properties will per default be traversable.",
               PERSISTENCE_CLASS_NAME,
               PERSISTENCE_UTIL_METHOD
         );
      }



Now, shouldn't this log.debug statement be followed by a return to abort the JPA detection process while concluding that a full-featured implementation of JPA2 is not available? But this is not the case, the detection proceeds assuming a 2.0 version. Here are the directly following lines:
Code:
      log.debugf(
            "Found %s on classpath containing '%s'. Assuming JPA 2 environment. Trying to instantiate JPA aware TraversableResolver",
            PERSISTENCE_CLASS_NAME,
            PERSISTENCE_UTIL_METHOD
      );


Naturally, when the conclusion is reached that JPA 2.0 is available while it's not, the JPATraversableResolver is used, which blows up when it calls:
Code:
         return Persistence.getPersistenceUtil().isLoaded( traversableObject, traversableProperty.getName() );


Am I right about this or is there something that I missed? Is this a well-known issue? Is there a way to work around this and force Validator not to use the JPATraversableResolver?


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Mon Nov 17, 2014 10:49 am 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 388
Hi,

Yes, I think that's a bug indeed. Can you open an issue in our tracker (https://hibernate.atlassian.net/browse/HV/?selectedTab=com.atlassian.jira.jira-projects-plugin:summary-panel) for this, please?

For the time being, you simply can set a custom traversable resolver when bootstrapping your validator. Check out the reference guide (https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/) for the different options for doing so. Out of interest, which JPA provider is this? It would be interesting to know which exception is raised here actually.

Thanks,

--Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Mon Nov 17, 2014 7:26 pm 
Newbie

Joined: Thu Jan 04, 2007 8:22 am
Posts: 12
Thanks Gunnar, I was unaware of the fact that I can use a custom TraversableResolver; this provides a neat solution to my problem.

However, since I've posted my question, I realized that although the code is indeed buggy as you confirmed, it's not really the cause of the issue. In my case, the JPA 2 implementation is, indeed, on the classpath as I packaged it within my application and instructed WebSphere to load parent classes last, so I'm not being affected by the bug.

The root cause of my problem is that the WebSphere JPA provider is still registered and IBM has decided not to make this provider implement the proper SPI interface "javax.persistence.spi.PersistenceProvider". In the implementation of PersistenceUtil in the Persistence class, there's this code:
Code:
         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;
         }

Since the provider cannot be cast to PersistenceProvider, I get the following error:
Quote:
javax.validation.ValidationException: Error in TraversableResolver.isReachable() for nswrta.wbs.command.BookingCommand@7188a0
at org.apache.bval.jsr303.ConstraintValidation.isReachable(ConstraintValidation.java:245) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.ConstraintValidation.validate(ConstraintValidation.java:166) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.ConstraintValidation.validate(ConstraintValidation.java:141) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.util.ValidationHelper.validateProperty(ValidationHelper.java:233) ~[bval-core-0.5.jar:0.5]
at org.apache.bval.util.ValidationHelper.validateBean(ValidationHelper.java:216) ~[bval-core-0.5.jar:0.5]
at org.apache.bval.jsr303.ClassValidator.validateBeanNet(ClassValidator.java:393) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.ClassValidator.validate(ClassValidator.java:149) ~[bval-jsr303-0.5.jar:0.5]
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:102) ~[spring-context-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.validation.DataBinder.validate(DataBinder.java:772) ~[spring-context-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.validate(RequestResponseBodyMethodProcessor.java:115) ~[spring-webmvc-3.2.10.R
ELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:101) ~[spring-webmvc-3
.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-3.2.10.RELEA
SE.jar:3.2.10.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157) ~[spring-web-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124) ~[spring-web-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-3.2.10.RELE
ASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) ~[spring-webmvc-3.2.10.REL
EASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:685) ~[spring-webmvc-3.2.10.RELEASE
.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) ~[spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:919) ~[spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851) ~[spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953) [spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855) [spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:738) [javax.j2ee.servlet.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829) [spring-webmvc-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831) [javax.j2ee.servlet.jar:na]
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1583) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1523) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:131) [com.ibm.ws.webcontainer.jar:na]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.REL
EASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RE
LEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.2.5.RELEASE.jar:3
.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [spring-security-web-3.2
.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155) [spring-security-web-3.2.5.RELE
ASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [spring-security-web-3
.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.5.RELEASE.jar:3.2
.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:70) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:59) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343) [spring-web-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260) [spring-web-3.2.10.RELEASE.jar:3.2.10.RELEASE]
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:885) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:865) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:175) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:863) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:182) [com.ibm.ws.webcontainer.jar:na]
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455) [com.ibm.ws.runtime.jar:na]
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384) [com.ibm.ws.runtime.jar:na]
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83) [com.ibm.ws.runtime.jar:na]
at com.ibm.ws.tcp.channel.impl.WorkQueueManager.requestComplete(WorkQueueManager.java:557) [na:CC70.CF [a0849.02]]
at com.ibm.ws.tcp.channel.impl.WorkQueueManager.attemptIO(WorkQueueManager.java:607) [na:CC70.CF [a0849.02]]
at com.ibm.ws.tcp.channel.impl.WorkQueueManager.workerRun(WorkQueueManager.java:984) [na:CC70.CF [a0849.02]]
at com.ibm.ws.tcp.channel.impl.WorkQueueManager$Worker.run(WorkQueueManager.java:1069) [na:CC70.CF [a0849.02]]
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1550) [com.ibm.ws.runtime.jar:na]
Caused by: java.lang.ClassCastException: com.ibm.websphere.persistence.PersistenceProviderImpl cannot be cast to javax.persistence.spi.PersistenceProvider
at javax.persistence.Persistence$1.isLoaded(Persistence.java:92) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final]
at org.apache.bval.jsr303.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:34) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:60) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.resolver.CachingTraversableResolver.isReachable(CachingTraversableResolver.java:82) ~[bval-jsr303-0.5.jar:0.5]
at org.apache.bval.jsr303.ConstraintValidation.isReachable(ConstraintValidation.java:241) ~[bval-jsr303-0.5.jar:0.5]
... 74 common frames omitted


I'll update this thread once I've tried the solution and can confirm that it does resolve the issue.


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Tue Nov 18, 2014 4:20 am 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 388
Hi,

Apparently you're not working with Hibernate Validator but with Apache Validation (see the "org.apache.bval.jsr303" package in the stacktrace).

The ClassCastException you see likely originates from the fact that you have two versions of the JPA API on your classpath. I assume that IBM's provider does implement PersistenceProvider it only is not assignment compatible to the other version of the JPA API you provide (note, class identity is based on the FQN and the classloader).

I think the best would be if you could replace the JPA provider within the application server instead of packaging Hibernate as part of the app (not sure whether/how that's doable with WebSphere). You also may try to omit the JPA API JAR from your deployment unit.

Hth,

--Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Tue Nov 18, 2014 6:45 pm 
Newbie

Joined: Thu Jan 04, 2007 8:22 am
Posts: 12
Hi Gunnar,

Actually, I am using Hibernate Validator, I probably copied the wrong stack trace from one of the instances where I was trying to using Apache BVal to see if that will fix the problem. Of course it didn't, so I switched back.

JPA detection in Apache BVal is, surprisingly, almost the same as the one in Hibernate Validator, even the class names are the same - you guys should consider suing them. Just kidding :)

But again, as I realized, it's not really the JPA detection that's causing my problem.

Anyway, thanks for your suggestion. At the moment, we're sharing this WAS instance with other applications, so I cannot mess with the JPA provider. If we were in our own instance, the best solution would be to install the JPA 2 feature pack for WAS. For the time being, with your suggested solution (a custom TraversableResolver), things seem to be working fine.

Thanks again.


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Tue Nov 18, 2014 8:14 pm 
Newbie

Joined: Thu Jan 04, 2007 8:22 am
Posts: 12
Sorry, one more question: Are you saying that the provider is not assignment compatible with the JPA interface because it was loaded using a different class loader?


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Mon Nov 24, 2014 3:52 am 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 388
Basically yes. If the JPA provider is loaded by some classloader from the container and the JPA API classes are loaded via the application classloader, the CCE is what I'd expect.

--Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
 Post subject: Re: Is JPA detection in validator 4.3.2 buggy?
PostPosted: Wed Dec 31, 2014 4:52 am 
Newbie

Joined: Wed Dec 31, 2014 4:41 am
Posts: 2
For the http://www.teragoldeu.com/ time being, you simply can set a custom traversable resolver when bootstrapping your validator.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.