
![[8.5.5.6 o posterior]](../ng_v8556.gif)
Integración de JAX-RS 2.0 con EJB y CDI
JAX-RS 2.0 en Liberty se integra con EJB (Enterprise JavaBeans) y CDI (Contexts and Dependency Injection).
Para que JAX-RS 2.0 funcione con los enterprise beans, debe utilizar @Path para anotar la clase de un bean y convertirla en una clase de recurso raíz.
Al integrarse con EJB, puede anotar los beans EJB para exponerlos como puntos finales REST. También puede utilizar el JTA y las funciones de seguridad de EJB. JAX-RS 2.0 en Liberty da soporte al uso de beans de sesión singleton y sin estado como clases de recursos raíz, proveedores y subclases de aplicación. Gracias a integración con CDI, puede anotar beans CDI o beans gestionados como puntos finales REST, y utilizar la inyección de CDI para los servicios web. JAX-RS 2.0 en Liberty da soporte a beans de tipo CDI como clases de recursos raíz, proveedores y subclases de aplicación. Los proveedores y las subclases de aplicación deben ser singletons o utilizar el ámbito de aplicación. La especificación CDI facilita la integración de componentes Java™ EE de distinto tipo. Proporciona un mecanismo común para inyectar componentes como EJB o beans gestionados en otros componentes como JSP u otros EJB.
- Para un bean de sesión sin estado, utilice la anotación
@Stateless como se muestra en el ejemplo siguiente:
@Stateless @Path("stateless-bean") public class StatelessResource {...}
- Para un bean singleton, utilice la anotación @Singleton
como se muestra en el ejemplo siguiente:
@Singleton @Path("singleton-bean") public class SingletonResource {...}
@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {
private @Inject
SimpleBean injected;
...
}
Restricciones en JAX-RS 2.0 con EJB y CDI
Vea los siguientes elementos para las restricciones de JAX-RS 2.0 en Liberty:
- Si utiliza EJB como un recurso JAX-RS, proveedor o aplicación, no puede utilizar la inyección de @Context en el constructor del bean EJB. La razón es que el EJB con el constructor predeterminado sólo puede utilizarse para JAX-RS según la especificación EJB y JAX-RS.
- Si utiliza una anotación EJB o CDI en una clase Java, pero la característica de Liberty para EJB (como ejbLite-3.2) o CDI (como cdi-1.0) no está configurada en el archivo server.xml, lo que significa que no hay soportes de EJB o CDI en el tiempo de ejecución de Liberty, el motor de JAX-RS 2.0 utiliza la clase Java como una clase POJO.
- Para una clase de aplicación, si no implementa ninguna interfaz o tiene
una anotación @Localbean, se considera un EJB; si implementa
interfaces locales o POJO, no se considera un EJB.
- Para un proveedor:
- Si una clase implementa las interfaces de proveedor POJO sólo sin la anotación @Local, se considera un proveedor de EJB válido.
- Si una clase tiene la anotación @LocalBean e implementa la interfaz de proveedor POJO, se considera un proveedor de EJB válido.
- Si una clase tiene la interfaz local con la anotación @Local, la interfaz local es una interfaz de proveedor. Si esta clase implementa la interfaz de proveedor, es un proveedor de EJB válido.
- Si una clase tiene una interfaz local con la anotación @Local y
la interfaz local no es una interfaz de proveedor, no es un proveedor válido.
La razón es que, en este caso, el contenedor EJB puede generar un apéndice EJB sólo para la interfaz local, no para la interfaz de proveedor de POJO.
- Si una clase tiene sólo la anotación @Local que hace referencia a una interfaz de proveedor, pero no implementa esta interfaz de proveedor, no es un proveedor válido, según la especificación JAX-RS 2.0: un proveedor es una clase que implementa una o varias interfaces JAX-RS que se introducen en esta especificación y que pueden anotarse con @Provider para el descubrimiento automático.
- Para el recurso:
- Si el recurso basado en EJB no implementa ninguna interfaz, todos los métodos que se declaran en esta clase están disponibles como recursos JAX-RS.
- Si el recurso basado en EJB implementa una interfaz (local o POJO), todos los métodos que se declaran en esta interfaz están disponibles como recursos JAX-RS.
- Si el recurso basado en EJB implementa una interfaz múltiple,
- Si todas las interfaces son interfaces POJO sin la anotación @Local, todos los métodos que se declaran en la interfaz están disponibles como recursos JAX-RS.
- Si todas las interfaces son interfaces locales con la anotación @Local, todos los métodos que se declaran en la interfaz están disponibles como recursos JAX-RS.
- Si algunas de las interfaces son interfaces locales con la anotación @Local, mientras que otras no son interfaces locales, sólo los métodos declarados en las interfaces locales están disponibles como recursos JAX-RS. La razón es que el contenedor EJB puede generar un apéndice EJB para las interfaces locales sólo en este escenario.
- Si el recurso basado en EJB tiene la anotación @LocalBean, todos los métodos que se declaran en la clase están disponibles como recursos JAX-RS.
- Si el recurso basado en EJB implementa una interfaz, el método de recursos JAX-RS debe declararse en la interfaz. Si la interfaz es un proveedor que no puede modificarse, debe crear una nueva interfaz para que la clase de recurso añada el método de recurso. De lo contrario, no se considera un recurso EJB.
- Para un proveedor:
- Si una clase de recursos con la anotación @Path implementa la interfaz de proveedor JAX-RS o se declara con la anotación @Provider, esta clase funciona como un recurso y un proveedor. En este caso, de forma predeterminada, el motor de JAX-RS 2.0 utiliza sólo una instancia de esta clase compartida por el recurso y el proveedor, y el ciclo de vida de la instancia es singleton.
- Si una clase se ha registrado en los métodos getClasses y getSingletons de la clase de aplicación, el motor de JAX-RS 2.0 utiliza de forma predeterminada la instancia del método getSingletons e ignorar el registro en el método getClasses.
- Si un recurso RESTful también es un bean gestionado CDI y su ámbito es javax.enterprise.context.Dependent, el método PreDestroy no puede invocarse debido a la restricción CDI.
Proceso asíncrono
Puede utilizar la técnica de proceso asíncrono de JAX-RS 2.0 para procesar hebras. El proceso asíncrono está soportado en la API de cliente y en la API de servidor. Para obtener más información sobre el proceso asíncrono, consulte el Capítulo 8 de JSR-339 Java API for RESTful ("Especificación").
El código siguiente muestra el proceso asíncrono en la API de cliente:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://example.org/customers/{id}");
target.resolveTemplate("id", 123).request().async().get(
new InvocationCallbackCustomer() {
@Override
public void completed(Customer customer) {
// Do something
}
@Override
public void failed(Throwable throwable) {
// Process error
}
});
El código siguiente muestra el proceso asíncrono en la API de servidor:
@Path("/async")
public class MyResource{
@GET
public void getAsync(@Suspended final AsyncResponse asyncResponse){
CompletionCallback callBack = new CompletionCallback(){
@Override
public void onComplete(Throwable throwable) {
...
}
};
asyncResponse.register(callBack);
asyncResponse.resume("some Response");
}
}
@Stateless
@Path("/")
class EJBResource {
@GET @Asynchronous
public void longRunningOp(@Suspended AsyncResponse ar) {
executeLongRunningOp();
ar.resume("Hello async world!");
}
}
La gestión de hebras explícita no es necesaria en este caso porque está
bajo el control del contenedor EJB. La respuesta se produce invocando la reanudación en
la AsyncResponse inyectada. Por lo tanto, el tipo de retorno de
longRunningOp está vacío. Ciclo de vida del bean JAX-RS 2.0 y el bean EJB
Aplicación | JAX-RS 2.0 | EJB | Resultado |
---|---|---|---|
Recurso | perRequest | Sin estado | Sin estado |
perRequest | Singleton | Singleton | |
Singleton | Sin estado | Sin estado | |
Singleton | Singleton | Singleton | |
Proveedor | Singleton | Sin estado | Sin estado |
Singleton | Singleton | Singleton |
Ciclo de vida del ámbito de JAX-RS 2.0 y el ámbito de CDI
Aplicación | Ámbito de JAX-RS 2.0 | Anotación del ámbito de CDI | Resultado |
---|---|---|---|
Recurso | 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 | ||
Proveedor | Singleton | @ApplicationScoped | Singleton |
Singleton | @RequestScoped | Singleton | |
Singleton | @Dependent | Singleton | |
Singleton | @SessionScoped | Singleton | |
Singleton | Singleton |
Mensajes de conflicto de ciclo de vida del ámbito de JAX-RS 2.0 y el ámbito de CDI
Aparecen los siguientes mensajes de aviso cuando el ciclo de vida del ámbito de JAX-RS 2.0 y CDI entran en conflicto. Son mensajes de aviso y no es necesario realizar ninguna acción.
Este mensaje aparece si el ámbito del recurso JAXRS-2.0 no coincide con el ámbito de CDI y la instancia de recursos existe en CDI, de modo que Liberty obtiene la instancia de recursos de CDI. La instancia no incluye la inyección de CDI si proviene de JAXRS.CWWKW1001W: El ámbito {1} del recurso JAXRS-2.0 {0} no coincide con el ámbito de CDI {2}. Liberty obtiene la instancia de recurso de {3}.
Este mensaje aparece porque la instancia de proveedor es sólo singleton. Liberty obtiene la instancia de proveedor de CDI si el ámbito de CDI del proveedor es Dependent o ApplicationScoped. La instancia no incluye la inyección de CDI si proviene de JAXRS.CWWKW1002W: El ámbito de CDI del proveedor JAXRS-2.0 {0} es {1}. Liberty obtiene la instancia de proveedor de {2}.