La pregunta SCBCD del día: @PreDestroy

(Imagen: Henri Matisse - El postre: Armonía en rojo)

A developer wants to release resources within a stateless session bean class. The cleanup method should be executed by the container before an instance of the class si removed. The deployment descriptor is not used. Wich three statements are correct? (Choose three)

  • The cleanup method may declare checked exceptions
  • The cleanup method must have no arguments and return void.
  • The cleanup method is executed in an unspecified transaction and security context.
  • The developer sholud mark the cleanup method with the @PreDestroy annotation.
  • The developer should mark the cleanup method with the @PostDestroy annotation.
  • The cleanup method is executed in the transaction and security context of the last business method invocation.

Los beans stateless son destruidos (i.e removidos de memoria) por el contenedor cuando estos ya no son necesarios. Este proceso se inicia cuando el evento PreDestroy del bean es disparado. La clase del bean puede registar un método para manejar este evento mediante la anotación @javax.annotation.PreDestroy (la cuarta va, y la quinta no existe xD). Este método puede tener cualquie nombre , pero debe devolver void, no admitir parámetros y no lanzar excepciones checked (la primera no va, pero la segunda sí). La clase bean puede definir sólamente un método @PreDestroy, y este método se utiliza por lo general para realizar operaciones de "limpieza", como cerrar recursos en utilización; que es lo que requiere la pregunta.

Y para terminar, los métodos PreDestroy se ejecutan en contexto transaccional y de seguridad no especificado. Por lo tanto, nos quedamos con la segunda, la tercera y la cuarta.

Pregunta tomada de ExamWorx

Segunda SCBCD del día: RunAs y RollesAllowed

(Imagen: Henri Matisse - La Danza)

Given:

10. @Stateless
11. @RunAS("X")
12. public class SecureBean01 implements Secure01{
13. @EJB Secure02 secure02;
23. @RolesAllowed("A")
24. public void methodA(){
25. secure02.methodB();
26. }
}
10. @Stateless
11. public void SecureBean02 implements Secure02{
23. @RolesAllowed("A")
24. public void methodB(){
}
}

A user who us only in role A invokes Secure01.methodA. Assuming NO other security-related metadata, what is the expected result?
  • An exception is thrown at Line 25
  • An exception is thrown at Line 13
  • methodA cannot be invoked by this user
  • The code executes without raising an exception
Es posible especificar un rol runAs para un EJB como hemos hecho para nuestra instancia de SecureBean1. Mientras que con la anotación @RollesAllowed y los elementos especificamos que roles pueden acceder a los métodos del bean (por lo que el usuario de rol A puede acceder a method A, descartando la tercera), la anotación runAs especifica el rol bajo el cual el método se va a ejecutar. En cristiano, el rol runAs es utilizado como la identidad del EJB cuando trata de ejecutar métodos en otros beans,  y esta identidad no es necesariamente la misma que está accediendo al bean.

Recapitulando, nuestro usuario accede al método methodA dado que mediante RolesAllowed se le ha dado acceso al rol "A". Ahora, dentro de methodA el bean asume el rol "X", debido a RunAs y con ese rol intentamos ejecutar methodB en SecureBean02. Pero methodB solo permite el acceso a usuarios con el rol "A" (mediante RolesAllowed), por lo que no se permite el acceso a methodB, y una excepción es lanzada en la línea 25.

Entonces, nuestra respuesta es la primera.




Pregunta tomada de ExamWorx

La pregunta SCBCD del día: Stateful Session Beans


(Imagen: Henri Matisse - Mujer con sombrero)

A developer creates a stateful session bean that is used by many concurrent clients. The clients are written by other developement teams and it is assumed that these clients might not remove the bean when ending their session. The number of concurrent sessions will be greater than the defined bean cache size. The developer must consider that the state of the session bean can be influenced by either passivation or timeout. Which three actions should the developer take to make the bean behave correctly in passivation and timeout situations? (Choose three)

  • Release references to resources ina a @Remove annotated method
  • Re-establish references in an @Init annotated method
  • Release references to resources in a @PreDestroy annotated method
  • Release references to resources in a @PrePassivate annotated method
  • Re-establish references to resources in a @PostActivate annotated method


