-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
There must always be a default CachingProvider #269
Comments
When an application that is designed to expect that only single CachingProvider is available is deployed into an environment that defines zero or two or more CachingProviders, an exception should be thrown as this is considered a deployment failure. Similarly when an application that is designed to expect multiple CachingProviders is deployed into an environment that consists of none or only a single CachingProvider, an exception should also be thrown as this too is considered a deployment failure. Given the above requirements, the current semantics are considered correct. ASIDE: We strongly believe that it should not be up to the (optional) Caching (helper class) to decide arbitrarily which CachingProvider instance to return. For example: Since the CachingProvider makes use of the Java ServiceLoader to aid in the location of the CachingProvider implementations, to guarantees can be made in terms of the order in which they are returned. ie: it's not possible to just return the "first" from the iterator provided by the ServiceLoader. Additionally, ServiceLoader provides no concept of a "default". Should an application not care about which or the number of CachingProviders, it should make that choice explicit, by randomly picking on of those returned by the Caching.getCachingProviders() method. Should an application require that there is only one "default" CachingProvider defined, it should use the Caching.getCachingProvider() method (or one of the helpers defined on the Caching class). Should an application require multiple CachingProviders, it should use the appropriate Caching.getCachingProviders(...) method. Should an application require a specifically named implementation, it should use the CachingProviders.getCachingProvider(String, ...) method. Should an application require a specific implementation of a CachingProvider, it should use the CachingProviders.getCachingProvider(String method). The existing Caching interface, which is optional, covers all of these use cases. |
Since JCache 1.0 doesn't support Java EE, there really isn't any "deployment". How would you know whether an application expects a single CachingProvider or multiple Is the resolution of this issue that Caching.getCachingProvider() will always return a CachingProvider? |
We don't and the specification should not be required to know. Just as JDBC, JMS, JPA et al specifications don't know the number of databases, MOMs etc, JCache doesn't know and shouldn't know for whether an application requires multiple CachingProviders. Should an application be required to work in a multi-CachingProvider environment / deployment, only the application developer can truly determine the required semantics, just like JDBC, JMS, JPA et al. As discussed with the leads, the specification is not in a position to reasonably choose a "default" CachingProvider for an application when it doesn't know. Perhaps with CDI this would be possible, but it's not currently. This concept has been outlined Issue #208 for the next release.
While this would be ideal, we've considered this many times. We've also attempted to implement it but there are some fundamental problems (as mentioned above). In terms of the implementation, it's fundamentally not possible using a Java ServiceLoader because of the non-deterministic manner in which the generation and iteration of Services (CachingProviders) are produced. i.e: While we could easily say "return the first CachingProvider" from the iteration a Java ServiceLoader provides, that CachingProvider could be very different between calls, especially if there are numerous threads, especially between executions of an application (that we proven). The problem is that there is no requirement for the Java ServiceLoader to return a list of Services (CachingProviders) defined in a service meta-inf file in either the order in which they are listed, or in fact in any order. This means assumptions about the order can't be made. It also means we can't assume the first defined in a file will be returned first. If the ServiceLoader mechanism provided the ability to define a "default" Service, we could use that, but alas it doesn't. Hence why we introduced the ability to do so using a system property! e.g: If an application wants to use a known CachingProvider, or a deployment wants to specify a specific default CachingProvider to use, there's a useful system property defined to do so. -Djavax.cache.cachingprovider=xxxx As outlined above, the JCache specification provides numerous means to work around this inherent defect with Java ServiceLoaders. Should an application want to work in a multiple-CachingProvider environment, it should be developed in a manner to do so - just as in solutions like JPA must also (that also uses the ServiceLoader paradigm). PS: The only possible way to work around this is to abstract out the notion of how CachingProviders are determined. While one may consider the introduction of yet-another-level-of-indirection a reasonable solution (i.e: a CachingProviderFactory), it doesn't really solve the problem as ultimately the said factory also has to make a choice, with the same information we currently have. |
There's no definition of deployment in the JCache spec, and Java SE defines no requirements related to deployment. If some JCache product defines deployment, it's outside the scope of an spec, and thus completely non-portable. Your resolution to this issues suggests that something would detect at the unspecified deployment time that an application requires more than one caching provider. If there's no way to do that, then that's not really a resolution to this issue. In Java SE, the only safe way to use the Caching methods that return a default caching provider is to set the system property to the caching provider you want, or to control all the components in your application to ensure that only a single caching provider is included. While it seems likely that we'll want to define a way to use injection to get the default caching provider in Java EE, it might be nice if the Caching method worked there as well. As long as the container has the ability to ensure that the application always gets a default caching provider, that's fine. |
While the specification permits multiple CachingProviders to be loaded, in the typical mode a developer naturally assumes there will be a single default.
However if an application server / environment / deployment is configured using multiple CachingProviders, an application assuming a single default Caching Provider would fail.
To resolve this we need to ensure that a default CachingProvider is always available, regardless of the application server / environment / deployment.
This will not require a change of the API signatures, just the semantics of existing signatures and tests.
The text was updated successfully, but these errors were encountered: