[[se_bootstrap]]

== Bootstrapping a CDI container in Java SE

In Java SE, the CDI container must be explicitly bootstrapped by the user.
This is performed by the `SeContainerInitializer` abstract class and its static method `newInstance()`.

`SeContainerInitializer` is a `ServiceProvider` of the service `javax.enterprise.inject.se.SeContainerInitializer` declared in META-INF/services.
This class allows a user to configure the CDI container before it is bootstrapped.
The `SeContainerInitializer.initialize()` method bootstraps the container and returns a `SeContainer` instance.

User can shutdown the container manually by calling the `close()` method on `SeContainer` or automatically using try-with-resources since `SeContainer` extends `AutoCloseable` interface.

[[se_container_initializer]]

=== `SeContainerInitializer` class

CDI container can be configured and bootstrapped from `javax.enterprise.inject.se.SeContainerInitializer` abstract class.

A CDI implementation is required to provide an implementation of `SeContainerInitializer` declared as a service provider.
Static method `newInstance()` uses Java service provider mechanism to obtain an implementation of `SeContainerInitializer` and return an instance of it.
There must be exactly one provider available, otherwise an IllegalStateException is thrown.

`SeContainerInitializer` configuration allows explicit addition of elements to the set of automatically discovered elements.
These additions are done in an internal synthetic bean archive that is added to the set of bean archives discovered by the container during deployment.

This synthetic bean archive behaves like an explicit bean archive (as defined in <<bean_archive>>).

[source, java]
----
public abstract class SeContainerInitializer {
    public static SeContainerInitializer newInstance() { ... }
    public SeContainerInitializer addBeanClasses(Class<?>... classes);
    public SeContainerInitializer addPackages(Class<?>... packageClasses);
    public SeContainerInitializer addPackages(boolean scanRecursively, Class<?>... packageClasses);
    public SeContainerInitializer addPackages(Package... packages);
    public SeContainerInitializer addPackages(boolean scanRecursively, Package... packages);
    public SeContainerInitializer addExtensions(Extension... extensions);
    public SeContainerInitializer addExtensions(Class<? extends Extension>... extensions);
    public SeContainerInitializer enableInterceptors(Class<?>... interceptorClasses);
    public SeContainerInitializer enableDecorators(Class<?>... decoratorClasses);
    public SeContainerInitializer selectAlternatives(Class<?>... alternativeClasses);
    public SeContainerInitializer selectAlternativeStereotypes(Class<? extends Annotation>... alternativeStereotypeClasses);
    public SeContainerInitializer addProperty(String key, Object value);
    public SeContainerInitializer setProperties(Map<String, Object> properties);
    public SeContainerInitializer disableDiscovery();
    public SeContainerInitializer setClassLoader(ClassLoader classLoader);
    public SeContainer initialize();
}
----

Unless specified differently each method of `SeContainerInitializer` returns the current `SeContainerInitializer` object.

* `newInstance()` static method returns an instance of the implementation of `SeContainerInitializer` discovered by Java service provider.
Each call returns a new instance of `SeContainerInitializer`. This method throws `IllegalStateException` if called in Jakarta EE container.
* `addBeanClasses()` adds classes to the the synthetic bean archive
* `addPackages()` adds packages content to the synthetic bean archive.
There are other versions of this method, which enables user to add a package according to class or classes it contains and also to add packages recursively.
* `addExtensions()` adds the provided extensions (class or instance) to the synthetic bean archive.
* `enableInterceptors()` adds interceptor classes to the list of enabled interceptors for the synthetic bean archive.
* `enableDecorators()` adds decorator classes to the list of enabled decorators for the synthetic bean archive.
* `selectAlternatives()` adds alternatives classes to the list of selected alternatives for the synthetic bean archive.
* `selectAlternativeStereotypes()` adds alternative stereotype classes to the list of selected alternative stereotypes for the synthetic bean archive.
* `addProperty()` adds a configuration property to the container
* `setProperties()` sets the `Map` of configuration properties for the container.
Original properties `Map` is replaced by a new instance.
* `disableDiscovery()` deactivates automatic type scanning and discovery.
All bean archives will be ignored except the implicit bean archive.
* `setClassLoader()` changes the default class loader for the container
* `initialize()` bootstraps the container and returns a `SeContainer` as defined in <<se_container>>.



Every invocation of the `SeContainerInitializer.initialize()` method returns a new `SeContainer` instance.
The application context is started automatically by the container on start up.
An implementation does not need to support multiple calls of `SeContainerInitializer.initialize()` method when the `SeContainer` is running.


[[se_container]]

=== `SeContainer` interface


The `javax.enterprise.inject.se.SeContainer` interface provides access to the `BeanManager` and programmatic lookup as defined in <<dynamic_lookup>>.
`SeContainer` also extends `AutoCloseable`, so when dereferenced, it should shutdown automatically.


[source, java]
----
public interface SeContainer extends Instance<Object>,AutoCloseable {
    void close();
    boolean isRunning();
    BeanManager getBeanManager();
}
----


* `close()` method explicitly shuts down the container.
If it is called and the container was already shutdown, it throws an `IllegalStateException`.
* `isRunning()` method returns `true` if called before container shuts down and `false` after.
* `getBeanManager()` method returns the `BeanManager` (as defined in <<beanmanager>>) for the running container.
If it is called and the container was already shutdown, it throws an `IllegalStateException`.

SeContainer implements `javax.enterprise.inject.Instance` and therefore might be used to perform programmatic lookup as defined in <<dynamic_lookup>>.
If no qualifier is passed to `SeContainer.select()` method, the `@Default` qualifier is assumed.

If any `Instance.select()` method is called and the container was already shutdown, the `IllegalStateException` is thrown.

The following code examples demonstrate the options of handling container shutdown:

[source,java]
----
public static void main(String... args) {
    SeContainerInitializer containerInit = SeContainerInitializer.newInstance();
    SeContainer container = containerInit.initialize();
    // retrieve a bean and do work with it
    MyBean myBean = container.select(MyBean.class).get();
    myBean.doWork();
    // when done
    container.close();
}
----


[source,java]
----
public static void main(String... args) {
    try(SeContainer container = SeContainerInitializer.newInstance().initialize()) {
        // start the container, retrieve a bean and do work with it
        MyBean myBean = container.select(MyBean.class).get();
        myBean.doWork();
    }
    // shuts down automatically after the try with resources block.
}
----