La anotación @javax.ejb.Remove le indica al contenedor EJB que cuando el método anotado finalice, el cliente no necesita más de la sesión, y procede a removerla. LA pregunta indica que no es una garantía que los beans se remuevan de sesión, así que esta alterntiva queda descartada.

La anotación @javax.ejb.Init se usa por cuestiones de compatibilidad con los session beans de EJB 2. Los métodos anotados con @Init tienen un comportamiento similar al método create de un session bean de EJB 2. Nada que ver con la pregunta, así que la segunda no va.

Por otro lado, el contenedor puede desechar una instancia EJB cuando el bean expira (timeout). Cuando ocurra el timeout, el contenedor puede invocar al método anotado con @PreDestroy, por lo que sería un buen momento para liberar recursos. Cabe resaltar, que un bean Stateful no puede expirar mientras una transacción esté en proceso. Entonces, la tercera va.


Antes que un bean sea "pasivado" (passivated), se invoca al método del bean anotado como @PrePassivate. La instancia puede en este método cerrar recursos abiertos y colocar los campos no-serializables y no-transient a null (para evitar problemas al serializar, ya que los campos transient son ignorados). Se desea este comportamiento, por lo que la cuarta también va.

Después de la "pasivación", se procede a recuperar el estado conversacional del bean, y es ahí donde se invoca al método anotado como @PostActivate. Aquí, la instancia puede abrir recursos que no han sido "pasivados" e inicializar valores de sus campos transient. Bastante útil para nuetsros fines, por lo que la qunita va.

Concluyendo, tenemos la tercera, la cuarta y la quinta.

Pregunta tomada de ExamWorx

Otra SCBCD hoy día: EntityManager.remove()

(Imagen: Paul Cézanne  - Retrato del tío Dominique)

A developer implemented a Java class called Store. The class is annotated correctly to act as an Entity. The developer created a stateless session bean to create, lookup, and remove Store objects. This session bean has a container managed entity manager injected into field em and a removeStore method with transaction attribute REQUIRED.

Given the following code:

32. public void removeStore(Store store){
33. em.remove(store);
34. }

What is a possible reason that an IllegalArgumentException is thrown al Line 33 when the removeStore method is called by a remote client?

  • The passed object is NOT serializable
  • The passed object is NOT found in the database
  • The passed object is NOT managed by the entity manager
  • There is no active transaction to manage the database remove

Una entidad puede ser borrada de base de datos invocando al método EntityManager.remove(). La operación remove() no borra inmediatamente los registros de la base de datos. Cuando el entity manager decide dar flush, se ejecuta una setencia SQL DELETE.

El método remove () lanza una IllegalArgumentException si el parámetro que recibe no es del tipo entidad (pero según la pregunta, esto no sucede). Se lanza la excepción TransactionRequiredException cuando no ejecuta en un contexto transaccional (pero como su atributo de transacción es REQUIRED, esto tampoco sucede).Si la entidad parámetro es una entidad "DETACHED" (o sea, no es administrada por el Entity Mannager), se lanza la excepción IllegalArgumentException... por lo que nuestra respuesta es la tercera.




Pregunta tomada de ExamWorx

La pregunta SCBCD del día: Application Exceptions

(Imagen: Paul Cézanne - Jugadores de cartas)


Which is the correct way of defining a runtime exception as an EJB 3.0 application exception?

  • public class MyAppException extends javax.ejb.EJBException
  • @ApplicationException public class MyAppException extends java.rmi.RemoteException
  • public class MyAppException extends java.lang.RuntimeException
  • @ApplicationException public class MyAppException extends java.lang.RuntimeException

Una excepción de aplicación se lanza en respuesta a un error de lógica de negocio,y no a un error de sistema. Las excepciones de aplicación son siempre  enviadas al cliente sin ser "envueltas" en excepciones del tipo EJBException(la primera no es!). Por defecto, no provocan rollback en la transacción. En este caso, el cliente tiene la oportunidad de recuperarse después de que la excepción de aplicación ha sido lanzada. Las excepciones de aplicación no heredan de RuntimeException o de RemoteException (What?!... paciencia, esto lo explicamos luego)

La anotación @javax.ejb.ApplicationException se puede usar para forzar a una excepción de aplicación a dar rollback a la transacción automáticamente (@ApplicationException(rollback=true)). Esta anotación también puede usarse en subclases de java.lang.RuntimeException y java.rmi.RemoteException. Nos sirve para evitar que una excepción RuntimeException sea "envuelta" en una EJBException,o para que una subclase de RemoteException no de rollback a la transacción, por ejemplo.

Entonces, nos quedamos con la cuarta....no?


Pregunta tomada de ExamWorx

Segunda SCBCD del día: Excepciones y Transacciones

(Imagen: Paul Cézanne - Mujer de Sombrero Verde)

FooBean and BarBean are both EJB 3.0 stateless session beans with container-managed transaction demarcation. All business methods in the two beans have transaction attribute REQUIRED. The business method foo in FooBean invokes the business method bar in BarBean.

Given:

10. public class BarBean{
11. public void bar(){
12. throw new EJBException("unexpected error...");
13. }
14. }

Which statement is true abput the result of this method invocation assuming execution reaches Line 12?

  • The container might roll back the transaction
  • The BarBean bean instance is in the ready state for the next invocation.
  • FooBean.foo method receives javax.ejb.EJBTransactionRolledBackException
  • FooBean.foo method receives javax.transaction.InvalidTransactionException

Antes de comenzar, debemos definir algunas cosas. Una excepción de sistema (System exception) incluye a java.lang.RuntimeException y sus sub-clases, como EJBException, lanzada en la línea 12. También se incluye java.rmi.RemoteException y sus sub-clases.

En los session beans (como el de la pregunta) cuando ocurre una excepción de sistema (como la de la pregunta) la instancia es desechada (de ahí inferimos que la segunda no va) y se lanza una RuntimeException. Si el cliente inicio la transacción (en nuestro caso, el cliente que inició la transacción es FooBean), que luego fue propagada al EJB (BarBean), el contenedor captura una excepción de sistema y la lanza como javax.ejb.EJBTransactionRolledbackException. EJBTransactionRolledbackException es una sub-clase de RuntimeException y le da al cliente la noticia de que ocurrió un rollback. Por ende, la respuesta correcta es la tercera opción.

Si el cliente no propagó la excepción al EJB, la excepción de sistema será capturada y lanzada como una EJBException. Pero ese no es el caso.

Pregunta tomada de ExamWorx

Primera SCBCD del día: UserTransaction.getStatus()

(Imagen: Paul Cézanne - Autorretrato)

Bean A is using bean-managed transaction demarcation and has invoked the foo method of bean B. When the foo method returns, bean A needs to determine if the transaction has been set to rollback Which must be true?

  • It is not possible for bean A to determine if the transaction has been set to rollback
  • Bean A must invoke getStatus method on the UserTransaction that it began
  • For this to be possible, bean B must also use bean-manged transaction demarcation.
  • Bean A must invoke the setRollbackOnly method on the UserTransaction that it began
  • Bean A must invoker the getRollbackOnly method on the UserTransaction that it began.

Los EJB's que usen BMT (Bean Managed Transaction, como en la pregunta) pueden acceder a UserTransaction desde EJBContext, mientras que los EJB's CMT (Container Managed Transaction) no pueden hacerlo. Los beans CMT utilizan los métodos setRollbackOnly y getRollbakOnly de EJBContext (y no de UserTransaction, con lo que la cuarta y quinta quedan muy decartadas) para interactuar con la transacción actual.


Para el caso de los beans BMT, UserTransaction nos provee del método getStatus, que retorna un entero comparable con las constantes de la interfaz javax.transaction.Status (para el caso de nuestro interés , el valor sería STATUS_ROLLEDBACK). Se puede utilizar este método para determinar el estado de la transacción asociado al objeto UserTransaction.

Por lo que, evidentemente, la respuesta sería la segunda.

Pregunta tomada de ExamWorx

La última SCBCD (del día): Timeout callback method

(Imagen: Paul Cézanne - La casa del ahorcado)

Ya me cansé... esta es la última del día.

Which statement is true about the Timer service in an EJB 3.0 stateless session bean?

  • The timeout callback method contains the business logic that handles the timeout event
  • The timeout callback method must be declared as a business method in business interfaces.
  • The timeout callback method can throw application exceptions to report business logic failures
  • A bean class can implement multiple timeout callback methods, each associated with a differrent timer.

