Frijoles Jakarta Enterprise

Compartir Imprimir Citar

Jakarta Enterprise Beans (EJB; anteriormente Enterprise JavaBeans) es una de varias API de Java para la construcción modular de software empresarial. EJB es un componente de software del lado del servidor que encapsula la lógica empresarial de una aplicación. Un contenedor web EJB proporciona un entorno de tiempo de ejecución para los componentes de software relacionados con la web, incluida la seguridad informática, la gestión del ciclo de vida del servlet de Java, el procesamiento de transacciones y otros servicios web. La especificación EJB es un subconjunto de la especificación Java EE.

Especificación

La especificación EJB fue desarrollada originalmente en 1997 por IBM y luego adoptada por Sun Microsystems (EJB 1.0 y 1.1) en 1999 y mejorada bajo el Java Community Process como JSR 19 (EJB 2.0), JSR 153 (EJB 2.1), JSR 220 (EJB 3.0), JSR 318 (EJB 3.1) y JSR 345 (EJB 3.2).

La especificación EJB proporciona una forma estándar de implementar el lado del servidor (también llamado "back-end") 'business' software que normalmente se encuentra en las aplicaciones empresariales (a diferencia del software de interfaz de usuario 'front-end'). Dicho software aborda los mismos tipos de problemas, y los programadores suelen volver a implementar repetidamente las soluciones a estos problemas. Jakarta Enterprise Beans está destinado a manejar preocupaciones comunes como la persistencia, la integridad transaccional y la seguridad de una manera estándar, dejando a los programadores libres para concentrarse en las partes particulares del software empresarial en cuestión.

Responsabilidades generales

La especificación EJB detalla cómo un servidor de aplicaciones proporciona las siguientes responsabilidades:

Además, la especificación Jakarta Enterprise Beans define las funciones que desempeñan el contenedor EJB y los EJB, así como también cómo implementar los EJB en un contenedor. Tenga en cuenta que la especificación EJB no detalla cómo un servidor de aplicaciones proporciona persistencia (una tarea delegada a la especificación JPA), sino que detalla cómo la lógica empresarial puede integrarse fácilmente con los servicios de persistencia ofrecidos por el servidor de aplicaciones.

Historia

Las empresas descubrieron que el uso de EJB para encapsular la lógica empresarial generaba una penalización en el rendimiento. Esto se debe a que la especificación original solo permitía la invocación de métodos remotos a través de CORBA (y, opcionalmente, otros protocolos), aunque la gran mayoría de las aplicaciones comerciales en realidad no requieren esta funcionalidad de computación distribuida. La especificación EJB 2.0 abordó esta preocupación al agregar el concepto de interfaces locales a las que las aplicaciones que no estaban distribuidas en múltiples servidores podrían llamar directamente sin penalizaciones de rendimiento.

La especificación EJB 3.0 (JSR 220) fue una desviación de sus predecesores, siguiendo un nuevo paradigma de peso ligero. EJB 3.0 muestra una influencia de Spring en su uso de objetos simples de Java y su soporte para la inyección de dependencia para simplificar la configuración y la integración de sistemas heterogéneos. EJB 3.0 junto con la otra versión de EJB se puede integrar con MuleSoft-v4 utilizando el conector EJB de PlektonLabs certificado por MuleSoft. Gavin King, el creador de Hibernate, participó en el proceso EJB 3.0 y es un abierto defensor de la tecnología. Muchas funciones originalmente en Hibernate se incorporaron en la API de persistencia de Java, el reemplazo de beans de entidad en EJB 3.0. La especificación EJB 3.0 se basa en gran medida en el uso de anotaciones (una característica agregada al lenguaje Java con su versión 5.0) y la convención sobre la configuración para permitir un estilo de codificación mucho menos detallado. En consecuencia, en términos prácticos, EJB 3.0 es mucho más liviano y casi una API completamente nueva, que se parece poco a las especificaciones EJB anteriores.

Ejemplo

A continuación se muestra un ejemplo básico de cómo se ve un EJB en el código:

@Stateless público clase Servicio al Cliente {} privado EntityManager entidad Manager; público vacío añadirCustomer()Cliente cliente) {} entidad Manager.persistencia()cliente); } }

Lo anterior define una clase de servicio para conservar un objeto Cliente (a través del mapeo O/R). El EJB se encarga de gestionar el contexto de persistencia y el método addCustomer() es transaccional y seguro para subprocesos de forma predeterminada. Como se demostró, el EJB se enfoca solo en la lógica comercial y la persistencia y no sabe nada sobre ninguna presentación en particular.

