> Markdown version of [Vaadin CDI Contexts](https://vaadin.com/docs/v14/flow/integrations/cdi/tutorial-cdi-contexts). Section index: [llms.txt](https://vaadin.com/docs/v14/flow/llms.txt)

# Vaadin CDI Contexts

In addition to standard CDI contexts, the [Vaadin CDI](https://vaadin.com/directory/component/vaadin-cdi/) add-on introduces new contexts.

Vaadin CDI contexts are conceptually similar to [Vaadin Spring scopes](https://vaadin.com/docs/v14/flow/integrations/spring/tutorial-spring-scopes.md).

## <a id="normal-scopes"></a>Normal Scopes

In CDI, most scopes are normal scopes. This means that most calls to managed beans are delegated by a client proxy to the active instance. The active instance is provided by the context.

The [Vaadin CDI](https://vaadin.com/directory/component/vaadin-cdi/) add-on introduces the `@VaadinServiceScoped`, `@VaadinSessionScoped`, `@NormalUIScoped`, `@NormalRouteScoped` normal scopes..

> **Note:** The Vaadin component hierarchy does not work properly with CDI client proxies. As a precaution, the `vaadin-cdi` add-on does not deploy if managed beans are found.

## <a id="pseudo-scopes"></a>Pseudo Scopes

Any scope that is not a normal scope is called a pseudo scope. The standard `@Dependent` and `@Singleton` are pseudo scopes.

The Vaadin add-on additionally introduces the `@UIScoped` and `@RouteScoped` pseudo scopes.

Injection of a pseudo-scoped bean creates a direct reference to the object, but there are some limitations when not using proxies:

- Circular referencing, for example injecting A to B and B to A, does not work.

- Injecting into a larger scope binds the instance from the currently active smaller scope, and ignores changes in the smaller scope. For example, a `@UIScoped` bean after being injected into a session scope will point to the same instance (even its `UI` is closed) regardless of current `UI`.

### <a id="using-push"></a>Using Push

Vaadin contexts are usable inside the `UI.access` method with any push transport.

Certain default contexts from CDI, such as `RequestScoped` or `SessionScoped`, can be problematic. HttpServletRequest can’t be resolved from a WebSocket connection in CDI and that is needed for HTTP request, session, and conversation contexts. You should, therefore, use `WEBSOCKET_XHR` (the default), or `LONG_POLLING` transport mode, to avoid losing the standard contexts.

Background-thread contexts that depend on HTTP requests are not active, regardless of push.

See [Asynchronous Updates](https://vaadin.com/docs/v14/flow/advanced/tutorial-push-access.md#asynchronous-updates) for more about using push.

### <a id="vaadinservicescoped-context"></a>`@VaadinServiceScoped` Context

The `@VaadinServiceScoped` context manages the beans during the Vaadin service lifecycle. The lifecycle of the service is the same as the lifecycle of its Vaadin servlet. See [Vaadin Servlet and Service](https://vaadin.com/docs/v14/flow/advanced/tutorial-application-lifecycle.md#vaadin-servlet-and-service) for more about the Vaadin service.

For beans that are automatically picked up by `VaadinService`, you need to use the `@VaadinServiceEnabled` annotation, together with the `@VaadinServiceScoped` annotation. See [Vaadin Service Interfaces as CDI Beans](https://vaadin.com/docs/v14/flow/integrations/cdi/tutorial-cdi-service-beans.md) for more.

### <a id="vaadinsessionscoped-context"></a>`@VaadinSessionScoped` Context

The `@VaadinSessionScoped` context manages the beans during Vaadin session lifecycle. This means that the same bean instance is used within the whole Vaadin session.

See [User Session](https://vaadin.com/docs/v14/flow/advanced/tutorial-application-lifecycle.md#user-session) for more.

**Example**: Using the `@VaadinSessionScoped` annotation on route targets.

```java
@Route("")
public class MainLayout extends Div {
    @Inject
    public MainLayout(SessionService bean){
        setText(bean.getText());
    }
}

@Route("editor")
public class Editor extends Div {
    @Inject
    public Editor(SessionService bean){
        setText(bean.getText());
    }
}

@VaadinSessionScoped
public class SessionService {
    private String uid = UUID.randomUUID().toString();

    public String getText(){
        return "session " + uid;
    }
}
```

Because it is session scoped, the same instance of `SessionService` is used if the application is accessed from the same Vaadin session. If you open the root target in one tab and the `editor` target in another, the text in both is the same. This is because the session is the same even though the tabs (and `UI` instances) are different.

## <a id="uiscoped-and-normaluiscoped-contexts"></a>`@UIScoped` and `@NormalUIScoped` Contexts

The `@UIScoped` and `@NormalUIScoped` contexts manage the beans during the `UI` lifecycle. Use `@UIScoped` for components and `@NormalUIScoped` for other beans.

See [Loading a UI](https://vaadin.com/docs/v14/flow/advanced/tutorial-application-lifecycle.md#loading-a-ui) for more about the `UI` lifecycle.

**Example**: Using the `@NormalUIScoped` annotation on route targets.

```java
@Route("")
public class MainLayout extends Div {
    @Inject
    public MainLayout(UIService bean){
        setText(bean.getText());
    }
}

@Route("editor")
public class Editor extends Div {
    @Inject
    public Editor(UIService bean){
        setText(bean.getText());
    }
}

@NormalUIScoped
public class UIService {
    private String uid = UUID.randomUUID().toString();

    public String getText(){
        return "ui " + uid;
    }
}
```

Because it is UI scoped, the same `UIService` is used while in the same `UI`. If you open the root target in one tab and the `"editor"` target in another, the text is different because the `UI` instances are different. If you navigate to the `editor` instance via the router (or the `UI` instance which delegates navigation to the router) the text is the same.

**Example**: Navigating to the `"editor"` target.

```java
public void edit() {
    getUI().get().navigate("editor");
}
```

In the same `UI` instance, the same bean instance is used with both `@UIScoped` and `@NormalUIScoped`.

> **Note: Preserving UIScope Beans**
>
> Unlike with earlier versions of Vaadin (i.e., versions 7 and 8), the `UI`, and thus the `UIScoped` and `NormalUIScoped` beans, aren’t preserved when the `@PreserveOnRefresh` annotation is used and the browser is then refreshed. To preserve the beans on refresh, you need to use instead `@RouteScoped`, as described [later on this page](#routescope.preserve).

## <a id="routescoped-normalroutescoped-contexts"></a>`@RouteScoped` & `@NormalRouteScoped` Contexts

The `@RouteScoped` and `@NormalRouteScoped` manage the beans during the `Route` lifecycle. Use `@RouteScoped` for components and `@NormalRouteScoped` for other beans.

Together with the `@RouteScopeOwner` annotation, both `@RouteScoped` and `@NormalRouteScoped` can be used to bind beans to router components (`@Route`, `RouteLayout`, `HasErrorParameter`). While the owner remains in the route chain, all beans owned by it remain in the scope.

See [Defining Routes With @Route](https://vaadin.com/docs/v14/flow/routing/tutorial-routing-annotation.md) and [Router Layouts and Nested Router Targets](https://vaadin.com/docs/v14/flow/routing/tutorial-router-layout.md) for more about route targets, route layouts, and the route chain.

**Example**: Using the `@NormalRouteScoped` annotation on route targets.

```java
@Route("")
@RoutePrefix("parent")
public class ParentView extends Div
        implements RouterLayout {
    @Inject
    public ParentView(
            @RouteScopeOwner(ParentView.class)
            RouteService routeService) {
        setText(routeService.getText());
    }
}

@Route(value = "child-a", layout = ParentView.class)
public class ChildAView extends Div {
    @Inject
    public ChildAView(
            @RouteScopeOwner(ParentView.class)
            RouteService routeService) {
        setText(routeService.getText());
    }
}

@Route(value = "child-b", layout = ParentView.class)
public class ChildBView extends Div {
    @Inject
    public ChildBView(
            @RouteScopeOwner(ParentView.class)
            RouteService routeService) {
        setText(routeService.getText());
    }
}

@NormalRouteScoped
@RouteScopeOwner(ParentView.class)
public class RouteService {
    private String uid = UUID.randomUUID().toString();

    public String getText() {
        return "ui " + uid;
    }
}
```

`ParentView`, `ChildAView`, and `ChildBView` (paths: `/parent`, `/parent/child-a`, and `/parent/child-b`) use the same `RouteService` instance while you navigate between them. After navigating away from `ParentView`, the `RouteService` is also destroyed.

Even though `@RouteScopeOwner` is redundant because it is a CDI qualifier, you need to define it on both the bean and on the injection point.

Route components can also be `@RouteScoped`. In this case, `@RouteScopeOwner` should point to a parent layout. If `@RouteScopeOwner` is omitted, the `@RouteScoped` annotated component — or in case of a nested routing hierarchy, the leaf route component — becomes the owner.

**Example**: Using the `@RouteScoped` annotation on an `@Route` component.

```java
@Route("scoped")
@RouteScoped
public class ScopedView extends Div {
    private void onMessage(
            @Observes(notifyObserver = IF_EXISTS)
            MessageEvent message) {
        setText(message.getText());
    }
}
```

The message is delivered to the `ScopedView` instance that was already navigated to. If on another view, there is no instance of this bean and the message is not delivered to it.

### <a id="routescope.preserve"></a>Preserving Beans during Browser Refresh

By default, when the user refreshes the page, all routing components are recreated. This applies to `@UIScoped` and `@RouteScoped` beans, too. New bean instances are created and injected to the new routing components. It’s possible to tell the framework to preserve the routing components during refresh with the `@PreserveOnRefresh` annotation. See the [Preserving the State on Refresh](https://vaadin.com/docs/v14/flow/advanced/tutorial-preserving-state-on-refresh.md) documentation page for more information.

When the `@PreserveOnRefresh` annotation is used on a routing component that has `@RouteScoped` beans injected into it, the beans are preserved too.

The example that follows shows beans being preserved with `@RouteScopeOwner` targeting a component with `@PreserveOnRefresh`:

```java
@RouteScoped
@RouteScopeOwner(MainLayout.class)
public class PreservedBean {
    private String uuid = UUID.randomUUID().toString();

    public String getText() {
        return uuid;
    }
}

@Route("") // optional, could use a subview with @Route instead
@PreserveOnRefresh
public class MainLayout extends VerticalLayout implements RouterLayout {

    @Inject
    @RouteScopeOwner(MainLayout.class)
    private PreservedBean bean;

    @PostConstruct
    public void init() {
        add(new Span("UUID:" + bean.getText()));
    }
}
```

In this example, both the `MainLayout` component and the `PreservedBean` injected bean are preserved after browser refresh. The text stays the same.

If the `@PreserveOnRefresh` annotation is removed from the layout, both the component and the bean are recreated after browser refresh. The text would change.

#### <a id="uiscoped-beans-arent-preserved"></a>UIScoped Beans Aren’t Preserved

Injected beans aren’t preserved when they’re `UIScoped`, but only when they’re `RouteScoped`, regardless of whether `@PreserveOnRefresh` is used. However, any currently active routing components are preserved, even if they’re `UIScoped`. This is due to the nature of the `@PreserveOnRefresh` feature implementation.

The `UI` instance itself isn’t preserved, but routing components are. Any bean tied to the `UI` instance with `UIScoped` is recreated, and the preserved routing components are moved to the new `UI`. To preserve beans during a browser refresh, you need to use `@RouteScoped`, as shown earlier.

`BEFF17CB-B9C4-448C-BF9B-DCB31CF45642`