Los métodos timeout callback deben poseer la anotación Timeout (o mediante timeout-method en el descriptor de despliegue) o el  bean debe implementar la interfaz javax.ejb.TimedObject, que posee el método ejbTimeout. Un bean sólo puede tener como máximo un método timeout. Entonces, la cuarta no va.

Los métodos timeout callback no deben lanzar excepciones de aplicación. Por lo tanto, la tercera tampoco va. 

Cuando expira el timer, el contenedor invoca al método timeout en el bean registrado para ese timer. El método timeout contiene la lógica de negocio que el proveedor del Bean provee para manejar el evento de timeout. Entonces nuestra respuesta es la primera.


Pregunta tomada de ExamWorx

Y seguimos con las preguntas SCBCD: setRollbackOnly

(Imagen: Paul Cézanne - El asesinato)

A session bean calls the setRollbackOnly method on the EJBContext interface within a business method with an active transaction, Which two are correct? (choose two)

  • The transaction timeout is immediately disabled
  • The container will ensure that the transaction will never commit
  • The bean must have started the current transaction for this to be legal
  • The bean must have bean-managed transaction demarcation for this to be legal
  • The bean must have container-managed transaction demarcation for this to be legal.


Un EJB con transacciones administradas por contenedor (CMT), puede usar el método setRollbackOnly del objeto EJBContext para marcar la transacción de modo que nunca se le de COMMIT.

El método setRollbackOnly procederá de esa manera si se le invoca de un método de negocio con atributos de transacción REQUIRED, REQUIRES_NEW y MANDATORY. En caso se le invoque desde métodos de negocio con atributos de transacción SUPPORTS, NOT_SUPPORTED o NEVER se lanzará la excepción java.lang.IllegalStateException.

Por lo expuesto, la respuesta es la segunda y la quinta.



Pregunta tomada de ExamWorx

Otra pregunta SCBCD: FlushMode

(Imagen: Paul Cézanne - La montaña Sainte-Victoire)

A business method of a stateless session bean with a transaction attribute REQUIRED executes a Java Persistence query on a container-managed persistence context.

Under which two conditions can the developer expect the persistence provider ensure that all changes made to the persistence context in the transaction are visible to the processing of the query? (Choose two)

  • The flush mode is NOT explicitly set.
  • The flush mode on the QUERY object is set to COMMIT.
  • The refresh method on the EntityManager is called.
  • The flush mode on the persistence context is set to AUTO but is NOT specified for the Query object
Tenemos dos posibles valores para el flush mode del EntityManager. Cuando está en AUTO, el flush se realiza automáticamente antes que se realize un query relacionado con entidades modificadas y al momento de darle commit a la transacción. Este es el valor por defecto, por lo que en la primera opción ese es el valor que toma el flush mode y ese es el comportamiento que necesitamos. Por lo tanto, la primera va. El otro valor posible es COMMIT, e implica que se da flush a los cambios sólo cuando se da commit a la transacción y no antes de un query. Y eso no es lo que queremos.


Ahora, la interfaz Query también posee un método setFlushMode que le permite cambiar el momento en el que se realiza el flush; para forzar un modo de flush diferente al del EntityManager para la duración del Query. Por ejemplo, una query quiere asegurarse que el EntityManager no haga flush antes de que se ejecute la query . Para esta situación, bastaría cambiar el modo de flush del query a COMMIT (query.setFlushMode(FlushModeType.COMMIT)). Pero esto no es lo que se quiere. De haber conservado el valor por defecto (FlushModeType.AUTO), se habría realizado el flush antes del Query, que es lo que necesitamos. Entonces, la segunda no va y la cuarta sí.

Por lo que la respuesta es la primera y la cuarta.

PS: Para no quedarnos con dudas en lo referente a la tercera alternativa; el método refresh de EntityManager toma por parámetro un objeto entidad y refresca su estado con valores tomados de la base de datos, sobreescribiendo cualquier cambio realizado. Nada que ver con la pregunta...no?



Pregunta tomada de ExamWorx

Una más SCBCD: Restricciones de programación EJB 3.0

(Imagen: Paul Cézanne - Bodegón con cortina)

A este paso, me voy a quedar sin pinturas xD

Which two are programming restrictions in the EJB 3.0 specification? (Choose two)

  • An enterprise bean must NOT attempt to load a native library
  • An enterprise bean must NOT declare static fields as final
  • An enterprise bean must NOT attempt to create a new security manager
  • An enterprise bean must NOT propagate a RuntimeException to the container
  • An enterprise bean must NOT attempt to obtain a javax.naming.InitialContext
Las restricciones de programación son muchas, pero aquí nos piden identificar dos. Comencemos:

Un EJB no debe leer ni escribir campos estáticos. Si se permite el uso de campos estáticos de sólo lectura, por lo que se recomienda que todos los campos estáticos de una clase EJB sean declarados como FINAL. Entonces, la segunda no va.

Un EJB no debe intentar crear un class loader; obtener el class loader actual; configurar el class loader; configurar el security manager; crear un nuevo security manager; detener la JVM; o cambiar los streams de input, output y error (uff!!!). De lo que inferimos que la segunda es correcta.

Además, un EJB no debe intentar cargar una librería nativa, ya que este trabajito lo hace el contenedor EJB. DE ahí que la primera también es correcta.

En lo referente a la cuarta y la quinta opción, las he buscado en el listado de restricciones y no las he encontrado; debido a que son tareas comunes y se realizan con frecuencia en el desarrollo EJB. Por lo tanto, nos quedamos con la primera y la tercera.


Pregunta tomada de ExamWorx

Otra pregunta SCBCD: Atributo de transacción MANDATORY

(Imagen: Paul Cézanne - Una Olimpia moderna)

La segunda (se los advertí xD):

A developer wants to achieve the following two behaviors for an EJB 3.0 session bean:

(1) If the client calls a business method with a transaction context, the container will invoke the enterprise bean's method in the client's transaction context.

(2)If the client calls a business method without a transaction context, the container will throw the javax.ejb.EJBTransactionRequiredException

Which transaction attribute should be used?

  • REQUIRED
  • SUPPORTS
  • MANDATORY
  • REQUIRES_NEW
  • NOT_SUPPORTED
Esta vez, comenzaremos por la respuesta correcta, que es la tercera. Como describe a detalle la pregunta, el atributo MANDATORY significa que el método EJB siempre debe ser parte de la transacción del cliente que lo invoca. El EJB no debe comenzar su propia transacción, ya que la transacción debe ser propagada desde el cliente. Y si se da el desafortunado caso que el cliente invocante (o sea ...el que invoca) no es parte de una transacción, la invocación fallará y se lanzará la excepción javax.ejb.EJBTransactionRequiredException.




Pregunta tomada de ExamWorx

La pregunta SCBCD del día: EntityManager.flush()

(Imagen: Paul Césanne - Muchacha al piano)

La primera del día (hoy se vienen muchas):

A developer is modifying an existing Java EE application that uses the JDBC API to access the database. This code must be used but cannot be changed, and new code needs to be added that uses the Java Persistence API.

Both parts of the code will execute in the same JTA transaction.

Which method of the EntityManager interface should the new code use to ensure that the data read by JDBC statements includes the state of managed entities?

  • Call refresh on each changed entity
  • Call flush at the end of each business  method
  • Call find before accessing any managed entity
  • Call  lock at the beginning of each business method
Cuando llamamos a persist(), merge (), o remove(), estos cambios no se sincronizan con la base de datos hasta que el EntityManager decida confirmarlos. Podemos forzar la sincronización en cualquier momento llamando a flush() en el EntityManager, de modo que los cambios realizados ya pasen a la BD. Por defecto, se invoca a flush antes que se ejecute una query relacionada con los cambios y al momento de realizar commit en una transacción.

Regresando a la pregunta, nuestro código JPA y el código JDBC legacy se ejecutan en la misma transacción; por lo que existe la posibilidad de que los cambios realizados por el código JPA no estén confirmados en BD al momento de ejecutar el código JDBC, lo que nos llevaría a sucesos impredecibles e indeseables. Para evitar esto, mejor llamamos a flush después de cada método JPA, de modo que los cambios ya estén en BD al momento de ejecutar el código JDBC.

Por lo expuesto, la respuesta correcta sería la segunda





Pregunta tomada de ExamWorx

Una pregunta SCBCD más: EJB QL


(Imagen: Andy Warhol - Sopa Campbell)

Ya deben andar aburridos con tanta pregunta...no?

A developer wants to create a Java Persistence Query that returns valid U.S phone numbers (formatted as "123-456-7890" or "800-RUN-EJB3") from a collection of differently formated international phone numbers. The developer needs only those numbers that begin with 303. Which WHERE clause is correct?
  • WHERE addr.phone LIKE '303_'
  • WHERE addr.phone LIKE '303%'
  • WHERE addr.phone LIKE '303-_-_'
  • WHERE addr.phone LIKE '303-%-%'
  • WHERE addr.phone LIKE '303-___-____'
  • WHERE addr.phone LIKE '303-%%%-%%%%'
El operador LIKE nos permite consultar Strings que pertenezcan a un patrón específico, en este caso el patrón de números de teléfono americanos. Se nos permite usar dos caracteres especiales al momento de definir un patrón: porcentaje (%) para cualquier secuencia de caracteres y underscore (_) para un sólo caracter.

Entonces la idea del patrón para la pregunta dada es que se inicie con '303-', le sigan tres caracterés, aparezca otro guión '-' y finalmente le sigan 4 caracteres. Para este fin, usamos underscore para representar a cada caracter por lo que la respuesta correcta es la quinta.

Pregunta tomada de ExamWorx

Otra pregunta SCBCD: Manejo de Transacciones

(Imagen: Salvador Dalí - Crucifixión)

Una más!

Given a set of CMT bean methods with the following transaction attributes:

Method M1 = SUPPORTS
Method M2 = REQUIRED
Method M3 = NOT_SUPPORTED
Method M4 = REQUIRES_NEW

And the following invocation sequence:

Method M1 invokes Method M2
Method M2 invokes Method M3
Method M1 invokes Method M4

If Method Mº1 is invoked by a method that does NOT have a transaction context, which describes a possible scenario?

  • Method M1: no transaction
    Method M2: new transaccion
    Method M3: no transaction
    Method M4: new transaction
  • Method M1: no transaction
    Method M2: Container throws EJBTransactionRequiredException
  • Method M1: new transaction
    Method M2: runs in the same transaction as M1
    Method M3: Container throws TransactionNotSupportedException
  • Method M1: no transaction
    Method M2: new transaction
    Method M3: Container throws TransactionNotSupportedException
Una vez, y como casi siempre, vamos por partes:

Se invoca M1 desde un método que no posee un contexto transaccional. Como el atributo de transacción de M1 es SUPPORTS, no se crea una nueva transacción. De haber existido un contexto transaccional, M1 se hubiera incluido en él, pero ese no es el caso. Entonces, para M1 no hay transacción.

M1, que no posee contexto transaccional, invoca a M2. El atributo de transacción de M2 es REQUIRED, lo que implica que M2 comenzará su propia nueva transacción (para que quede constancia, si M1 estaba en un contexto transaccional se hubiera unido a él). Segundo paso: M2 crea una nueva transacción.

M2 en su nueva transacción invoca a M3, cuyo atributo de transacción es NOT_SUPPORTED. Es debido a esto que la transacción M2 es suspendida hasta que el método M3 se complete, y cuando se complete se continuará con la transacción de M2. Pero en M3 no se ejecuta transacción alguna.

Y para terminar esto, M1 invoca a M4, cuyo a tributo de transacción es REQUIRES_NEW, por lo que una nueva transacción siempre es iniciada, sin importar que el cliente sea o no parte de una transacción. Entonces, M4 se ejecuta en una nueva transacción.

Por lo que queda demostrado que la respuesta correcta es la primera.

PS: Para los que se quedaron curiosos, la excepción javax.ejb.EJBTransactionRequiredException es lanzada cuando se invoca a un método con atributo de transacción MANDATORY desde un cliente que no es parte de una transacción;

Pregunta tomada de ExamWorx

La pregunta SCBCD del día: Message Driven Beans

(Imagen: Salvador Dalí - Autorretrato)

La primera del día:

Given code snippets from two files:

public class Dog{
public void onMessage(Message m){
System.out.print("1");
}
}

and

@MessageDriven
class MessageDog extends Dog implements MessageDrivenBean{
MessageDog (Message m){
System.out.print("2");
}
}

Which four code changes, when used togeteher, create a valid JMS message driven bean?

  • Make class MessageDog public
  • Make the MessageDog constructor no-arg
  • Make the MessageDog constructor public
  • Move the onMessage method to the class MessageDog
  • Change MessageDog that is not a subclass of Dog
  • Make class MessageDog implement MessageListener instead of MessageDrivenBean.

Hora de repasar los requisitos para construir un MDB (Message Driven Bean) válido. Veamos:

  • La clase debe ser pública, no final y no abstracta. Por lo tanto, debemos considerar la primera opción
  • La clase debe tener un constructor público que no reciba argumentos. Entonces, la segunda y la tercera opción también son necesarias para que esto funcione.
  • La clase debe implementar, directa o indirectamente, la interfaz message listener necesaria. De tratarse de un MDB JMS, la interfaz a implementar es javax.jms.MessageListener. Para esto, debemos considerar la cuarta opción ( el implementar jax.ejb.MessageDrivenBean es opcional) de modo que se implemente javax.jms.MessageListener de manera indirecta, ya que el método onMessage está en la clase padre Dog.
Entonces, nos quedaríamos con la primera, segunda, tercera y quinta opción.

Pregunta tomada de ExamWorx

Mas preguntas SCBCD: Relación ManyToMany

(Imagen: Miguel Ángel - Autorretrato)

Given two entities with a many-to-many bidirectional association between them:

@Entity
public class Employee{
Collection projects;
//more code here
}

and

@Entity
public class Project{
Set emps;
//more code here
}

What set of annotations correctly defines the association?

  • @ManyToMany in the projects field / @ManyToMany (mappedBy="project") on the emps field
  • @ManyToMany (mappedBy="emps") on the projects field / @ManyToMany on the emps field
  • @ManyToMany (targetEntity=Project.class)  on the projects field /@ManyToMany (mappedBy="projects ") on the emps field
  • @ManyToMany(targetEntity=Project.class)  on the projects field / @ManyToMany on the emps field
Observamos que en la clase Employee, el atributo projects de tipo Collection no está haciendo uso de Generics. Por ende, nos vemos en la necesidad de usar el atributo targetEntity de la anotación ManyToMany, para señalar la clase entidad con la que se tiene relación. En Project, esto no es necesario ya que por medio del generic indicamos que la relación es con Employee (en el atributo emps)

Ahora, nos valemos del atributo mappedBy de ManyToMany para indicar la propiedad en la clase Employee que define la relación. Por ende, Project es el lado inverso de la relación.

Entonces... la respuesta es la tercera



Pregunta tomada de ExamWorx

Otra pregunta SCBCD: Merge y EntityManager



(Imagen : Claude Monet - Señora Monet en traje Japonés)

Una más, para mantener el ritmo:

Given:

@PersistenceContext
EntityMAnager em;
public boolean test (Order o){
boolean b = false;
o = em.merge(o);
em.remove(o);
o = em.merge(o);
b = em.contains(o);
return b;

}

Which statement is correct?

The method will return TRUE
The method will return FALSE
The method will throw an exception
The Order instance will be removed from database


Para resolver esto, debemos tener bien claro lo que hace el método merge de EntityManager. Merge nos permite sincronizar los cambios de estado realizados a una entidad no administrada (o sea  no administrada por el EntityManager... los gringos usan "detached")con la base de datos.  Dada la sentencia : B = em.merge(A) podemos inferir que :

  • Si A no es una entidad, se lanzará la excepción IllegalArgumentException
  • Si A no está administrada, su estado es copiado a la instancia administrada B
  • Si A es una entidad nueva, se crea la nueva entidad administrada B y el estado de A es copiado a B
  • Si A es una entidad administrada existente, se ignora la sentencia
  • Si A es una entidad removida (como es nuestro caso, ya que se ejecutó em.remove(o) ), se lanza la excepción  IllegalArgumentException
Por ende, al ejecutar el segundo merge(o) ocurriría la última situación descrita, por lo que seleccionariamos la tercera opción como respuesta.

Aunque nunca llega a ejecutarse, cabe resaltar que EntityManager.contains se utiliza para determinar si una entidad está siendo administrada por el Contexto de Persistencia (o sea ...el EntityManager). De ser así retorna TRUE, caso contrario... FALSE.