Tal EJB puede ser utilizado por una clase, p. la capa web de la siguiente manera:

@Named@RequestScopedpúblico clase Servicio de atención al cliente {} @EJB privado Servicio al Cliente cliente; público String añadirCustomer()Cliente cliente) {} cliente.añadirCustomer()cliente); context.añadir Mensaje(...) // abreviado para brevedad retorno "customer_overview"; }}

Lo anterior define un bean de respaldo JavaServer Faces (JSF) en el que se inyecta el EJB por medio de la anotación @EJB. Su método addCustomer generalmente está vinculado a algún componente de la interfaz de usuario, como un botón. A diferencia del EJB, el backing bean no contiene ninguna lógica empresarial ni código de persistencia, pero delega dichas preocupaciones al EJB. El backing bean conoce una presentación en particular, de la cual el EJB no tenía conocimiento.

Tipos de Enterprise Beans

Un contenedor EJB contiene dos tipos principales de beans:

Frijoles de sesión

Beans de sesión con estado

Los beans de sesión con estado son objetos comerciales que tienen estado: es decir, realizan un seguimiento del cliente que llama con el que están tratando durante una sesión y, por lo tanto, el acceso a la instancia del bean está estrictamente limitado a un solo cliente a la vez. Si se intenta el acceso simultáneo a un solo bean de todos modos, el contenedor serializa esas solicitudes, pero a través de la anotación @AccessTimeout, el contenedor puede generar una excepción. Beans de sesión con estado' El estado puede persistir (pasivarse) automáticamente por el contenedor para liberar memoria después de que el cliente no haya accedido al bean durante algún tiempo. El contexto de persistencia extendida JPA está explícitamente soportado por Stateful Session Beans.

Ejemplos

Beans de sesión sin estado

Los beans de sesión sin estado son objetos comerciales que no tienen un estado asociado. Sin embargo, el acceso a una sola instancia de bean todavía está limitado a un solo cliente a la vez, el acceso simultáneo al bean está prohibido. Si se intenta el acceso simultáneo a un solo bean, el contenedor simplemente enruta cada solicitud a una instancia diferente. Esto hace que un bean de sesión sin estado sea automáticamente seguro para subprocesos. Las variables de instancia se pueden usar durante una sola llamada de método de un cliente al bean, pero no se garantiza que el contenido de esas variables de instancia se conserve en diferentes llamadas de método de cliente. Las instancias de beans de sesión sin estado generalmente se agrupan. Si un segundo cliente accede a un bean específico justo después de que haya finalizado una llamada de método realizada por un primer cliente, podría obtener la misma instancia. La falta de sobrecarga para mantener una conversación con el cliente que llama hace que consuman menos recursos que los beans con estado.

Ejemplos

Beans de Sesión Singleton

Singleton Session Beans son objetos comerciales que tienen un estado compartido global dentro de una JVM. El acceso simultáneo a la única instancia de bean puede ser controlado por el contenedor (simultaneidad administrada por contenedor, CMC) o por el propio bean (simultaneidad administrada por Bean, BMC). El CMC se puede ajustar mediante la anotación @Lock, que designa si se utilizará un bloqueo de lectura o un bloqueo de escritura para una llamada de método. Además, Singleton Session Beans puede solicitar explícitamente que se creen instancias cuando se inicia el contenedor EJB, utilizando la anotación @Startup.

Ejemplos

Beans controlados por mensajes

Beans controlados por mensajes son objetos comerciales cuya ejecución se activa mediante mensajes en lugar de llamadas a métodos. Message Driven Bean se utiliza, entre otros, para proporcionar una abstracción fácil de usar de alto nivel para la especificación JMS (Java Message Service) de nivel inferior. Puede suscribirse a colas de mensajes JMS o temas de mensajes, lo que normalmente ocurre a través del atributo de activaciónConfig de la anotación @MessageDriven. Se agregaron en EJB para permitir el procesamiento controlado por eventos. A diferencia de los beans de sesión, un MDB no tiene una vista de cliente (Local/Remoto/Sin interfaz), i. mi. los clientes no pueden buscar una instancia de MDB. Un MDB solo escucha cualquier mensaje entrante en, por ejemplo, una cola o tema JMS y los procesa automáticamente. La especificación Java EE solo requiere compatibilidad con JMS, pero Message Driven Beans puede admitir otros protocolos de mensajería. Dichos protocolos pueden ser asíncronos pero también pueden ser síncronos. Dado que los beans de sesión también pueden ser sincrónicos o asincrónicos, la principal diferencia entre beans controlados por sesión y mensajes no es la sincronicidad, sino la diferencia entre la llamada a métodos (orientados a objetos) y la mensajería.

