> Markdown version of [Custom Instantiator](https://vaadin.com/docs/next/flow/advanced/custom-instantiators). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Custom Instantiator

An `Instantiator` is used for discovering, creating and managing object instances that Flow uses. Usually, a custom instantiator is needed for dependency injection frameworks so that they can provide managed instances of objects according to the specific conventions of that DI framework.

## <a id="creating-a-custom-instantiator"></a>Creating a Custom Instantiator

To create a custom instantiator, implement the `Instantiator` interface and implement the following methods:

- `Stream<VaadinServiceInitListener> getServiceInitListeners()`;

- `T getOrCreate(Class<T> type)`; and

- `T createComponent(Class<T> componentClass)`

It’s usually good to extend the `DefaultInstantiator` and only implement `getOrCreate` and `createComponent` with dependency injection bean handling, with a fallback to the default functionality.

`getOrCreate(Class<T>)` should always return an initialized object of type T, where the instance returned is an initialized one from the current scope, or generate a new bean instance, or if not a bean handle field injection. `createComponent(Class<T>)` should always create a new component with field injection.

As an example, the simplified instantiator for Context and Dependency Injection (CDI) could be as follows:

Simplified CustomInstantiator for CDI sample

```java
import com.vaadin.flow.component.Component;
import com.vaadin.flow.di.DefaultInstantiator;

import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.Unmanaged;
import jakarta.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomInstantiator extends DefaultInstantiator {

    @Inject
    private BeanManager beanManager;

    public CustomInstantiator(BeanManager beanManager, VaadinService service) {
        super(service);
        this.beanManager = beanManager;
    }

    /**
     * Hands over an existing bean or tries to instantiate one.
     */
    @Override
    public<T> T getOrCreate(Class<T> type) {
        Set<Bean<T>> beans = beanManager.getBeans(type);
        if(beans == null || beans.isEmpty()) {
            getLogger().debug("'{}' is not a CDI bean.",
                        type.getName());
            return createComponent(type);
        }
        Bean<?> bean = beanManager.resolve(beans);
        final CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
        //noinspection unchecked
        return (T) beanManager.getReference(bean, type, ctx);
    }

    /**
     * Tries to instantiate new bean.
     */
    @Override
    public<T extends Component> T createComponent(Class<T> componentClass) {
        Unmanaged<T> unmanagedClass = new Unmanaged<T>(componentClass);
        Unmanaged.UnmanagedInstance<T> instance = unmanagedClass.newInstance();
        instance.produce().inject().postConstruct();
        return instance.get();
    }

    private static Logger getLogger() {
        return LoggerFactory.getLogger(CdiInstantiator.class);
    }
}
```

## <a id="loading-the-custom-instantiator-using-java-serviceloader"></a>Loading the custom Instantiator using Java ServiceLoader

To load the instantiator, you should implement the `InstantiatorFactory` interface and load it through the Java ServiceLoader.

```java
package org.example;

import com.vaadin.flow.di.Instantiator;
import com.vaadin.flow.di.InstantiatorFactory;
import com.vaadin.flow.server.VaadinService;

import jakarta.enterprise.inject.spi.BeanManager;
import org.apache.deltaspike.core.api.provider.BeanManagerProvider;

public class CustomInstantiatorFactory implements InstantiatorFactory {

    @Override
    public Instantiator createInstantiator(VaadinService vaadinService) {
        BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
        return new CustomInstantiator(beanManager, service);
    }
}
```

To load the factory, add to `src/main/resources/META-INF/services/` the file `com.vaadin.flow.di.InstantiatorFactory` with the content being the fully qualified name of the factory class. For this example, the content would be `org.example.CustomInstantiatorFactory`.

## <a id="loading-the-custom-instantiator-though-vaadinservletservice"></a>Loading the custom Instantiator though VaadinServletService

Implement `VaadinServletService` and `VaadinServlet`.

For `VaadinServletService`, override the `createInstantiator()`.

```java
import com.vaadin.flow.di.Instantiator;
import com.vaadin.flow.server.VaadinServletService;

import jakarta.enterprise.inject.spi.BeanManager;

public class CustomVaadinServletService extends VaadinServletService {
    private BeanManager beanManager;

    public CustomVaadinServletService(CustomServlet servlet,
                DeploymentConfiguration configuration,
                BeanManager beanManager) {
        super(servlet, configuration);
        this.beanManager = beanManager;
    }

    protected Instantiator createInstantiator() throws ServiceException {
        Set<Bean<CdiInstantiator>> beans = beanManager.getBeans(CustomInstantiator.class);
        if(beans == null || beans.isEmpty()) {
            getLogger().debug("'{}' is not a CDI bean.", type.getName());
            Unmanaged<T> unmanagedClass = new Unmanaged<T>(CustomInstantiator.class);
            Unmanaged.UnmanagedInstance<T> instance = unmanagedClass.newInstance();
            instance.produce().inject().postConstruct();
            return instance.get();
        }
        Bean<?> bean = beanManager.resolve(beans);
        final CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
        //noinspection unchecked
        return (CustomInstantiator) beanManager.getReference(bean, CustomInstantiator.class, ctx);
    }
}
```

For `VaadinServlet`, override the `createServerService(DeploymentConfiguration deploymentConfiguration)` to return the custom VaadinServletService.

```java
import com.vaadin.flow.function.DeploymentConfiguration;
import com.vaadin.flow.server.VaadinServlet;
import com.vaadin.flow.server.VaadinServletService;

import jakarta.enterprise.inject.spi.BeanManager;
import org.apache.deltaspike.core.api.provider.BeanManagerProvider;

@WebServlet(urlPatterns = "/*", asyncSupported = true)
public class CustomServlet extends VaadinServlet {

  @Override
  protected VaadinServletService createServletService(DeploymentConfiguration deploymentConfiguration) throws ServiceException {
      BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
      CustomVaadinServletService service = new CustomVaadinServletService(this, deploymentConfiguration, beanManager);
      service.init();
      return service;
  }
}
```

`e1b2822e-926b-4801-9cb0-2c45a9af64e7`
