RESTful Web Services integration with CDI

In Open Liberty, Jakarta RESTful Web Services (formerly known as JAX-RS) can integrate with the Contexts and Dependency Injection (CDI) specification. By integrating RESTful Web Services with CDI, you can annotate CDI beans or managed beans as REST endpoints and use CDI injection for web services.

In Open Liberty, RESTful Web Services support is enabled by the Jakarta RESTful Services feature. This feature helps applications build and consume RESTful services. It also supports CDI-style beans as root resource classes, providers, and application subclasses. Providers and application subclasses must be singleton classes or use the application scope. The CDI specification helps integrate various kinds of Jakarta EE components in a loosely coupled but type-safe way. This specification provides a common mechanism to inject components, such as enterprise beans or managed beans, into other components, such as Jakarta Server Pages (JSP) files or other enterprise beans. CDI support in Open Liberty is enabled by the Contexts and Dependency Injection feature.

One way to implement CDI with RESTful Web Services resources is to use the @ApplicationScoped and @Inject annotations with application-scoped beans in your application code, as shown in the following example:

@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {

    private @Inject
    SimpleBean injected;

...

}

The @ApplicationScoped annotation specifies that only one instance of this bean is used for the lifecycle of the application. Normally, RESTful Web Services resources are per-request, which means the RESTful Web Services engine creates a new instance of the class for each HTTP request. Per-request classes are beneficial in some cases but they are generally less efficient than per-application resources, in which the same instance is used for every HTTP request.

The @Inject annotation injects an instance of the SimpleBean class into the instance of the ApplicationScopedResource bean. For more information about CDI, see Context and Dependency Injection beans.

RESTful Web Services and CDI scopes

The scope of a bean defines the lifecycle of its instances. A bean lifecycle can be singleton, so that the same instance is used for every HTTP request, or per-request, so that a new instance is created for each HTTP request. Bean lifecycles can also be scoped to a particular session, or by conversation, which is defined by explicit developer-controlled boundaries for JSF applications.

RESTful Web Services and CDI specify slightly different scopes. If the lifecycle scopes that are specified by RESTful Web Services and CDI are in conflict, the resulting lifecycle depends on the component type of the RESTful Web Services resource. RESTful Web Services provider component types are always singletons, regardless of the CDI annotation. RESTful Web Services resource component types adopt whatever lifecycle is specified by the CDI annotation.

For example, the ApplicationScoped CDI scope annotation defines a singleton lifecycle, because only one instance of a class with this annotation is used for the lifecycle of the application. If you configure a RESTful Web Services resource scope as per-request, but then specify the @ApplicationScoped CDI scope on it, the resource lifecycle is singleton. Similarly, if you configure a RESTful Web Services resource scope as singleton, but then specify the @RequestScoped CDI scope on it, the resource lifecycle is per-request, as specified by the CDI annotation. However, if the RESTful Web Services component is a provider, the lifecycle is singleton, regardless of the CDI annotation.

For more information, see CDI scopes.

Restrictions on RESTful Web Services with CDI

CDI with RESTful Web Services in Open Liberty is subject to the following restrictions:

  • If the Contexts and Dependency Injection feature is not enabled in your server.xml file, the runtime has no CDI support. Therefore, if you specify a CDI annotation in a Java class, the RESTful Web Services engine uses the Java class as a plain old Java object (POJO) class.

  • If a resource class with the @Path annotation implements a RESTful Web Services provider interface or declares with the @Provider annotation, then this class works as both a resource and a provider. In this case, the RESTful Web Services engine uses only one instance of this class that is shared by the resource class and the provider. The lifecycle of the instance is singleton.

  • If a RESTful resource is also a CDI-managed bean and its scope is javax.enterprise.context.Dependent, the PreDestroy method cannot be called because of the CDI restriction.

  • If a class is registered in both the getClasses and getSingletons methods of the application class, the RESTful Web Services engine uses the instance from the getSingletons method and ignores the getClasses instance. However, objects that are returned in the getSingletons method are not managed by CDI. In general, avoid use of the getSingletons method as it is targeted for deprecation and eventual removal from future versions of the RESTful Web Services specification.