Ejemplos

Ejecución

Los EJB se implementan en un contenedor EJB, generalmente dentro de un servidor de aplicaciones. La especificación describe cómo interactúa un EJB con su contenedor y cómo interactúa el código del cliente con la combinación contenedor/EJB. Las clases EJB utilizadas por las aplicaciones se incluyen en el paquete javax.ejb. (El paquete javax.ejb.spi es una interfaz de proveedor de servicios utilizada solo por implementaciones de contenedores EJB).

Los clientes de EJB no instancian esos beans directamente a través del nuevo operador de Java, sino que deben obtener una referencia a través del contenedor EJB. Esta referencia generalmente no es una referencia al bean de implementación en sí, sino a un proxy, que implementa dinámicamente la interfaz comercial local o remota que solicitó el cliente o implementa dinámicamente un subtipo del bean real. Luego, el proxy se puede convertir directamente a la interfaz o al bean. Se dice que un cliente tiene una 'vista' en el EJB, y la interfaz local, la interfaz remota y el tipo de bean se corresponden respectivamente con la vista local, la vista remota y la vista sin interfaz.

Este proxy es necesario para dar al contenedor EJB la oportunidad de proporcionar de forma transparente servicios transversales (similares a AOP) a un bean como transacciones, seguridad, intercepciones, inyecciones y comunicación remota. Como ejemplo, un cliente invoca un método en un proxy, que primero iniciará una transacción con la ayuda del contenedor EJB y luego llamará al método del bean real. Cuando el método del bean regresa, el proxy finaliza la transacción (es decir, comprometiéndola o revirtiéndola) y transfiere el control al cliente.

El contenedor EJB es responsable de garantizar que el código del cliente tenga suficientes derechos de acceso a un EJB. Los aspectos de seguridad se pueden aplicar declarativamente a un EJB a través de anotaciones.

Transacciones

Los contenedores EJB deben admitir transacciones ACID administradas por contenedor y transacciones administradas por beans.

Las transacciones gestionadas por contenedor (CMT) están activas de forma predeterminada para llamadas a beans de sesión. Es decir, no se necesita una configuración explícita. El bean puede ajustar este comportamiento de forma declarativa a través de anotaciones y, si es necesario, dicha configuración puede anularse más tarde en el descriptor de implementación. El ajuste incluye desactivar transacciones para todo el bean o métodos específicos, o solicitar estrategias alternativas para la propagación de transacciones e iniciar o unirse a una transacción. Estas estrategias se ocupan principalmente de lo que debería suceder si una transacción ya está o no en curso en el momento en que se llama al bean. Se admiten las siguientes variaciones:

Transacciones declarativas Tipos de gestión
Tipo Explicación
MANDATORIA Si el cliente no ha iniciado una transacción, se lanza una excepción. De lo contrario se utiliza la transacción del cliente.
NECESITA Si el cliente ha iniciado una transacción, se utiliza. De lo contrario se inicia una nueva transacción. (este es el defecto cuando no se ha especificado ningún tipo explícito)
REQUIRES_NEW Si el cliente ha iniciado una transacción, se suspende. Siempre se inicia una nueva transacción.
APOYOS Si el cliente ha iniciado una transacción, se utiliza. De lo contrario, no se utiliza ninguna transacción.
NO_SUPPORTADO Si el cliente ha iniciado una transacción, se suspende. No se inicia ninguna nueva transacción.
Nunca Si el cliente ha iniciado una transacción, se lanza una excepción. No se inicia ninguna nueva transacción.

Alternativamente, el bean también puede declarar a través de una anotación que desea manejar transacciones mediante programación a través de la API JTA. Este modo de operación se llama Bean Managed Transactions (BMT), ya que el propio bean maneja la transacción en lugar del contenedor.

Eventos

JMS (Java Message Service) se usa para enviar mensajes de beans a clientes, para permitir que los clientes reciban mensajes asincrónicos de estos beans. Los MDB se pueden usar para recibir mensajes de clientes de forma asíncrona usando un JMS cola o un tema.

Servicios de nombres y directorios

Como alternativa a la inyección, los clientes de un EJB pueden obtener una referencia al objeto proxy del bean de sesión (el stub EJB) mediante la interfaz de directorio y nombres de Java (JNDI). Esta alternativa se puede utilizar en casos en los que la inyección no está disponible, como en código no administrado o clientes Java SE remotos independientes, o cuando es necesario determinar mediante programación qué bean obtener.

