Skip to content
Advertisement

Java9 modules : How to execute Provider based on some priority of execution?

I am using java 9 modules to implement provider , i have multiple providers for service interface. I want to provide some priority for providers for their execution insted of using findFirst();

JavaScript

I have service-interface modules as below ,

ServiceInterface.Java

JavaScript

module-info.java

JavaScript

I have provider-module which has two implementation for service interface ,

Provider1.java

JavaScript

Provider2.java

JavaScript

module-info.java

JavaScript

Now , i have consumer-module which will use ServiceLoader to load Provider. instead of using findFirst() to load service provider. I want to load based on some priority example i want to load Provider2 then i should be able to load instead of loading provider 1.

Consumer.java

JavaScript

any suggestions for implementing priority to load Providers instead of using findFirst().

Advertisement

Answer

The Designing services section of the ServiceLoader documentation says

[…] there are two general guidelines:

  • A service should declare as many methods as needed to allow service providers to communicate their domain-specific properties and other quality-of-implementation factors. An application which obtains a service loader for the service may then invoke these methods on each instance of a service provider, in order to choose the best provider for the application.

  • A service should express whether its service providers are intended to be direct implementations of the service or to be an indirection mechanism such as a “proxy” or a “factory”. Service providers tend to be indirection mechanisms when domain-specific objects are relatively expensive to instantiate; in this case, the service should be designed so that service providers are abstractions which create the “real” implementation on demand. For example, the CodecFactory service expresses through its name that its service providers are factories for codecs, rather than codecs themselves, because it may be expensive or complicated to produce certain codecs.

Following this guideline, we can simply add a priority query method to the interface to match bullet one and keep the other stuff as-is, as the instantiation is not expensive.

JavaScript
JavaScript
JavaScript

But since this is just an example, your use case might involve expensive-to-create service instances. In that case, you can follow the recommendation to separate the service provider interface and the actual service, as most JDK services do.

JavaScript
JavaScript

Of course, the module-info declarations have to be adapted to provide or use ServiceProviderInterface instead of ServiceInterface. The use case will now look like

JavaScript

to the same outcome but not instantiating Provider1.ActualService(). Only the actually used Provider2.ActualService() is instantiated.


Alternatively to the guidelines of the documentation, you can use the first approach with an annotation instead of the priority() method.

JavaScript
JavaScript
JavaScript
JavaScript

This can avoid potentially expensive instantiations without the need to deal with two interfaces, however, the properties you can declare and query prior to the instantiation are limited to compile time constants.

On the other hand, this approach can be used to extend an already existing service framework, as the module providing the interface doesn’t need to know about the annotation(s). It’s possible to introduce them as an extended contract between certain service implementations and use sites.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement