= Native Bootstrapping
:toc:

This guide discusses the process of bootstrapping a Hibernate `org.hibernate.SessionFactory`.  It also
discusses the ways in which applications and integrators can hook-in to and affect that process.  This
bootstrapping process is defined in 2 distinct steps.  The first step is the building of a ServiceRegistry
holding the services Hibernate will need at bootstrap- and runtime.  The second step is the building of
a Metadata object representing the mapping information for the application's model and its mapping to
the database.

NOTE: Prior to version 5.0 applications bootstrapped a `SessionFactory` is via the
`org.hibernate.cfg.Configuration` object.  That approach is still supported in a slightly limited manner.
See the _Legacy Bootstrapping_ guide for details.


== Building the ServiceRegistry

Actually we are concerned with building 2 different ServiceRegistries:

    * `org.hibernate.boot.registry.BootstrapServiceRegistry`
    * `org.hibernate.boot.registry.StandardServiceRegistry`

Each of these is built from a builder, `org.hibernate.boot.registry.BootstrapServiceRegistryBuilder`
and `org.hibernate.boot.registry.StandardServiceRegistryBuilder` respectively.


NOTE: For more information on ServiceRegistries in general, see the _Services and Registries_ guide.

=== BootstrapServiceRegistry

The `BootstrapServiceRegistry` is intended to hold services that Hibernate needs at both bootstrap and run time.
This boils down to 3 services:

    * `ClassLoaderService` - which controls how Hibernate interacts with ClassLoaders
    * `IntegratorService` - which controls the management ands discovery of `org.hibernate.integrator.spi.Integrator` instances.
    * `StrategySelector` - which control how Hibernate resolves implementations of various strategy
    	contracts.  This is a very powerful service, but a full discussion of it is beyond the scope
    	of this guide.

If you are ok with the default behavior of Hibernate in regards to these BootstrapServiceRegistry services
(which is quite often the case, especially in SE environments) building the BootstrapServiceRegistry can be skipped.
If you wish to alter how the `BootstrapServiceRegistry` is built, you would use the `BootstrapServiceRegistryBuilder`:

[[bootstrap-registry-builder-example]]
.Building a BootstrapServiceRegistry
====
[source, JAVA]
----
    BootstrapServiceRegistryBuilder bootstrapRegistryBuilder
            = new BootstrapServiceRegistryBuilder();
    // add a special ClassLoader
    bootstrapRegistryBuilder.applyClassLoader( mySpecialClassLoader );
    // manually add an Integrator
    bootstrapRegistryBuilder.applyIntegrator( mySpecialIntegrator );
    ...

    BootstrapServiceRegistry bootstrapRegistry = bootstrapRegistryBuilder.build();
----
====

The services of the `BootstrapServiceRegistry` cannot be extended (added to) nor overridden (replaced).


=== StandardServiceRegistry

The services of the `StandardServiceRegistry` may be extended and overridden.

A `StandardServiceRegistry` is built through the `StandardServiceRegistryBuilder` which can be constructed in
one of 2 ways:

[[standard-registry-builder-example1]]
.Building a StandardServiceRegistryBuilder with a supplied BootstrapServiceRegistry
====
[source, JAVA]
----
    BootstrapServiceRegistry bootstrapRegistry = ...;
    StandardServiceRegistryBuilder standardRegistryBuilder
            = new StandardServiceRegistryBuilder( bootstrapRegistry );
----
====

[[standard-registry-builder-example2]]
.Building a StandardServiceRegistryBuilder without a supplied BootstrapServiceRegistry
====
[source, JAVA]
----
    StandardServiceRegistryBuilder standardRegistryBuilder
            = new StandardServiceRegistryBuilder();
----
====

The second form will create a `BootstrapServiceRegistry` on the fly with default behavior.

A `StandardServiceRegistry` is also highly configurable via the `StandardServiceRegistryBuilder` API.  See the
`StandardServiceRegistryBuilder` javadocs for full details.  Some specific methods of interest:

[[standard-registry-builder-example3]]
.Configuring StandardServiceRegistryBuilder
====
[source, JAVA]
----
    StandardServiceRegistryBuilder standardRegistryBuilder = ...;
    // load some properties via resource lookup
    standardRegistryBuilder.loadProperties( "org/hibernate/example/MyProperties.properties" );
    // configure the registry from a resource lookup for a cfg.xml config file
    standardRegistryBuilder.configure( "org/hibernate/example/MyCfg.xml" );
    // apply a random setting
    standardRegistryBuilder.applySetting( "myProp", "some value" );
    // apply a service initiator
    standardRegistryBuilder.addInitiator( new CustomServiceInitiator() );
    // apply a service impl
    standardRegistryBuilder.addService( SomeCustomService.class, new SomeCustomServiceImpl() );

    // and finally build the StandardServiceRegistry
    StandardServiceRegistry standardRegistry = standardRegistryBuilder.build();
----
====


== Building the Metadata

The `org.hibernate.boot.Metadata` object contains the parsed representations of an application's
domain model and its mapping to a database.  The first thing we obviously need to build a parsed
representation is the source information to be parsed (annotated classes, `hbm.xml` files, `orm.xml` files).  This is
the purpose of `org.hibernate.boot.MetadataSources`.