Los nombres JNDI para beans de sesión EJB son asignados por el contenedor EJB a través del siguiente esquema:

Nombres de JNDI
Ámbito Patrón de nombre
Global java:global[/ seleccion-nombre título]/ seleccionmodule-nombre comercial/cantabean-nombre titular[!
Aplicación java:app/ mademodule-name titulada " / identificadobean-name " [!
Módulo java:module/seguido-nombre de abejo[! identificado-calificado-interface-name]

(las entradas entre corchetes indican partes opcionales)

Se puede obtener un solo bean con cualquier nombre que coincida con los patrones anteriores, dependiendo de la 'ubicación' del cliente Los clientes en el mismo módulo que el bean requerido pueden usar el alcance del módulo y alcances más grandes, los clientes en la misma aplicación que el bean requerido pueden usar el alcance de la aplicación y superior, etc.

Por ej. el código que se ejecuta en el mismo módulo que el bean CustomerService (como se muestra en el ejemplo anterior de este artículo) podría usar el siguiente código para obtener una referencia (local) a él:

Servicio al Cliente cliente = ()Servicio al Cliente) nuevo Contexto inicial().Lookup()"java:module/CustomerService");

Ejecución remota/distribuida

Para la comunicación con un cliente que está escrito en el lenguaje de programación Java, un bean de sesión puede exponer una vista remota a través de una interfaz anotada @Remote. Esto permite llamar a esos beans desde clientes en otras JVM que pueden estar ubicadas en otros sistemas (remotos). Desde el punto de vista del contenedor EJB, cualquier código en otra JVM es remoto.

Los beans de sesión sin estado y Singleton también pueden exponer una "vista de cliente de servicio web" para la comunicación remota a través de WSDL y SOAP o XML simple. Esto sigue las especificaciones JAX-RPC y JAX-WS. Sin embargo, se propone la compatibilidad con JAX-RPC para su futura eliminación. Para admitir JAX-WS, el bean de sesión se anota con la anotación @WebService y los métodos que se van a exponer de forma remota con la anotación @WebMethod.

Aunque la especificación EJB no menciona la exposición como servicios web RESTful de ninguna manera y no admite explícitamente esta forma de comunicación, la especificación JAX-RS admite explícitamente EJB. Siguiendo la especificación JAX-RS, los beans de sesión Stateless y Singleton pueden ser recursos raíz a través de la anotación @Path y los métodos comerciales EJB se pueden asignar a métodos de recursos a través de las anotaciones @GET, @PUT, @POST y @DELETE. Sin embargo, esto no cuenta como una "vista de cliente de servicio web", que se usa exclusivamente para JAX-WS y JAX-RPC.

La comunicación a través de servicios web es típica para los clientes que no están escritos en el lenguaje de programación Java, pero también es conveniente para los clientes Java que tienen problemas para acceder al servidor EJB a través de un cortafuegos. Además, los clientes de Java pueden utilizar la comunicación basada en servicios web para eludir los requisitos misteriosos y mal definidos de las denominadas "bibliotecas de clientes"; un conjunto de archivos jar que un cliente Java debe tener en su class-path para poder comunicarse con el servidor EJB remoto. Estas bibliotecas cliente pueden entrar en conflicto con las bibliotecas que el cliente ya puede tener (por ejemplo, si el propio cliente también es un servidor Java EE completo) y se considera que dicho conflicto es muy difícil o imposible de resolver.

Legado

Interfaces de inicio e interfaz comercial requerida

Con EJB 2.1 y versiones anteriores, cada EJB tenía que proporcionar una clase de implementación de Java y dos interfaces de Java. El contenedor EJB creó instancias de la clase de implementación de Java para proporcionar la implementación de EJB. Las interfaces de Java fueron utilizadas por el código de cliente del EJB.

Descriptor de implementación requerido

Con EJB 2.1 y versiones anteriores, la especificación EJB requería que estuviera presente un descriptor de implementación. Esto era necesario para implementar un mecanismo que permitiera implementar los EJB de manera coherente, independientemente de la plataforma EJB específica que se eligiera. La información sobre cómo se debe implementar el bean (como el nombre de las interfaces de inicio o remotas, si se debe almacenar el bean en una base de datos y cómo, etc.) debe especificarse en el descriptor de implementación.

El descriptor de implementación es un documento XML que tiene una entrada para cada EJB que se implementará. Este documento XML especifica la siguiente información para cada EJB:

