1.1. What is a Service?

A services provides a certain types of functionality, in a pluggable manner. Specifically, they are interfaces defining certain functionality and then implementations of those Service contract interfaces. The interface is known as the Service role; the implementation class is known as the Service implementation. The pluggability comes from the fact that the Service implementation adheres to contract defined by the interface of the Service role and that consumers of the Service program to the Service role, not the implementation.

Generally speaking, users can plug in alternate implementations of all standard Service roles (overriding); they can also define additional services beyond the base set of Service roles (extending).

Let’s look at an example to better define what a Service is. Hibernate needs to be able to access JDBC Connections to the database. The way it obtains and releases these Connections is through the ConnectionProvider service. The Service is defined by the interface (service role) org.hibernate.engine.jdbc.connections.spi.ConnectionProvider which declares methods for obtaining and releasing the Connections. There are then multiple implementations of that Service contract, varying in how they actually manage the Connections.

Internally Hibernate always references org.hibernate.engine.jdbc.connections.spi.ConnectionProvider rather than specific implementations in consuming the Service (we will get to producing the Service later when we talk about registries). Because of that fact, other ConnectionProvider Service implementations could easily be plugged in.

There is nothing revolutionary here; programming to interfaces is generally accepted as good programming practice. What’s interesting is the ServiceRegistry and the pluggable swapping of the different implementors.

1.1.1. Service contracts

The basic requirement for a Service is to implement the marker interface org.hibernate.service.Service. Hibernate uses this internally for some basic type safety.

The Service can also implement a number of optional life-cycle related contracts:

org.hibernate.service.spi.Startable

allows the Service impl to be notified that it is being started and about to be put into use.

org.hibernate.service.spi.Stoppable

allows the Service impl to be notified that it is being stopped and will be removed from use.

org.hibernate.service.spi.ServiceRegistryAwareService

allows the Service to be injected with a reference to the registry that is managing it. See Service dependencies for more details.

org.hibernate.service.spi.Manageable

marks the Service as manageable in JMX provided the JMX integration is enabled. This feature is still incomplete.

Other

The different registry implementations also understand additional optional contracts specific to that registry. For details, see the details for each registry in What is a ServiceRegistry?.

1.1.2. Service dependencies

Services are allowed to declare dependencies on other services using either of two approaches.

@org.hibernate.service.spi.InjectService

Any method on the Service implementation class accepting a single parameter and annotated with @InjectService is considered requesting injection of another service.

By default, the type of the method parameter is expected to be the Service role to be injected. If the parameter type is different than the Service role, the serviceRole attribute of the @InjectService annotation should be used to explicitly name the role.

By default, injected services are considered required, that is the start up will fail if a named dependent Service is missing. If the Service to be injected is optional, the required attribute of the @InjectService annotation should be declared as false (default is true).

org.hibernate.service.spi.ServiceRegistryAwareService

The second approach is a pull approach where the Service implements the optional Service interface org.hibernate.service.spi.ServiceRegistryAwareService which declares a single injectServices method.

During startup, Hibernate will inject the org.hibernate.service.ServiceRegistry itself into services which implement this interface. The Service can then use the ServiceRegistry reference to locate any additional services it needs.