<?xml version='1.0' encoding='utf-8' ?>

<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<chapter xml:id="services"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xi="http://www.w3.org/2001/XInclude">

    <title>Services and Registries</title>

    <para>
        Services and registries are new *as a formalized concept* starting in 4.0.  But the functionality provided by
        the different Services have actually been around in Hibernate much, much longer.  What is new is managing them,
        their lifecycles and dependencies through a lightweight, dedicated container we call a ServiceRegistry.  The
        goal of this guide is to describe the design and purpose of these Services and Registries, as well as to look at
        details of their implementations where appropriate.  It will also delve into the ways third-party integrators and
        applications can leverage and customize Services and Registries.
    </para>

    <section xml:id="services-service">
        <title>What is a Service?</title>

        <para>
            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.
        </para>

        <para>
            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).
        </para>

        <para>
            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)
            <interfacename>org.hibernate.engine.jdbc.connections.spi.ConnectionProvider</interfacename> 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.
        </para>

        <para>
            Internally Hibernate always references <interfacename>org.hibernate.engine.jdbc.connections.spi.ConnectionProvider</interfacename>
            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.
        </para>

        <para>
            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.
        </para>

        <section xml:id="services-contracts">
            <title>Service contracts</title>

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

            <para>
                The service can also implement a number of optional life-cycle related contracts:
                <itemizedlist>
                    <listitem>
                        <para>
                            <interfacename>org.hibernate.service.spi.Startable</interfacename> - allows the service
                            impl to be notified that it is being started and about to be put into use.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            <interfacename>org.hibernate.service.spi.Stoppable</interfacename> - allows the service
                            impl to be notified that it is being stopped and will be removed from use.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            <interfacename>org.hibernate.service.spi.ServiceRegistryAwareService</interfacename> - allows
                            the service to be injected with a reference to the registry that is managing it.  See
                            <xref linkend="services-dependencies"/>.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            <interfacename>org.hibernate.service.spi.Manageable</interfacename> - marks the service
                            as manageable in JMX provided the JMX integration is enabled.  This feature is still incomplete.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            The different registry implementations also understand additional optional contracts specific
                            to that registry.  For details, see the details for each registry under
                            <xref linkend="services-registry"/>
                        </para>
                    </listitem>
                </itemizedlist>
            </para>
        </section>

        <section xml:id="services-dependencies">
            <title>Service dependencies</title>
            <para>
                Services are allowed to declare dependencies on other services using either of 2 approaches.
            </para>
            <section>
                <title>@<interfacename>org.hibernate.service.spi.InjectService</interfacename></title>
                <para>
                    Any method on the service implementation class accepting a single parameter and annotated with
                    @<interfacename>InjectService</interfacename> is considered requesting injection of another service.
                </para>
                <para>
                    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 <methodname>serviceRole</methodname> attribute
                    of the <interfacename>InjectService</interfacename> annotation should be used to explicitly name the role.
                </para>
                <para>
                    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
                    <methodname>required</methodname> attribute of the <interfacename>InjectService</interfacename>
                    annotation should be declared as <literal>false</literal> (default is <literal>true</literal>).
                </para>
            </section>
            <section>
                <title><interfacename>org.hibernate.service.spi.ServiceRegistryAwareService</interfacename></title>
                <para>
                    The second approach is a pull approach where the service implements the optional service interface
                    <interfacename>org.hibernate.service.spi.ServiceRegistryAwareService</interfacename> which declares
                    a single <methodname>injectServices</methodname> method.  During startup, Hibernate will inject the
                    <interfacename>org.hibernate.service.ServiceRegistry</interfacename> itself into services which
                    implement this interface.  The service can then use the <interfacename>ServiceRegistry</interfacename>
                    reference to locate any additional services it needs.
                </para>
            </section>
        </section>
    </section>


    <section xml:id="services-registry">
        <title>What is a ServiceRegistry?</title>

        <para>
            A ServiceRegistry, at its most basic, hosts and manages Services.  Its contract is defined by the
            <interfacename>org.hibernate.service.ServiceRegistry</interfacename> interface.
        </para>

        <para>
            We already gave a basic overview and definition of services.  But services have other interesting
            characteristics as well.  Services have a lifecycle.  They have a scope.  Services might depend on other
            services.  And they need to be produced (choose using one implementation over another).  The ServiceRegistry
            fulfills all these needs.
        </para>

        <para>
            In a concise definition, the ServiceRegistry acts as a inversion-of-control (IoC) container.
        </para>

        <note>
            <para>
                Despite some recent revisionist history, Spring did not invent IoC nor dependency injection nor were
                they even the first to bring it into Java.  Projects like JBoss MicroContainer and Apache Avalon
                pre-date Spring by many years and each did IoC and dependency injection.  The concepts in ServiceRegistry
                are actually very similar to Apache Avalon.
            </para>
        </note>

        <para>
            Why not just use an existing IoC framework?  The main reason was that this had to be as light-weight and as
            small of a footprint as possible.  The initial design also had called for Services to be swappable at runtime,
            which unfortunately had to be removed due to performance problems in the proxy-based swapping-solution; the
            plan is to investigate alternate ways to achieve swap-ability with better performance at a later date.
        </para>

        <para>
            A Service is associated with a ServiceRegistry.  The ServiceRegistry scopes the Service.  The
            ServiceRegistry manages the lifecycle of the Service.  The ServiceRegistry handles injecting dependencies
            into the Service (actually both a pull and a push/injection approach are supported).  ServiceRegistries are
            also hierarchical, meaning a ServiceRegistry can have a parent ServiceRegistry.  Services in one registry
            can depend on and utilize services in that same registry as well as any parent registries.
        </para>

    </section>


    <section xml:id="services-binding">
        <title>ServiceBinding</title>

        <para>
            The association of a given Service to a given ServiceRegistry is called a binding and is represented by the
            <interfacename>org.hibernate.service.spi.ServiceBinding</interfacename> interface.  Furthermore, the specific
            contract between a ServiceBinding and the ServiceRegistry is represented by the
            <interfacename>org.hibernate.service.spi.ServiceBinding.ServiceLifecycleOwner</interfacename> interface.
        </para>

        <para>
            There are 2 ways a Service becomes associated (bound) to a ServiceRegistry.
            <itemizedlist>
                <listitem>
                    <para>
                        the Service can be directly instantiated and then handed to the ServiceRegistry
                    </para>
                </listitem>
                <listitem>
                    <para>
                        a ServiceInitiator can be given to the ServiceRegistry (which the ServiceRegistry will use if and when the Service is needed)
                    </para>
                </listitem>
            </itemizedlist>
            ServiceRegistry implementations register bindings through calls to the overloaded
            <methodname>org.hibernate.service.internal.AbstractServiceRegistryImpl#createServiceBinding</methodname>
            method accepting either a Service instance or a ServiceInitiator instance.
        </para>

        <para>
            Each specific type of registry defines its own ServiceInitiator specialization.
        </para>
    </section>


    <section xml:id="services-registry-types">
        <title>Types of ServiceRegistries</title>

        <para>
            Currently Hibernate utilizes 3 different ServiceRegistry implementations forming a hierarchy.  Each
            type is a specialization for the purpose of type-safety, but they add no new functionality.
        </para>

        <section xml:id="services-registry-boot">
            <title>BootstrapServiceRegistry</title>

            <para>
                The <interfacename>org.hibernate.boot.registry.BootstrapServiceRegistry</interfacename>
                holds 3 service and is normally built by means of the
                <classname>org.hibernate.boot.registry.BootstrapServiceRegistryBuilder</classname> factory class.
                The builder gives type safe access to customizing these 3 Services.
            </para>

            <important>
                <para>
                    This registry holds services that absolutely have to be available for most things in Hibernate to work.
                </para>
            </important>

            <para>
                In normal usage, the BootstrapServiceRegistry has no parent.
            </para>

            <para>
                The services of the BootstrapServiceRegistry cannot be extended (added to) nor overridden (replaced).
            </para>

            <section>
                <title>ClassLoaderService</title>

                <para>
                    The service role for this service is <interfacename>org.hibernate.boot.registry.classloading.spi.ClassLoaderService</interfacename>.
                </para>

                <para>
                    This service defines Hibernate's ability to interact with ClassLoaders.  The manner in which
                    Hibernate (or any library) should interact with ClassLoaders varies based on the runtime environment
                    which is hosting the application.  Application servers, OSGi containers, and other modular class
                    loading systems impose very specific class-loading requirements.  This service is provides
                    Hibernate an abstraction from this environmental complexity.  And just as importantly, it does so
                    in a centralized, swappable manner.
                </para>

                <para>
                    The specific capabilities exposed on this service include:
                    <itemizedlist>
                        <listitem>
                            <para>
                                Locating Class references by name.  This includes application classes as well as "integration" classes.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Locating resources (properties files, xml files, etc) as "classpath resources"
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Interacting with <classname>java.util.ServiceLoader</classname>, Java's own service
                                provider discovery mechanism
                            </para>
                        </listitem>
                    </itemizedlist>
                </para>
            </section>

            <section>
                <title>IntegratorService</title>

                <para>
                    The service role for this service is <interfacename>org.hibernate.integrator.spi.IntegratorService</interfacename>.
                </para>

                <para>
                    Applications, third-party integrators and others all need to integrate with Hibernate.  Historically
                    this used to require something (usually the application) to coordinate registering the pieces of each
                    integration needed on behalf of each integration.  The
                    <interfacename>org.hibernate.integrator.spi.Integrator</interfacename> contract formalized this
                    "integration SPI".  The IntegratorService manages all known integrators.
                </para>

                <tip>
                    <para>
                        The concept of "Integrator" is still being actively defined and developed.  Expect changes in
                        these SPIs.
                    </para>
                </tip>

                <para>
                    There are 2 ways an integrator becomes known.
                    <itemizedlist>
                        <listitem>
                            <para>
                                The integrator may be manually registered by calling
                                <methodname>BootstrapServiceRegistryBuilder#with(Integrator)</methodname>
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                The integrator may be discovered, leveraging the standard Java ServiceLoader
                                capability provided by the ClassLoaderService.  Integrators would simply define a file
                                named <filename>/META-INF/services/org.hibernate.integrator.spi.Integrator</filename>
                                and make it available on the classpath.  ServiceLoader covers the format of this file
                                in detail, but essentially it lists classes by FQN that implement Integrator one
                                per line.
                            </para>
                        </listitem>
                    </itemizedlist>
                </para>
            </section>

            <section>
                <title>StrategySelector</title>

                <para>
                    The service role for this service is <interfacename>org.hibernate.boot.registry.selector.spi.StrategySelector</interfacename>.
                </para>

                <para>
                    Think of this as the "short naming" service.  Historically to configure Hibernate users would
                    often need to give FQN references to internal Hibernate classes.  Of course this has caused lots
                    of problems as we refactor internal code and move these classes around into different package
                    structures.  Enter the concept of short-naming, using a well defined and well known "short name"
                    for the strategy/implementation class.
                </para>

                <para>
                    The short name mappings in this service can be managed, even by applications and integrators
                    which can be very powerful.  For more information on this aspect, see:
                    <itemizedlist>
                        <listitem>
                            <para>
                                <methodname>BootstrapServiceRegistryBuilder#applyStrategySelector</methodname>
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <methodname>BootstrapServiceRegistryBuilder#applyStrategySelectors</methodname>
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <interfacename>org.hibernate.boot.registry.selector.StrategyRegistrationProvider</interfacename>
                                via ServiceLoader discovery
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <methodname>StrategySelector#registerStrategyImplementor`</methodname> /
                                <methodname>StrategySelector#unRegisterStrategyImplementor</methodname>
                            </para>
                        </listitem>
                    </itemizedlist>
                </para>
            </section>
        </section>


        <section xml:id="services-registry-standard">
            <title>StandardServiceRegistry</title>

            <para>
                The <interfacename>org.hibernate.boot.registry.StandardServiceRegistry</interfacename> defines the
                main Hibernate ServiceRegistry, building on the BootstrapServiceRegistry (BootstrapServiceRegistry is
                its parent).  This registry is generally built using the
                <classname>org.hibernate.boot.registry.StandardServiceRegistryBuilder</classname> class.  By default
                it holds most of the Services used by Hibernate.  For the full list of Services typically held in the
                StandardServiceRegistry, see the source code of <classname>org.hibernate.service.StandardServiceInitiators</classname>.
                Some particular StandardServiceRegistry Services of note include:
            </para>

            <para>
                In normal usage, the parent of the StandardServiceRegistry is the BootstrapServiceRegistry.
            </para>

            <para>
                The services of the StandardServiceRegistry can be extended (added to) and overridden (replaced).
            </para>

            <section>
                <title>ConnectionProvider/MultiTenantConnectionProvider</title>
                <para>
                    The Service providing Hibernate with Connections as needed.  Comes in 2 distinct (and mutually
                    exclusive) roles:
                    <itemizedlist>
                        <listitem>
                            <para>
                                <interfacename>org.hibernate.engine.jdbc.connections.spi.ConnectionProvider</interfacename> -
                                provides Connections in normal environments
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                <interfacename>org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider</interfacename> -
                                provides (tenant-specific) Connections in multi-tenant environments
                            </para>
                        </listitem>
                    </itemizedlist>
                </para>
            </section>

            <section>
                <title>JdbcServices</title>
                <para>
                    <interfacename>org.hibernate.engine.jdbc.spi.JdbcServices</interfacename> is an aggregator
                    Service (a Service that aggregates other Services) exposing unified functionality around JDBC
                    accessibility.
                </para>
            </section>

            <section>
                <title>TransactionCoordinatorBuilder</title>
                <para>
                    <interfacename>org.hibernate.resource.transaction.TransactionCoordinatorBuilder</interfacename>
                    is used by Hibernate to integrate with and underlying transaction system.  It is responsible for
                    building <interfacename>org.hibernate.resource.transaction.TransactionCoordinator</interfacename>
                    instances for use by each Hibernate Session.
                </para>
            </section>

            <section>
                <title>JtaPlatform</title>
                <para>
                    When using a JTA-based TransactionCoordinatorBuilder, the
                    <interfacename>org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform</interfacename> Service
                    provides Hibernate access to the JTA TransactionManager and UserTransaction, as well handling
                    Synchronization registration.
                </para>
            </section>

            <section>
                <title>JndiService</title>
                <para>
                    The <interfacename>org.hibernate.engine.jndi.spi.JndiService</interfacename> service is used
                    by Hibernate to interact with JNDI contexts.  Hibernate's default JndiService assumes just a single
                    InitialContext.
                </para>
            </section>

            <section>
                <title>RegionFactory</title>
                <para>
                    The <interfacename>org.hibernate.cache.spi.RegionFactory</interfacename> service defines the
                    integration with third party cache implementors as second-level caching providers.
                </para>
            </section>

            <section>
                <title>SessionFactoryServiceRegistryFactory</title>
                <para>
                    <interfacename>org.hibernate.service.spi.SessionFactoryServiceRegistryFactory</interfacename> is a
                    service that acts as a factory for building the third type of ServiceRegistry
                    (the SessionFactoryServiceRegistry) which we will discuss next.  I opted for the "factory as
                    service" approach because in the current design there is really not a good exposed hook-in spot
                    for when the SessionFactoryServiceRegistry needs to be built.
                </para>
            </section>
        </section>


        <section xml:id="services-registry-sf">
            <title>SessionFactoryServiceRegistry</title>

            <para>
                <interfacename>org.hibernate.service.spi.SessionFactoryServiceRegistry</interfacename> is the 3rd
                standard Hibernate ServiceRegistry.  SessionFactoryServiceRegistry is designed to hold Services which
                need access to the SessionFactory.
            </para>

            <para>
                Typically its parent registry is the StandardServiceRegistry.
            </para>

            <note>
                <para>
                    Integrators, as it stands in 4.x, operate on the SessionFactoryServiceRegistry...
                </para>
            </note>

            <para>
                Currently SessionFactoryServiceRegistry holds just 4 Services:
            </para>

            <section>
                <title>EventListenerRegistry</title>
                <para>
                    <interfacename>org.hibernate.event.service.spi.EventListenerRegistry</interfacename> is the main
                    service managed in the SessionFactoryServiceRegistry.  The is the Service that manages all of
                    Hibernate's event listeners.  A major use-case for Integrators is to alter the listener registry.
                </para>
                <para>
                    If doing custom listener registration, it is important to understand the
                    <classname>org.hibernate.event.service.spi.DuplicationStrategy</classname> and its effect on
                    registration.  The basic idea is to tell Hibernate:
                    <itemizedlist>
                        <listitem><para>what makes a listener a duplicate</para></listitem>
                        <listitem><para>how to handle duplicate registrations (error, first wins, last wins)</para></listitem>
                    </itemizedlist>
                </para>
            </section>

            <section>
                <title>StatisticsImplementor</title>
                <para>
                    <interfacename>org.hibernate.stat.spi.StatisticsImplementor</interfacename> is the SPI portion of
                    the Statistics API; the collector portion, if you will.
                </para>
            </section>

            <section>
                <title>NativeQueryInterpreter</title>
                <para>
                    <interfacename>org.hibernate.engine.query.spi.NativeQueryInterpreter</interfacename> is the
                    service Hibernate uses for interpreting native queries.  Exists as a service mainly so that
                    integrations such as OGM can override it.
                </para>
            </section>

            <section>
                <title>CacheImplementor</title>
                <para>
                    To be honest, I have no idea why this is a service... :)
                </para>
            </section>
        </section>
    </section>

    <section xml:id="services-custom">
        <title>Custom Services</title>
        <para>
            So far we have focused on the Hibernate provided services.  But applications and integrations
            can provide their own services as well, either
            <itemizedlist>
                <listitem>
                    <para>providing a new implementation of a standard service (overriding)</para>
                </listitem>
                <listitem>
                    <para>providing a whole new service role (extending)</para>
                </listitem>
            </itemizedlist>
        </para>

        <section xml:id="services-overriding">
            <title>Custom Service Implementations (overriding)</title>
            <para>
                We discussed swappability of service implementations above.  Lets look at an example in practice.
                For the sake of illustration, lets say that we have developed a new ConnectionProvider integrating
                with the wonderful new latest-and-greatest connection pooling library.  Let's look at the steps
                necessary to make that happen.
            </para>
            <para>
                The first step is to develop the actual integration by implementing the ConnectionProvider contract.
            </para>
            <example>
                <title>Custom ConnectionProvider implementation</title>
                <programlisting role="JAVA"><xi:include href="extras/override/LatestAndGreatestConnectionProviderImpl.java" parse="text" /></programlisting>
            </example>
            <para>
                At this point we have a decision about how to integrate this new ConnectionProvider into Hibernate.
                As you might guess, there are multiple ways.
            </para>
            <para>
                As a first option, we might just require that the code bootstrapping the StandardServiceRegistry do
                the integration.
            </para>
            <example>
                <title>Overriding service implementation via StandardServiceRegistryBuilder</title>
                <programlisting role="JAVA"><xi:include href="extras/override/ex1-direct.java" parse="text" /></programlisting>
            </example>
            <para>
                A second option, if our LatestAndGreatestConnectionProviderImpl should always be used, would be to
                provide a <interfacename>org.hibernate.service.spi.ServiceContributor</interfacename> implementation
                as well to handle the integration on the users behalf.
            </para>
            <example>
                <title>LatestAndGreatestConnectionProviderImplContributor</title>
                <programlisting role="JAVA"><xi:include href="extras/override/ex2-contributor.java" parse="text" /></programlisting>
            </example>
            <para>
                We still need to be able to tell Hibernate to perform this integration for us.  To do that we leverage
                Java's ServiceLoader.  When building the StandardServiceRegistry, Hibernate will look for JDK
                service providers of type <interfacename>org.hibernate.service.spi.ServiceContributor</interfacename>
                and automatically integrate them.  We discussed this behavior above.  Here we'd define a classpath
                resource named <filename>META-INF/services/org.hibernate.service.spi.ServiceContributor</filename>.
                This file will have just a single line naming our impl.
            </para>
            <example>
                <title>META-INF/services/org.hibernate.service.spi.ServiceContributor</title>
                <programlisting><xi:include href="extras/override/ex2-meta-inf" parse="text" /></programlisting>
            </example>
            <para>
                A third option, if we simply want to make our LatestAndGreatestConnectionProviderImpl available
                as a configuration choice, we would again use a ServiceContributor but in a slightly
                different way.
            </para>
            <example>
                <title>LatestAndGreatestConnectionProviderImplContributor</title>
                <programlisting role="JAVA"><xi:include href="extras/override/ex3-contributor.java" parse="text" /></programlisting>
            </example>
            <para>
                That all allows the appication to pick our LatestAndGreatestConnectionProviderImpl by a short-name.
            </para>
            <example>
                <title>Custom service short-name</title>
                <programlisting role="JAVA"><xi:include href="extras/override/ex3-app.java" parse="text" /></programlisting>
            </example>
        </section>

        <section xml:id="services-extending">
            <title>Custom Service Roles (extending)</title>
            <para>
                We can also have the ServiceRegistry host custom services (completely new Service roles).  As an example,
                let's say our application publishes Hibernate events to a JMS Topic and that we want to leverage the
                Hibernate ServiceRegistry to host a Service representing our publishing of events.  So we will expand the
                ServiceRegistry to host this completely new Service role for us and manage its lifecycle.
            </para>

            <example>
                <title>The EventPublishingService service role</title>
                <programlisting role="JAVA"><xi:include href="extras/extend/EventPublishingService.java" parse="text" /></programlisting>
            </example>

            <example>
                <title>The EventPublishingService implementation</title>
                <programlisting role="JAVA"><xi:include href="extras/extend/EventPublishingServiceImpl.java" parse="text" /></programlisting>
            </example>

            <example>
                <title>An alternative EventPublishingService implementation</title>
                <programlisting role="JAVA"><xi:include href="extras/extend/EventPublishingServiceImpl.java" parse="text" /></programlisting>
            </example>

            <para>
                Because we have alternative implementations, it is a good idea to develop an initiator as well
                that can choose between them at runtime.
            </para>

            <example>
                <title>The EventPublishingServiceInitiator</title>
                <programlisting role="JAVA"><xi:include href="extras/extend/EventPublishingServiceInitiator.java" parse="text" /></programlisting>
            </example>

            <para>
                We could have the application register the EventPublishingServiceInitiator with the
                StandardServiceRegistryBuilder, but it is much nicer to write a ServiceContributor to handle this
                for the application.
            </para>
        </section>
    </section>
</chapter>