Los contenedores EJB antiguos de muchos proveedores requerían más información de implementación que la de la especificación EJB. Requerirían la información adicional como archivos XML separados o algún otro formato de archivo de configuración. Un proveedor de la plataforma EJB generalmente proporcionaba sus propias herramientas que leían este descriptor de implementación y posiblemente generaban un conjunto de clases que implementarían las ahora obsoletas interfaces Home y Remote.

Desde EJB 3.0 (JSR 220), el descriptor XML se reemplaza por anotaciones Java establecidas en la implementación de Enterprise Bean (a nivel de fuente), aunque aún es posible usar un descriptor XML en lugar de (o además de) el anotaciones Si un descriptor XML y anotaciones se aplican al mismo atributo dentro de un Enterprise Bean, la definición XML anula la anotación de nivel de fuente correspondiente, aunque algunos elementos XML también pueden ser aditivos (por ejemplo, una propiedad de configuración de activación en XML con un se agregará un nombre diferente al ya definido a través de una anotación @ActivationConfigProperty en lugar de reemplazar todas las propiedades existentes).

Variaciones de contenedores

A partir de EJB 3.1, la especificación EJB define dos variantes del contenedor EJB; una versión completa y una versión limitada. La versión limitada se adhiere a un subconjunto adecuado de la especificación llamado EJB 3.1 Lite y es parte del perfil web de Java EE 6 (que es a su vez un subconjunto de la especificación completa de Java EE 6).

EJB 3.1 Lite no admite las siguientes funciones:

EJB 3.2 Lite excluye menos características. En particular, ya no excluye @Asynchronous y @Schedule/@Timeout, pero para @Schedule no es compatible con "persistent" atributo que admite EJB 3.2 completo. La lista completa de excluidos para EJB 3.2 Lite es:

Historial de versiones

EJB 4.0, versión final (2020-05-22)

Jakarta Enterprise Beans 4.0, como parte de Jakarta EE 9, fue una versión de herramientas que movió principalmente los nombres de los paquetes API del nivel superior javax.ejb paquete al nivel superior jakarta.ejb.

Otros cambios incluyeron la eliminación de las API en desuso que no tenían sentido para pasar al nuevo paquete de nivel superior y la eliminación de las funciones que dependían de las funciones que se eliminaron de Java o en cualquier otro lugar en Jakarta EE 9. Se eliminaron las siguientes API:

Otros cambios menores incluyen marcar el grupo API Enterprise Beans 2.x como "Opcional" y hacer que la anotación Horario sea repetible.

EJB 3.2.6, versión final (2019-08-23)

Jakarta Enterprise Beans 3.2, como parte de Jakarta EE 8, y a pesar de que todavía usa "EJB" abreviatura, este conjunto de API se ha renombrado oficialmente como "Jakarta Enterprise Beans" por la Fundación Eclipse para no pisar el Oracle "Java" marca comercial.

EJB 3.2, versión final (2013-05-28)

JSR 345. Enterprise JavaBeans 3.2 fue una versión relativamente menor que contenía principalmente aclaraciones de especificación y eliminó algunas restricciones impuestas por la especificación, pero con el tiempo pareció no tener un propósito real. También se exigió que algunas características EJB completas existentes estuvieran en EJB 3 lite y la funcionalidad que se propuso eliminar en EJB 3.1 se eliminó de hecho (se hizo opcional).

Se agregaron las siguientes características:

EJB 3.1, versión final (2009-12-10)

JSR 318. El propósito de la especificación Enterprise JavaBeans 3.1 es simplificar aún más la arquitectura EJB al reducir su complejidad desde el punto de vista del desarrollador, al mismo tiempo que agrega nuevas funciones en respuesta a las necesidades de la comunidad:

EJB 3.0, versión final (2006-05-11)

JSR 220 - Cambios importantes: Esta versión facilitó mucho la escritura de EJB mediante el uso de 'anotaciones' en lugar de los complejos 'descriptores de implementación' utilizado en la versión 2.x. El uso de interfaces domésticas y remotas y el archivo ejb-jar.xml ya no eran necesarios en esta versión, ya que se reemplazó con una interfaz comercial y un bean que implementa la interfaz.

EJB 2.1, versión final (2003-11-24)

JSR 153 - Cambios importantes:

EJB 2.0, versión final (2001-08-22)

JSR 19 - Cambios importantes: Objetivos generales:

EJB 1.1, versión final (17-12-1999)

Cambios importantes:

Objetivos para la versión 1.1:

EJB 1.0 (24 de marzo de 1998)

Anunciado en JavaOne 1998, la tercera conferencia de desarrolladores de Java de Sun (del 24 al 27 de marzo) Objetivos para la versión 1.0: