JAX-RS 2.0 integration with EJB and CDI

JAX-RS 2.0 in Liberty integrates with Enterprise JavaBeans (EJB) and Contexts and Dependency Injection (CDI).

Open Liberty For information about JAX-RS 2.0 and later integration with CDI in Liberty, see the Open Liberty website

For JAX-RS 2.0 to work with enterprise beans, you need to use @Path to annotate the class of a bean and convert it to a root resource class.

By integrating with EJB, you can annotate the EJB beans to expose them as REST endpoints. You can also use the JTA and security functions of EJB. JAX-RS 2.0 in Liberty supports the use of stateless and singleton session beans as root resource classes, providers, and application subclasses. By integrating with CDI, you can annotate CDI beans or Managed beans as REST endpoints and use CDI injection for web services. JAX-RS 2.0 in Liberty supports CDI-style beans as root resource classes, providers, and application subclasses. Providers and application subclasses must be singletons or use the application scope. CDI specification makes it easier to integrate Java™ EE components of different types. It provides a common mechanism to inject component such as EJB components or Managed beans into other components such as JSPs or other EJBs.

For EJB, you can use annotation with stateless session beans and singleton POJO beans.
  • For a stateless session bean, use the @Stateless annotation as is shown in the following example:
    @Stateless
    @Path("stateless-bean")
    public class StatelessResource {...}
  • For a singleton bean, use the @Singleton annotation as is shown in the following example:
    @Singleton
    @Path("singleton-bean")
    public class SingletonResource {...}
For CDI, you can use the @ApplicationScoped and @Inject annotations with application scoped beans.
Tip: If the CDI feature is disabled, JAX-RS reports no errors, but the instances are obtained by using POJO.
@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {

    private @Inject
    SimpleBean injected;

...

}

Restrictions on JAX-RS 2.0 with EJB and CDI

See the following items for the restrictions of JAX-RS 2.0 in Liberty:

  • If you use EJB as JAX-RS resource, provider or application, you cannot use the @Context injection on constructor of the EJB bean. The reason is that the EJB with default constructor can only be used for JAX-RS according to EJB and JAX-RS specification.
  • If you use EJB or CDI annotation in a Java class, but the Liberty feature for EJB (such as ejbLite-3.2) or CDI (such as cdi-1.0) is not configured in the server.xml file, which means there are no EJB or CDI supports in Liberty run time, then the JAX-RS 2.0 engine uses the Java class as POJO class.
  • For an Application class, if it implements no interface or it has @Localbean annotation, it is seen as EJB; if it implements local or POJO interfaces, it is not seen as EJB.
    • For a Provider:
      • If a class implements POJO provider interfaces only without the @Local annotation, it is seen as a valid EJB provider.
      • If a class has the @LocalBean annotation and it implements the POJO provider interface, it is seen as a valid EJB provider.
      • If a class has the local interface with the @Local annotation, the local interface is a provider interface. If this class implements the provider interface, then it is a valid EJB provider.
      • If a class has a local interface with @Local annotation, and if the local interface is not a provider interface, then it is not a valid provider.

        The reason is that in this case, EJB container can generate EJB stub for the local interface only rather than the POJO provider interface.

      • If a class has the @Local annotation only that refers a provider interface, but it does not implement this provider interface, then it is not a valid provider according to the JAX-RS 2.0 specification: A provider is a class that implements one or more JAX-RS interfaces that are introduced in this specification and that might be annotated with @Provider for automatic discovery.
    • For Resource:
      • If EJB-based resource does not implement any interface, all of the methods that are declared in this class are available as JAX-RS resources.
      • If EJB-based resource implements one interface (local or POJO), then all the methods that are declared in this interface are available as JAX-RS resources.
      • If EJB-based resource implements multiple interface,
        1. If all the interfaces are POJO interfaces without the @Local annotation, then all the methods that are declared in interface are available as JAX-RS resources.
        2. If all the interfaces are local interfaces with the @Local annotation, then all the methods that are declared in the interface are available as JAX-RS resources.
        3. If some of the interfaces are local interfaces with the @Local annotation while others are not local interfaces, then only the methods declared in the local interfaces are available as JAX-RS resources. The reason is that the EJB container can generate EJB stub for local interfaces only in this scenario.
        4. If the EJB-based resource has the @LocalBean annotation, then all the methods that are declared in class are available as JAX-RS resource.
        5. If EJB-based resource implements an interface, then JAX-RS resource method must be declared in the interface. If the interface is a provider that can't be modified, then you must create a new interface for the resource class to add the resource method. Otherwise, it is not seen as EJB resource.
  • If a resource class with the @Path annotation implements JAX-RS provider interface or it declares with the @Provider annotation, then this class works as both a resource and a provider. In this case, by default, the JAX-RS 2.0 engine uses only one instance of this class that is shared by the resource and the provider, and the lifecycle of the instance is singleton.
  • If a class is registered in both the getClasses and getSingletons methods of the application class, then by default, the JAX-RS 2.0 engine uses the instance from the getSingletons method and ignore the registration in the getClasses method.
  • 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.

JAX-RS 2.0 bean and EJB bean lifecycle

JAX-RS bean and EJB bean have different lifecycle. If the bean lifecycle of JAX-RS and EJB conflicts, the lifecycle is managed by EJB container in Liberty. So the EJB instance is applied while the JAX-RS lifecycle does not work. For more information, see the following table:
Table 1. JAX-RS 2.0 bean and EJB bean lifecycle
Application JAX-RS 2.0 EJB Result
Resource perRequest Stateless Stateless
  perRequest Singleton Singleton
  Singleton Stateless Stateless
  Singleton Singleton Singleton
Provider Singleton Stateless Stateless
  Singleton Singleton Singleton

JAX-RS 2.0 scope and CDI scope lifecycle

Beans have a scope that determines the lifecycle of its instances. JAX-RS and CDI have slightly different scopes. If the scope lifecycle of JAX-RS and CDI conflict, see the following table for the result:
Table 2. JAX-RS 2.0 scope and CDI scope lifecycle
Application JAX-RS 2.0 Scope CDI Scope annotation Result
Resource perRequest @ApplicationScoped Singleton
  perRequest @RequestScoped perRequest
  perRequest @Dependent perRequest
  perRequest @SessionScoped Session
  perRequest   perRequest
  Singleton @ApplicationScoped Singleton
  Singleton @RequestScoped perRequest
  Singleton @Dependent Singleton
  Singleton @SessionScoped Session
  Singleton   Singleton
Provider Singleton @ApplicationScoped Singleton
  Singleton @RequestScoped Singleton
  Singleton @Dependent Singleton
  Singleton @SessionScoped Singleton
  Singleton   Singleton

JAX-RS 2.0 scope and CDI scope lifecycle conflict messages

The following warning messages are displayed when the scope lifecycle of JAX-RS 2.0 and CDI conflicts. They are warning messages and no actions are required.

  • CWWKW1001W: The scope {1} of JAXRS-2.0 Resource {0} does not match the CDI scope {2}. Liberty gets resource instance from {3}.
    This message is displayed if the JAXRS-2.0 resource scope does not match the CDI scope and the resource instance exists in CDI, so Liberty gets the resource instance from CDI. Instance does not include CDI injection if it is from JAXRS.
  • CWWKW1002W: The CDI scope of JAXRS-2.0 Provider {0} is {1}. Liberty gets the provider instance from {2}.
    This message is displayed because provider instance is Singleton only. Liberty gets provider instance from CDI if the CDI scope of provider is Dependent or ApplicationScoped. Instance does not include CDI injection if it is from JAXRS.