"Provider org.hibernate.validator.HibernateValidator not a subtype" error during service discovery

Description

While using DefaultProviderResolver, we get the following error when there are multiple validator implementations in classpath and one ahead in the classpath is not class loader compatible with the api jar:

I have tracked the error down to beanvalidation-api/src/main/java/javax/validation/Validation.java where it is not handling ServiceConfigurationError correctly. This code was introduced in BVAL-298. There was a discussion about ServiceConfigurationError in as well. The correct thing to do is to ignore the ServiceConfigurationError and try the next available provider. I am attaching a patch to this effect.

Environment

None

Activity

Show:
Sanjeeb Sahoo
December 10, 2012, 7:03 AM

The patch fails the unit tests, but after looking at the tests, I believe the tests are at fault. So, change the test when accept the patch.

Sanjeeb Sahoo
December 10, 2012, 8:38 AM
Edited

The underlying service discovery issue manifests differently when an earlier version of bean validator is used which didn't use java.util.ServiceLoader:

See for more details about how the earlier code looked like.

Hardy Ferentschik
December 10, 2012, 10:07 AM

Could you describe your precise setup? Which providers do you have on the classpath?

Hardy Ferentschik
December 10, 2012, 10:51 AM

So what are you saying here. You want to use the Bean Validation API version 1.1, but have say Hibernate Validator 4 (Bean Validation 1.0 compatible) and Hibernate Validator 5 (BV 1.1 compatible) on the classpath at the same time? That does not sound like a good idea to me.

Sanjeeb Sahoo
January 16, 2013, 9:44 PM

Sorry for the delayed response. I didn't get notification from JIRA for some reason.

In the presence of a module system, it is possible to have more than one provider configured in the system. See the scenario below where we see the problem:

Each jar is a module (say OSGi bundle).

m1.jar depends on BV_1.0.jar
m2.jar depends on BV_1.1.jar
TCL have both BV_1.0.jar and BV_2.0.jar

m2.jar calls BV.getValidator() or the equivalent factory method.

Since m2.jar depends on BV_1.1.jar, it uses BV 1.1 API. BV uses TCL while using ServiceLoader to find a provider. ServiceLoader upon finding META-INF/services of BV_1.0.jar, tries to load it and throws a ServiceConfigurationError since the loaded class does not implement the interface requested by user. ServiceLoader actually allows it to be used to try the next available provider. Check the documentation of java.util.ServiceLoader.iterator(). Instead of trying the next available provider, BV returns immediately. It does not attempt to recover from situations where it can. That's the bug IMO. If you want to call it an RFE, I am fine too as long as you address it.

Can you tell me why you think trying the next provider is actually a bad thing? What would have gone wrong in such a case?

Thanks,
Sahoo

Assignee

Hardy Ferentschik

Reporter

Sanjeeb Sahoo

Labels

None

Feedback Requested

None

Feedback Requested By

None

backPortable

None

Suitable for new contributors

None

Pull Request

None

backportDecision

None

backportReEvaluate

None

Components

Fix versions

Affects versions

Priority

Critical
Configure