Pregunta tomada de ExamWorx

La pregunta SCBCD del día: Entity Callbacks

(Imagen: Claude Monet - Camile Monet en su lecho de muerte)

Una más:

A developer wants to create a portable EJB 3.0 application that includes de following class definiton for the entity account:

@Entity
@EntityListeners(com.acme.AlertMonitor.class)
public class Account {
//more code here
@PrePersist
protected void validateCreate(){
/*more code here*/
}
}


Which statement is correct?

  • The validateCreate method may NOT throw runtime exceptions
  • The validateCreate method can invoke the EntityManager.flush operation
  • Methods of the class com.acme.AlertMonitor annotated with callback annotations must take an Object or Account instance as only argument
  • The above class definition is NOT correct. An entity cannot define a callback method like PrePersist and use EntityListeners annotation at the same time.
A ver ... vamos por partes. Los métodos callback (como PrePersist) de las entidades pueden lanzar excepciones runtime, por lo quer la primera opción sería incorrecta.

La pregunta establece que el código debe ser portable, por lo que para ese fin se recomienda no invocar a EntityManager, Query, acceder a otras entidades o modificar relaciones en métodos callback de entidades. Segunda opción, descartada también.

Los métodos callback de las entidades definidos directamente en la clase entidad (como validateCreate), o en una superclase tienen la firma void metodo (). Es decir, no reciben parámetros. Sin embargo, si el método callback lo definimos en una clase Listener (como AlertMonitor, según la anotación @EntityListeners), la firma de los métodos es void metodo (Object entidad), donde el objeto "entidad" representa a la entidad sobre la que se realiza la operación. Habemus respuesta!!

La cuarta es incorrecta debido a que es posible usar clases Listeners y definir métodos callback en la misma entidad nis haber conflictos. Primero se ejecutaría el método callback de la clase Listener (para este caso AlertMonitor) y después el método callback de la clase Entidad (validateCreate de la clase Account).

Concluyendo... la respuesta es la tercera.

Pregunta tomada de ExamWorx

La pregunta SCBCD del día: Seguridad

(Imagen: Claude Monet -  Mujer en el jardín)

Retomando el blog, después de un prolongado descanso; me propongo a comenzar una seguidilla de preguntas sobre el SCBCD 5 (o sea .. full EJB 3.0), de modo que me mantenga publicando constantemente y de paso me vaya preparando. Ahí va la primera:

**A developer implements a Session Bean with a method doStuff which behaves differently depending on the caller's security role. Only users in security roles "USER" and "ADMIN"  are allowed to call the method. Asume that there is no security related metadata in the deployment descriptor. Which two, taken in combination, are appropiate to acomplish this? (Choose two)

  1. Anotate method doStuff with @PermitAll
  2. Anotate method doStuff with @RolesAllowed ({"ADMIN", "USER"})
  3. If EJBContext.getCallerPrincipal returns "ADMIN", implement the behavior for users in role ADMIN
  4. If EJBContext.isCallerInRole ("ADMIN") returns true, implement the behavior for users in role ADMIN
A ver, la pregunta establece que sólamente deben acceder al método doStuff (wow... que creativos) los usuario en los roles "USER " y "ADMIN", así que usar la anotación @PermitAll sería un poco contraproducente (cualquier usuario autenticado puede acceder al método, como su nombre lo sugiere).

Por el contrario, mediante la anotación @RolesAllowed ({"ADMIN", "USER"}), establecemos que los roles lógicos que pueden acceder al método son "ADMIN" y "USER". Por ende, la segunda opción iría.

Ahora, debemos hacer que el método se comporte de una u otra manera dependiendo del rol del usuario conectado. Para esto, es bastante conveniente el método isCallerInRole("aqui va el rol") , que nos determina si es que el usuario está asociado al rol que le pasamos como parámetro. Entonces, la cuarta opción también sería seleccionada.

Concluyendo, las correctas serían la segunda y la tercera opción.

PS: Para que no queden dudas, el método getCallerPrincipal  nos devuelve un objeto de tipo javax.security.Principal , que nos representa al usuario que está invocando al EJB, por lo que no devolvería "ADMIN", como sugiere la tercera opción. 


Pregunta tomada de ExamWorx