11.6. About Using External Services
Any of the pluggable contracts we have seen so far allows for the injection of a service. The most notable example being the
DirectoryProvider. The full list is:
DirectoryProviderReaderProviderOptimizerStrategyBackendQueueProcessorWorkerErrorHandlerMassIndexerProgressMonitor
Some of these components need to access a service which is either available in the environment or whose lifecycle is bound to the
SearchFactory. Sometimes, you even want the same service to be shared amongst several instances of these contract.
11.6.1. Exposing a Service
To expose a service, you need to implement
org.hibernate.search.spi.ServiceProvider<T>. T is the type of the service you want to use. Services are retrieved by components via their ServiceProvider class implementation.
11.6.1.1. Managed Services
If your service ought to be started when Hibernate Search starts and stopped when Hibernate Search stops, you can use a managed service. Make sure to properly implement the
start and stop methods of ServiceProvider. When the service is requested, the getService method is called.
Example 11.7. Example of ServiceProvider implementation
public class CacheServiceProvider implements ServiceProvider<Cache> { private CacheManager manager; public void start(Properties properties) { //read configuration manager = new CacheManager(properties); } public Cache getService() { return manager.getCache(DEFAULT); } void stop() { manager.close(); } }
Note
The
ServiceProvider implementation must have a no-arg constructor.
To be transparently discoverable, such service should have an accompanying
META-INF/services/org.hibernate.search.spi.ServiceProvider whose content list the (various) service provider implementation(s).
Example 11.8. Content of META-INF/services/org.hibernate.search.spi.ServiceProvider
com.acme.infra.hibernate.CacheServiceProvider
11.6.1.2. Provided Services
Alternatively, the service can be provided by the environment bootstrapping Hibernate Search. In this case, the
CacheContainer instance is not managed by Hibernate Search and the start/stop methods of its corresponding service provider will not be used.
Note
Provided services have priority over managed services. If a provider service is registered with the same
ServiceProvider class as a managed service, the provided service will be used.
The provided services are passed to Hibernate Search via the
SearchConfiguration interface (getProvidedServices).
Important
Provided services are used by frameworks controlling the lifecycle of Hibernate Search and not by traditional users.
If a service instance must be retrieved from the environment, use registry services like JNDI and look the service up in the provider.
11.6.2. Using a Service
Many of the pluggable contracts of Hibernate Search can use services. Services are accessible via the
BuildContext interface.
Example 11.9. Example of a Directory Provider Using a Cache Service
public CustomDirectoryProvider implements DirectoryProvider<RAMDirectory> { private BuildContext context; public void initialize( String directoryProviderName, Properties properties, BuildContext context) { //initialize this.context = context; } public void start() { Cache cache = context.requestService( CacheServiceProvider.class ); //use cache } public RAMDirectory getDirectory() { // use cache } public stop() { //stop services context.releaseService( CacheServiceProvider.class ); } }
When you request a service, an instance of the service is served to you. Make sure to then release the service. This is fundamental. Note that the service can be released in the
DirectoryProvider.stop method if the DirectoryProvider uses the service during its lifetime or could be released right away of the service is simply used at initialization time.