Pautas asociadas al uso de EJB3

LIBP-0043 (Libro de pautas)

Se deben tener en cuenta las siguientes pautas para el desarrollo de aplicaciones basadas en EJB3.

Pautas

TítuloCarácter
Elección correcta de la estrategia de herenciaObligatoria
Usar consultas con nombreObligatoria
Uso de la interfaz remota y de la interfaz local en los beans de sesiónObligatoria
Usar los beans de sesión con estado solo cuando sea necesarioObligatoria
Uso correcto de las transacciones
Utilizar un método Remove en los beans de sesión con estadoObligatoria
No realizar inyecciones de un bean con estado sobre un objeto sin estadoObligatoria

Elección correcta de la estrategia de herencia

EJB3 soporta tres tipos de estrategia de herencia en la vinculación. Cada una con sus ventajas y desventajas, pero la estrategia basada en tablas simples (single-table strategy) es la que probablemente ofrezca un mejor rendimiento. Esto es debido a que todas las entidades se almacenan en una tabla simple y los "JOINs" entre tablas están permitidos. Lo recomendable es crear una tabla y discriminarlas de forma eficiente. Una columna discriminadora es aquella que contiene un valor único de un tipo de objeto en una fila de la tabla. Por ejemplo, la tabla se discrimina por el tipo de usuario:

@Table(name = "USERS")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name = "USER_TYPE",discriminatorType = DiscriminatorType.STRING, length = 1)
public class User ...

@Entity
@DiscriminatorValue(value = "S")
public class Seller extends User ...

@Entity
@DiscriminatorValue(value ="B")
public class Bidder extends User

Usar consultas con nombre

En lugar de usar consultas dinámicas, asegúrese de que utiliza consultas con nombre en su aplicaciones. Una consulta con nombre se prepara una vez y puede ser reutilizada por el proveedor de persistencia de forma eficiente. Además, el SQL generado puede ser almacenado en caché. Usted puede convertir la consulta anterior a una consulta con nombre como este:

@NamedQuery(
name = "findCategoryByName",
query = "SELECT c FROM Category c WHERE c.categoryName = ?1")

Uso de la interfaz remota y de la interfaz local en los beans de sesión

Solo se debe utilizar la interfaz remota cuando se realicen invocaciones desde diferentes JVM

EJB 3 no sólo proporciona la capacidad de invocar los componentes de forma remota, sino también le autoriza para construir componentes ligeros que se pueden implementar y ejecutar localmente con los módulos de su presentación. Si sus clientes y los componentes EJB están colocados juntos, entonces debe asegurarse de que no se debe marcar con su interfaz la anotación @Remote. La interfaz remota utiliza una costosa llamada RMI incluso si los clientes están en la misma JVM.

Si su arquitectura tiene una condición por la cual la aplicación cliente tiene que ejecutarse en una máquina diferente JavaVirtual (JVM) de la que se utiliza para ejecutar los beans de sesión en un contenedor EJB, entonces necesita utilizar la interfaz remota. La JVM distinta, puede ubicarse en la misma máquina física o en máquinas separadas. Si su arquitectura de aplicaciones va a utilizar la misma JVM, tanto para la aplicación de cliente y los beans de sesión, se debe utilizar la interfaz local.

  • La anotación @Remote puede utilizarse para referirse a la interfaz de negocio a distancia.
  • La anotación @Local puede ser usado para denotar la interfaz de negocio local.

Usar los beans de sesión con estado solo cuando sea necesario

Existe una tendencia a abusar de los beans de sesión con estado, que hace que los desarrolladores queden decepcionados con su rendimiento. La mayoría de las aplicaciones empresariales no tienen estado por naturaleza, por lo que se debe determinar si se necesitan beans de sesión con estado . Los beans de sesión sin estado ofrecen un desempeño mucho mejor que los beans de sesión con estado, ya que no están obligados a administrar el estado. Por lo tanto, es recomendable solo usar los beans de sesión con estado si su uso es justificado.

Uso correcto de las transacciones

En el caso de de utilizar CMP es recomendable estudiar sin son necesarias todas las transacciones, prestando especial atención a los atributos de transacción de cada método de negocio.

La gestión de transacciones es un asunto costoso. Es recomendable verificar que cada método EJB realmente necesita una transacción. Si está utilizando el manejo de transacciones por CMT (por defecto), el contenedor inicia una transacción porque el valor predeterminado del atributo de transacciones es "Required" . Para los métodos que no requieren de una transacción, debe explícitamente deshabilitar las transacciones estableciendo el tipo de transacción a NOT_SUPPORTED de la siguiente manera:

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public List<Item> findMostPopularItems() {
...
}

Utilizar un método Remove en los beans de sesión con estado

Se debe destruir una instancia de bean de sesión con estado usando la anotación @Remove cuando concluye la conversación. Cualquier método de negocio puede ser anotado con @Remove para que una vez finalizada con éxito de ese método de negocio, la instancia del bean será destruido. Se puede ver en confirmOrder:

@Remove
public Long confirmOrder() {
}

Si no se eliminan las instancias del bean con estado cuando ya no se necesitan, es muy probable que el número de instancias del bean inactivas crezca forzando a la continua activación/desactivación del contenedor. Además de esta anotación, la mayoría de los contenedores proporcionan un tiempo de terminación para destruir una instancia de un bean. Este tiempo de espera (time out) es útil para mantener el número de instancias del bean en un número manejable. Es recomendable utilizar este tiempo de terminación.

No realizar inyecciones de un bean con estado sobre un objeto sin estado

No se debe inyectar un bean de sesión con estado en un objeto sin estado, porque un bean de sesión con estado puede estar compartido por múltiples clientes de forma concurrente. Para estos casos es recomendable usar JNDI.

Esto se debe a que cuando se utiliza la inyección de dependencias, el contenedor inyecta un nuevo bean de sesión con estado en el bean de sesión sin estado, el mismo bean de sesión con estado no puede ser inyectado en todos los beans de sesión sin estado. Si se hace uso de JNDI, la referencia a un bean de sesión con estado puede ser obtenida e inyectada en todos los beans de sesión sin estado. El mismo bean con estado podría ser utilizado.