[[MetadataSources-example]]
.Configuring a MetadataSources
====
[source, JAVA]
----
    MetadataSources sources = new MetadataSources( standardRegistry );
    // alternatively, we can build the MetadataSources without passing
    // a service registry, in which case it will build a default
    // BootstrapServiceRegistry to use
    // MetadataSources sources = new MetadataSources();

	// add a class using JPA/Hibernate annotations for mapping
    sources.addAnnotatedClass( MyEntity.class );

	// add the name of a class using JPA/Hibernate annotations for mapping.
	// differs from above in that accessing the Class is deferred which is
	// important if using runtime bytecode-enhancement
    sources.addAnnotatedClassName( "org.hibernate.example.Customer" );

    // Adds the named hbm.xml resource as a source: which performs the
    // classpath lookup and parses the XML
    sources.addResource( "org/hibernate/example/Order.hbm.xml" );

    // Adds the named JPA orm.xml resource as a source: which performs the
    // classpath lookup and parses the XML
    sources.addResource( "org/hibernate/example/Product.orm.xml" );
----
====

`MetadataSources` has many other methods as well; explore its API and javadocs for more information.  Also,
all methods on `MetadataSources` allow for chaining should you prefer that style.

[[MetadataSources-chaining-example]]
.Configuring a MetadataSources with method chaining
====
[source, JAVA]
----
    MetadataSources sources = new MetadataSources( standardRegistry )
            .addAnnotatedClass( MyEntity.class )
            .addAnnotatedClassName( "org.hibernate.example.Customer" )
            .addResource( "org/hibernate/example/Order.hbm.xml" )
            .addResource( "org/hibernate/example/Product.orm.xml" );
----
====

Once we have the sources of mapping information defined, we need to build the `Metadata` object.  If you are
ok with the default behavior in building the `Metadata` (or if relying on a `MetadataBuilderInitializer` - see below)
then you can simply call `MetadataSources#buildMetadata`.

NOTE : Notice that a ServiceRegistry can be passed at a number of points in this bootstrapping process.  The suggested
approach is to build a `StandardServiceRegistry` yourself and pass that along to the `MetadataSources` constructor.
From there, `MetadataBuilder`, `Metadata`, `SessionFactoryBuilder` and `SessionFactory` will all pick up that
same `StandardServiceRegistry`.

However, if you wish to adjust the process of building `Metadata` from `MetadataSources` you will need to use
the `MetadataBuilder` as obtained via `MetadataSources#getMetadataBuilder`.  `MetadataBuilder` allows a lot of control
over the `Metadata` building process.  See its javadocs for full details.

[[MetadataBuilder-example]]
.Building Metadata via MetadataBuilder
====
[source, JAVA]
----
    MetadataBuilder metadataBuilder = sources.getMetadataBuilder();

    // Use the JPA-compliant implicit naming strategy
    metadataBuilder.applyImplicitNamingStrategy( ImplicitNamingStrategyJpaCompliantImpl.INSTANCE );

    // specify the schema name to use for tables, etc when none is explicitly specified
	metadataBuilder.applyImplicitSchemaName( "my_default_schema" );

	Metadata metadata = metadataBuilder.build();
----
====

== Building the SessionFactory

Much like we've discussed above, if you are ok with the default behavior of building a `SessionFactory`
from a `Metadata` reference, you can simply call `Metadata#buildSessionFactory`.  However, if you would like to
adjust that building process you will need to use `SessionFactoryBuilder` as obtained via
`Metadata#getSessionFactoryBuilder`.  See the `SessionFactoryBuilder` javadocs for details of the control it allows
over the `SessionFactory` building process.

[[SessionFactoryBuilder-example]]
.Building SessionFactory via SessionFactoryBuilder
====
[source, JAVA]
----
    SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();

    // Supply a SessionFactory-level Interceptor
    sessionFactoryBuilder.applyInterceptor( new MySessionFactoryInterceptor() );

    // Add a custom observer
    sessionFactoryBuilder.addSessionFactoryObservers( new MySessionFactoryObserver() );

    // Apply a CDI BeanManager (for JPA event listeners)
    sessionFactoryBuilder.applyBeanManager( getBeanManagerFromSomewhere() );

    SessionFactory sessionFactory = sessionFactoryBuilder.build();
----
====

== Putting It All Together

The bootstrapping API is quite flexible, but in most cases it makes the most sense to think of
it as a 3 step process:

1. Build the `StandardServiceRegistry`
2. Build the `Metadata`
3. Use those 2 things to build the `SessionFactory`

[[Putting-It-All-Together-ex1]]
.Building SessionFactory via SessionFactoryBuilder
====
[source, JAVA]
----
    StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
            .configure( "org/hibernate/example/MyCfg.xml" )
            .build();

    Metadata metadata = new MetadataSources( standardRegistry )
            .addAnnotatedClass( MyEntity.class )
            .addAnnotatedClassName( "org.hibernate.example.Customer" )
            .addResource( "org/hibernate/example/Order.hbm.xml" )
            .addResource( "org/hibernate/example/Product.orm.xml" )
            .getMetadataBuilder()
            .applyImplicitNamingStrategy( ImplicitNamingStrategyJpaCompliantImpl.INSTANCE )
            .build();

    SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
            .applyBeanManager( getBeanManagerFromSomewhere() )
            .build();
----
====


== Integration Points

=== Integrator
=== ServiceContributor
=== TypeContributor
=== MetadataSourcesContributor
=== MetadataBuilderInitializer
=== SessionFactoryBuilderInitializer (todo)
=== SessionFactoryObserver