SCBCD: Apuntes tácticos 4


(Imagen: Paul Gauguin - Mujer con flor)

  • En una relación de uno a uno se debe usar la anotación JoinColumn (name, referencedColumnName). Name es el nombre de la columna en la tabla actual y referencedColumnName es el nombre de la llave foránea en la otra tabla. Esta anotación reside en la entidad de la tabla que tiene la llave foránea (llave primaria en la otra tabla)
  • Una relación uno a uno bidireccional utiliza un atributo mappedBy en la anotación OneToOne en la tabla secundaria.
  • En una relación una a muchos y muchos a uno se usa la anotación @JoinColumn en el lado "muchos" de la relación y el atributo mappedBy en el otro lado de la relación para relaciones bidireccionales.
  • Una relación ManyToOne no utiliza el atributo mappedBy debido a que el lado "muchos" siempre es el lado "owning" de la relación
  • En las relaciones muchos a muchos se utiliza una tabla de asociación.
  • Se utiliza la anotación @JoinTable en el lado "owning" de la relación (que puede ser cualquiera)
  • Se utiliza un atributo mappedBy en una relación ManyToMany para una relación bidireccional
  • Para sentencias JPQL, no se puede mezclar parámetros nombrados y posicionales
  • Los inner joins son los joins por defecto
  • Los Left Join (o sea Left Outer Join) obtiene entidades donde los valores pueden ser nulos
  • "_" reemplaza a un carácter y "%" reemplaza a un grupo de caracteres para sentencias LIKE
  • Para subquerys se utilizan las sentencias ALL, ANY, SOME, EXISTS
  • El bean provider es responsable de crear los archivos ejb-jar y de implementar las interfaces de negocio y las interfaces de vista al cliente
  • Aquí van las responsabilidades del application assembler
  • Integra la aplicación con otros componentes
  • Puede modificar los valores de entradas del entorno
  • Puede modificar los nombres de las relaciones para enity beans 2.1
  • Puede definir roles de seguridad, y enlazar referencias a roles de seguridad
  • Puede modificar atributos de transacción
  • Puede modificar el orden de los interceptores, aumentarlos o sobreescribirlos.
  • Aquí van las responsabilidades del deployer
  • Resuelve dependencias externas requeridas por el EJB
  • Usa las herramientas definidas por el proveedor del contenedor
  • Mapea los roles de seguridad definidos por el bean Provider/Application Assembker con roles actuales del entorno operativo.
  • Aquí van las responsabilidades del proveedor del servidor EJB
  • Proveer las herramientas de despliegue necesarias para poner en marcha los EJB's
  • Dar soporte a lso EJB's desplegados en tiempo de ejecución
  • Darle herramientas las administrador del sistema para controlar el comportamiemto en tiempo de ejecución de los beans
  • Las clases de persistencia administradas deben ser incluidas en la raíz de la persistence unit
  • La anotación DeclareRoles y RunAs sólo es aplicable a clases.
  • La anotación DenyAll es aplicada sólamente a métodos.
  • Si un bean implementa más de una interfaz de negocio, entonces necesita especificarlas como @Local o como @Remote
  • Una interfaz de negocio no puede ser a la vez Local y Remote
  • Una interfaz de negocio no puede heredar de javax.ejb.EJBObject o javax.ejb.EJBLocalObject
  • La clase bean puede ser específicada como @Local o @Remote (o las dos con una lista de interfaces)
  • Los métodos de la interfaz de negocio no deben lanzar RemoteException
  • Los métodos interceptores callback pueden tener cualquier visibilidad pero no deben ser fianl ni static
  • Un método callback no puede ser especificado más de una vez en una clase.
  • Los métodos @AroundInvoke deben llamar siempre a InvocationContext.proceed()
  • Los interceptores de métodos de negocio tienen la siguiente firma: public Object method (InvocationContext) throws Exception
  • La interfaz de negocio para un MDB es la interfaz message listener (javax.jms.MessageListener)

    Basado en las notas de Raghavendra Balgi

SCBCD: Apuntes tácticos 3

(Imagen: Paul Gauguin - Retrato de Madame Gauguin)


  • Los MDB's no deben invocar a los métodos isCallerInRole(), getEJBObject(), getEJBLocalObject()
  • Las clases correspondientes a Session Beans deben ser públicas, no finales y no abstractas. Deben poseer un constructor público sin parámetros y no tener el método finalize implementado.
  • Si el session bean sólo implementa una interfaz, dicha interfaz será considerada como interfaz de negocio local.
  • Los timers pueden ser creados desde session beans stateless, MDB's y entity beans 2.1
  • Se puede obtener TimerService por inyección de dependencia (DI) o mediante context.getTimerService
  • TimerService nos provee de los métodos createTimer y getTimers
  • Se puede implementar un método timeour callback con la anotación @Timeout (void method(Timer)) o implementando la interfaz javax.ejb.TimedObject junto a su método public void ejbTimeout (Timer)
  • Al invocar una operación en un Timer expirado, se obtiene NoSuchObjectLocalException
  • Un método timeout puede tener cualquier visibilidad pero no puede ser static ni final
  • Una clase entidad debe estar anotada con @Entity o declarada en el descriptor XML
  • Debe tener un constructor sin parámetros public o protected
  • No debe ser final , y ninguno de sus métodos debe ser final.
  • El estado de las variables debe ser private, protected o package (no public!!!)
  • Se usa la anotación @ExcludeDefaultListeners para excluir los listeners por defecto (duh!)
  • Se usa la anotación @ExcludeSuperclassListeners para evitar la invocación de listener de la clase padre en la misma clase y sus subclases.
  • Una entidad puede sobreescribir los listeners definidos por su clase padre
  • Los métodos listener en la clase Listener tienen la firma void method (Object) y los métodos listener en la misma clase o en la clase padre tienen la firma : void method
  • Orden de invocación de Listeners:
  • Listeners por defecto para la persistence unit
  • Entity Listener del padre
  • Entity Listener de la entidad
  • Listeners definidos en el padre
  • Listeners definidos en la entidad
  • PersistenceContextType puede ser TRANSACTIOPNo EXTENDED. TransactionType puede ser JTA (por defecto para aplicaciones J2EE) o RESOURCE_LOCAL (por defecto en J2SE )
  • Las excepciones NoResultException y NoUniqueResultException no causan rollback en la transacción
  • Las funciones agregadas de JPQL son : AVG, COUNT, MIN, MAX, SUM
  • COUNT devuelve un long
  • MIN/MAX devuelve el tipo al que son aplicadas
  • AVG devuelve double
  • SUM retorna Long, Double, BigInteger o BigDecimal
  • De no encontrar valores COUNT devuelve cero. El resto devuelve NULL


Basado en las notas de Raghavendra Balgi

SCBCD: Apuntes tácticos 2

(Imagen: Paul Gauguin - El espírito de la muerte observa)


  • Un EntityManager está asociado a un contexto de persistencia, dentro del cúal existe un grupo de instancias administradas.
  • El grupo de instancias administradas por un EntityManager está definido por una Persistence Unit
  • El método merge sólamente funciona dentro de una transacción
  • El método find devuelve null si la instancia buscada no existe
  • El método getReference lanza EntityNotFoundException si la instancia buscada no existe
  • El método contains devuelve "true" si la entidad es parte del contexto de persistencia.
  • El método flush requiere de una transacción para funcionar, caso contrario se lanza TransactionRequiredException
  • Existen dos tipos de modo de flush (configurables mediante setFlushModeType): AUTO y COMMIT
  • El método clear termina el contexto de persistencia, y todas las entidades pasan a ser no administradas
  • Los siguientes métodos de EntityManager requieren una transacción: persist, merge, refresh y remove
  • Los métodos callback del ciclo de vida en entidaes pueden ser especificados en la misma clase, una superclase o una clase entity-listener aparte
  • Estos métodos se pueden especificar con las anotaciones @PrePersist, @PostPersist, @PreRemove, @PostRemove, @PreUpdate, @PostUpdate y @PostLoad
  • Los entity listeners por defecto son especificados para todas las entidades de una persistence unit
  • Se puede especificar muchso entity listeners para una clase entidad o una superclase y el orden de invocación es el orden en el que están especificados en la metadata.
  • LOs métodos callback del ciclo de vida tienen la siguiente firma: void methodname() cuando son definidos en clase entidad o en su superclase.
  • Si son definidos en una clase Entity Listener aparte, la firma de los métodos es la siguiente: void methodname(Object), donde Object es el objeto sobre el que se realiza la operación.
  • Para definir entity-listeners para una entidad se usa la anotación @EntityListeners. Dicha anotación toma como input un arrglo.
  • El método getInvokedBusinessInterface sólo es accesible desde métodos de negocio o interceptores de métodos de negocio.
  • Los beans stateless con BMT pueden acceder a getUserTransaction en todos sus métodos, pero no tienen acceso a setRollbackOnly y getRollbackOnly
Basado en las notas de Raghavendra Balgi

SCBCD: Apuntes tácticos I


(Imagen: Paul Gauguin - Cristo amarillo)

Aquí unas notas de emergencia para leer antes de dar el SCBCD. Están basadas en lo publicado por Raghavendra Balgi, cuyas notas he traducido y aumentado. Ah! He omitido las porciones de descriptor de despliegue XML porque es laborioso ponerlas en un post. Con esas consideraciones...prosigo:

  • Los MDB's (message-driven beans) pueden usar como atributos de transacción REQUIRED y NOT_SUPPORTED. Los métodos timeout
  • callback REQUIRED, REQUIRES_NEW, NOT_SUPPORTED, y los session beans REQUIRED, REQUIRES_NEW, MANDATORY
  • Sólamente los session beans y los MDB's pueden usar transacciones administradas por bean (BMT)
  • AL utilizar BMT, no se deben utilizar los métodos setRollbackOnly y getRollbackOnly de EJBContext. En ese caso, se deben usar
  • los métodos getStatus y rollback de userTransaction.
  • Las transacciones están disponibles para métodos de negocio, métodos message listener (ej. onMessage en MDB's), métodos
  • timeout y métodos de interceptores.
  • Si un session bean stateless no le da COMMIT o ROLLBACK a la transacción antes de finalizar el método, el contenedor marcará
  • la transacción para rollback y se lanzará la excepción EJBException al cliente.
  • Atributos de transacción para beans CMT (transacciones manejadas por contenedor)
  • REQUIRED: Se crea una transacción si es que una no existe ya
  • REQUIRES_NEW: Se se crea una nueva transacción (si una ya existe, se suspende)
  • NEVER: Si existe una transacción, te devuelve una EJBException
  • SUPPORTS: Si existe la usa, y si no es así no se molesta en crear una nueva.
  • NOT_SUPPORTED: De existir una transacción, la suspende antes de invocar al método.
  • MANDATORY: De no existir una transacción se lanza EJBTransactionRequiredException
  • Los beans CMT no deberían usar UserTransaction
  • El descriptor de despliegue no puede ser usado poara sobre-escribir el tipo de transacción asociado al bean
  • El atributo de transacción por defecto es REQUIRED, y el tipo de transacción por defecto es CONTAINER
  • Los stateful session beans que son CMT pueden implementar la interfaz SessionSynchronization (afterBegin, beforeCOmpletition y afterCompletition)
  • Las excepciones de aplicación pueden ser especificadas en la interfaz de negocio, métodos message listener o en endpoints de webservice
  • Las excepciones de aplicación deben extender java.lang.Exception o java.lang.RuntimeException pero no de java.rmi.RemoteException
  • Se consideran excepciones de aplicacióna javax.ejb.CreateException, FinderException y RemoveException
  • Una excepción de aplicación es pasada al cliente tal cual
  • Una excepción de aplicación no causa un rollback en la transacción (a menos que sea especificado con el elemento "rollback" de la anotación @ApplicationException)
  • Una excepción de sistema es una excepción que hereda de RemoteException o de RuntimeException, cuando no es definida como excepción de aplicación.
  • Si un session bean con atributo de transacción REQUIRED/MANDATORY/SUPPORTS (con transacción del cliente) lanza una excepción de aplicación, el cliente recibe esta excepción de aplicación.
  • Si un session bean con atributo de transacción REQUIRED/MANDATORY/SUPPORTS (con transacción del cliente) lanza una excepción que no es de aplicación, el cliente recibe EJBTransactionRolledbackException
  • Si un session bean con REQUIRED/REQUIRES_NEW (con transacción del contenedor) lanza una excepción de aplicación, el cliente recibe una excepción de aplicación.
  • Si un session bean con atributo de transacción REQUIRED/REQUIRES_NEW (con transacción del contenedor) lanza una excepción que no es de aplicación, el cliente recibe EJBException, y la instancia es descartada.
  • Si una existe transacción, y se lanza una excepción de aplicación, el cliente recibe una excepción de aplicación.
  • Si no existe transacción, y se lanza una excepción que no es de aplicación, el cliente recibe EJBException, y se descarta la instancia.
  • Un bean puede implementar TimedObject e implementar el método ejbTimeout(Timer) o anotar un método con @Timeout (public void method(Timer)) para especificar un método Timeout Callback
  • Los métodos createTimer de TimerService especifican la duración en milisegundos.
  • Para seguridad programática, se utilizan los métodos getCallerPrincipal() e isCallerInRole(String) de EJBContext

SCBCD del Día: SessionContext.getBusinessObject()

(Imagen: Henri Matisse - Alegría de Vivir)

A developer writes two session beans which cooperate. The first session bean, ShoppingCart, collects orders and is implemented as a stateful session bean. The second session bean, CalculateDiscount, is implemented as a stateless session bean and runs on a different server. ShoppingCart contains the method getTotalPrice, which calculates the total price of the order in the ShoppingCart, including discounts. Discounts are calculated by CalculateDiscounts using the information on the Shopping
Cart bean, combined with data from a database. Which scenario can accomplish this?

  • The CalculateDiscount offers a method calculate which is invoked by the ShoppingCart bean passing the "this" reference
  • The CalculateDiscount offers a method calculate which is invoked by the ShoppingCart bean. CalculateDiscount accesses the ShoppingCart instance by JNDI lookup.
  • The CalculateDiscount offers a method calculate which is invoked by hte ShoppingCart bean passing its reference obtained from the SessionContext.getBusinessObject method
  • The CalculateDiscount offers a method calculate which is invoked by the ShoppingCart bean. CalculateDiscount accesses the state of ShoppingCart by dependency injection.

Para hacer esto más llevadero, comencemos por la respuesta, que es la tercera.

El método SessionContext.getBusinessObject() nos devuelve una referencia al EJB actual que puede ser invocada por otros clientes, como el bean CalculateDiscount de la pregunta. Esta referencia sería el equivalente EJB de la sentencia Java "this". getBusinessObject recibe como parámetro un objeto Class, que debe ser una de las interfaces (remota o local) del bean, de modo que el contenedor sepa si crear una referencia local o remota del EJB actual. El método getBusinessObject permite a la instancia bean obtener su propia referencia EJB, que puede luego pasar a otros beans (como CalculateDiscount ). Aquí un ejemplito:

@Stateless
public class A_bean implements A_BeanRemote{
@Resource
private SessionContext context;
public void someMethod(){
B_BeanRemote b = ... // referencia remote a B_bean
A_BeanRemote mySelf = getBusinessObject(A_BeanRemote.class)
b.aMethod(mySelf);

}
...
}

Es ilegal para una instancia bean pasarle la referencia "this" a otro bean; por el contrario, debe pasarle una referencia local o remota del EJB, que el bean puede obtener de SessionContext.

Pregunta tomada de ExamWorx

Cartas a un joven desarrollador, o crónica de un programador novato




A raíz del blog, ocasionalmente me llegan al mail consultas de gente novicia en programación (estudiantes, en su mayoría), y buscan cierta orientación de este desorientado pero siempre voluntarioso blogger. Así que, dado que me lo solicitan (porque no me creo en posición de aconsejar a nadie), procedo a trancribir un mail que le hice llegar a una de estas personas que requerían cierta guía para iniciarse en la profesión.

-----
Miércoles, 25 de Febrero del 2009

Hola estudianteQueQuiereProgramarEnJava..!

Primero, agradecerte por los comentarios, ya que siempre me reconforta saber que lo que escribo es de utilidad para alguien.

Ahora, el tema de las prácticas y el de iniciarte en la profesión es algo complejo, y algún día pienso dedicarle un post al respecto. Mientras lo hago, déjame contarte un poco mi experiencia:

Cuando andaba mas o menos en séptimo ciclo de la universidad, decidí que era tiempo de dejarme de holgazanerías y ponerme a buscar trabajo. Mi currículum sólamante decía que era estudiante de la UNI, sabía inglés y había llevado cursos de programación en el instituto de la facultad. Logré que me entrevistaran 3 veces, pero en ninguna me llamaron. Ahí viene la primera lección: sólamente haber estudiado no basta.

Después conseguí que me incluyeran en un proyecto de desarrollo dentro de la universidad: era un proyecto bastante pequeño, sólamente éramos estudiantes y no me pagaban ni un sol. Estuve ahí más o menos por 6 meses y fue un período de aprendizaje intenso (estar en la cancha te abre bastante los ojos) . Al final, el proyecto abortó pero yo tenía algo que poner en mi CV. Al cabo de unos meses de eso ingresé al programa de ayudantía en el Centro de Cómputo de la Universidad, donde también me asignaron a proyectos bastante pequeños y con una paga más pequeña aún (en vez de paga yo la llamaría "propina"). Sólo me dedicaba a ponerle ganas, y terminado el proyectito lo agregué presto a mi CV con letras grandes y mayúsculas.

Aún estando en la ayudantía mi amigo Lion me dijo que estaban necesitando practicantes en una compañía de seguros, y que si estaba interesado le podía mandar mi CV. Ahora, ¿cómo es que Lion, estando en un ciclo inferior al mío y sin haber practicado nunca había conseguido trabajo en Rímac Seguros? Pues la respuesta estaba en que Lion era un programador certificado (SCJP: Sun Certified Java Programmer). Segunda lección: Si no tienes experiencia, la mejor manera de hacerte atractivo para el mercado laboral es certificarte.

Le envíe mi CV a Lion , y a los días me llamaron para rendir un exámen técnico. Como ya había tenido cierta experiencia con los proyectos "académicos" (dícese de los proyectos donde no te pagan), y además estaba estudiando para certificarme; el examen lo di sin problemas. Después me tocó una entrevista, en la que hicieron bastante énfasis en los proyectos pequeños en los que estaba. Confieso que exageré un poco, pero logré convencerlos que era el programador que necesitaban. Ingresé a Rímac, logré un sueldo decente (para un estudiante de 8 ciclo) y tenía que comprarme un terno para trabajar. Tercera lección: Los proyectitos universitarios sirven, sólo tienes que saber venderlos bien.

Posteriormente siguió un período de esclavitud de más de un año, pero eso ya es otra historia. Resumiendo, mi consejo es que si quieres hacer una línea de carrera en Java y todavía no tienes experiencia, lo más recomendable es certificarse. No es tan difícil, ya que niños de 12 años lo han hecho. También busca meterte en un proyecto de Java sea como sea: no importa que sea chiquito y que no te paguen; después esas líneas en el CV te van a llevar a un trabajo decente. Y tercero pero no menos importante...estudia!! Que en la mayoría de empresas de desarrollo te van a tomar un examen de conocimientos: tienes que estar preparado para demostrar lo que sabes.

Bueno estudianteQueQuiereProgramarEnJava , disculpa lo extenso y espero que este relato te sirva de algo.

Saludos,

Carlos G. Gavidia

PS: Creo que con lo escrito ya tengo para un post, así que no te sorprendas si ves publicado este mail en la web xD

SCBCD del Día: Entity Inheritance

(Imagen: Henri Matisse - Mujer en saco púpura)

A developer wants to have bookingDate in table BOOKING, flightNUmber in table FLIGHTBOOKING and hotelName in table HOTELBOOKING. Which code, inserted at Line 11 of class Booking is appropiate for this strategy?

10. @Entity
11. //insert code here
12. public class Booking{
13. private Date bookingDate;

15. @Entity
16. public class FlightBooking extends Booking{
17. private String flightNumber;

20. @Entity
21. public class HotelBooking extends Booking {
22. private String hotelName;

  • @Joined
  • @SingleTable
  • @TablePerClass
  • @Inheritance(strategy=JOINED)
  • @Inheritance(strategy=SINGLE_TABLE)
  • @Inheritance(strategy=TABLE_PER_CLASS)

La especificación de persistencia de Java nos brinda tres maneras diferentes de "mapear" una jerarquía de herencia en una base de datos relacional

Una tabla por jerarquía de clases: Una tabla tendrá todas las propiedades de cada clase en la jerarquía

Una tabla por clase concreta: Cada clase tendrá dedicada una tabla, con todas sus propiedades y las propiedades de sus superclases en esta tabla

Y la que nos interesa, una tabla por subclase, donde cada subclase tiene su propia tabla, pero esta tabla contiene sólamente las propiedades definidas para esta clase en particular. Así como está especificado en la pregunta.En otras palabras, es similar a la estrategia anterior (TABLE_PER_CLASS), sólo que normalizada. A esta estrategia también se le llama JOINED. Por ejemplo, para las entidades EMPLOYEE, CUSTOMER y person:

@Entity
@Inheritance (strategy=InheritanceType.JOINED)
public class Person {
...
}

@Entity
public class Customer extends Person {
...
}

@Entity
@PrimaryKeyJoinColumn (name="EMP_PK")
public class Employee extends Customer{
...
}

A estas alturas, ya se habrán dado cuenta que la cuarta es la correcta.

SCBCD del Día: Explicit Transaction Management II

(Imagen: Henri Matisse- Dos muchachas, fondo amarillo y rojo)

Explicit Transaction Management

Using bean-managed transaction demarcation, under which two circunstances must the container roll back a transaction? (Choose two)

  • A stateful session bean invokes UserTransaction.getRollbackOnly
  • A stateful session bean throws an uncaught application exception from a business method
  • A stateful session bean begins a transaction in a business method but does NOT complete it before returning
  • A stateless session bean begins a transaction in a business method but does NOT complete it before returning
  • A message-driven bean begins a transaction in a message listener method but does NOT complete it before returning

Veamos a las opciones una por una, para ver quien miente y quien dice la verdad. El método getRollbackOnly retorna TRUE si la transacción actual ha sido marcada para un rollback. Esta información puede utilizarse para evitar ejecutar código que ya no va a ser "commited" después de todo. Por eso, la primera no va. Además, getRollbackOnly y setRollbackOnly son usados por beans CMT (container-managed transaction), lo que refuerza aún más nuestra afirmación que la primera no va.

Las excepciones de aplicación son lanzadas por lo general en respuesta a un error de lógica de negocio (y no por un error de sistema). Las excepciones de aplicación son lanzadas directamente al cliente sin ser empaquetadas en una excepción EJBException. Por defecto, no causan un rollback en la transacción (aunque esto puede ser modificado) , por lo que la segunda alternativa tampoco es cierta.

Con los stateless session beans, las transacciones administradas mediante UserTransaction (como se trata de un BMT es así) deben ser iniciadas y completadas dentro de un mismo método. De no hacerlo, se lanzaría una excepción que nos llevaría al rollback, por lo que la cuarta es correcta. Sin embargo, con los stateful session beans una transacción puede comenzar en un método y recibir el commit en otro método, debido a que los beans stateful son usados sólamente por un cliente. Entonces, la tercera miente.

Para finalizar, los message driven beans también tienen la opción de administrar sus propias transacciones. En el caso de los MDB's, el alcance de la transacción debe comenzar y terminar en el método onMessage(). Por eso, la quinta también va.

En síntesis, nos quedamos con la cuarta y la quinta opción.

Pregunta tomada de ExamWorx

SCBCD del Día: Explicit Transaction Management

(Imagen: Henri Matisse - Lanzador de cuchillos)

  • Which is the correct way of declaring bean-managed transaction demarcation for an EJB 3.0 message-driven bean?

@MessageDriven
public class MyMessageBean implements MessageListener, UserTransaction {

@MessageDriven
@TransactionManagement (TransactionManagementType.BEAN)
public class MyMessageBean implements MessageListener{

@MessageDriven
public class MyMessageBean implements MessageListener{
@TransactionManagement(TransactionManagementType.BEAN)
public void onMessage(Message message) {...}

@MessageDriven (transactionManagement = TransactionManagementType.BEAN)
public class MyMessageBean implements MessageListener{

Los EJB's pueden también manejar transacciones de manera explícita. Sólamante los session beans y los message-driven beans que definan un javax.ejb.TransactionManagementType como Bean mediante la anotación @javax.ejb.TransactionManagement pueden administrar sus propias transacciones. A los EJB's que administran sus propias transacciones se les llama beans BMT (bean-managed transaction). Los beans entity no pueden ser BMT. Los BMT's no declaran atributos de transacción para sus métodos. Aquí un ejemplito:

@Stateless
@TransactionManagement (TransactionManagerType.BEAN)
public class HypotheticalBean implements HypotheticalLocal{ ... }

Que cómo verán, es similar a la segunda alternativa que es nuestra respuesta.

Para administrar sus propias transacciones , un EJB necesita obtener un objeto UserTransaction. Éste se obtiene mediante EJBContext y inyectándolo con @Resource.

Pregunta tomada de ExamWorx

Otra SCBCD dominical: Web service endpoint interface


(Imagen: Henri Matisse - Desnudo azul)

Which statement describes a component definition that is allowed by the EJB 3.0 specification?

  • A stateful session bean that is a Web Service Endpoint
  • A stateful session bean that has one remote business interface and is a Web Service endpoint
  • A message-driven bean that has one message listener interface and is a Web Service Endpoint
  • A stateless session bean that has three local business interfaces and is a Web Service Endpoint

La interfaz web Service Endpoint es específica y exclusiva de los session beans stateless, por lo tanto la respuesta es la cuarta.

Fin del post.

Jajaja! Mejor ahondamos un poquito en el asunto, que ser tan breve tampoco es mi estilo. Una de las características más potentes de EJB 3.0 es exponer los session beans stateless como webservices basados en SOAP. Lo único que se debe hacer para hacer a un bean accesible por SOAP es marcar una interfaz de negocio con la anotación @javax.jws.WebService. Por ejemplo:

@webService
public interface BidManagerWS {
void addBid(Bid bid);
List getBids(Iten item);
}

Sólamente los métodos contenidos en esta interface serán expuestos como web services. La anotación @WebService no impone restricciones especiales ni a la interface ni al bean que la implementa.



Pregunta tomada de ExamWorx

SCBCD Dominical: Transaction Attributes

(Imagen: Henri Matisse - Marinero Joven)

Given the following stateful session bean

@Stateful
public class VideoBean implements Video{
public void methodA(){}

@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public void methodB(){}

public void methodC(){}

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void methodD(){}

}

Assuming no other transaction-related metadata, which is true?

  • methodB and methodC have transaction attribute SUPPORTS while methodD has transaction attribute REQUIRED
  • methodA and methodC have transaction attribute REQUIRES_NEW, while methodB has transaction attribute SUPPORTS
  • methodC, methodD and methodA have transaction attribute REQUIRED, and methodB has transaction attribute SUPPORTS
  • methodB has transaction attribute SUPPORTS , methodD has transaction attribute REQUIRED, and methodA and methodC have transaction attribute REQUIRES_NEW


Al utilizar un servidor EJB, no es necesario el control explícito de transacciones. Los servidores EJB manejan las transacciones implícitamente, basados en los atributos de transacción establecidos en tiempo de despliegue. Para esto utilizamos la anotación @javax.ejb.TransactionAttribute.

Se puede configurar un atributo de transacción para todo el EJB (o sea, para todos sus métodos) o se puede  colocar atributos de transacción diferentes para cada método individualmente. 

Ahora, si no se define @transactionAttribute ni se utiliza el descriptor de despliegue, el atributo de transacción por defecto es REQUIRED; por lo que methodA y methodC en nuestra pregunta tendrán dicho atributo de transacción.methodB tiene asignado SUPPORTS usando la anotación, y methodD es REQUIRED por el mismo medio, por lo que nuestra respuesta sería la tercera.

Ahora, sólo para recordar, el atributo REQUIRED establece que si el cliente que lo invoca es parte de una transacción, el EJB se incluye en el alcance de dicha transacción. Caso contrario, el EJB inicia su propia transacción (por eso el REQUIRED). Para el caso de SUPPORTS, si el cliente es parte de una transacción el EJB se unirá a dicha transacción (como REQUIRED), pero si no es así el EJB continuará su ejecución sin un contexto transaccional.Y para terminar, REQUIRES_NEW significa que siempre se inicia una nueva transacción, sin importar que el cliente ya sea parte de una transacción



Pregunta tomada de ExamWorx

Pregunta SCBCD: EntityManagerFactory

(Imagen: Henri Matisse - Desnudo Azul II)

Within a Java EE environment, which annotation can be used to inject an entity manager factory?

  • @Entity
  • @Factory
  • @JTAFActory
  • @PersistenceUnit
  • @PersistenceContext

Los EntityManagers pueden ser creados u obtenidos desde un EntityManagerFactory. En aplicaciones Java SE, es necesario crear instancias de EntityManager desde EntityManagerFactory, pero en aplicaciones Java EE esto no es obligatorio.

EntityManagerFactory posee el método createEntityManager, que nos devuelve instancias de EntityManager que administran contextos de persistencia extendidos. Una vez que se termina de utilizar el EntityManagerFactory, se debe invocar a close() (a menos que sea inyectado). Con el método isOpen() verificamos si una referencia a EntityManagerFactory es válida.

Ahora que sabemos lo que es un EntityManagerFactory, veamos como obtenerlo. En aplicaciones Java EE se puede inyectar directamente en un campo o método setter mediante la anotación @javax.persistence.PersistenceUnit.

A diferencia de lo que ocurre en aplicaciones Java SE, un EntityManagerFactory inyectado es cerrado automáticamente por el contenedor EJB al descartar la instancia. En efecto, si se invoca a close() desde un EntityManagerFactory inyectado se lanza la excepción IllegalStateException.

Entonces, la respuesta es la cuarta.

Pregunta tomada de ExamWorx

SCBCD del día: EJB QL

(Imagen: Henri Matisse - Las penas del rey)

A User entity is in a one-to-many relationship with a Book entity. Assume that a developer has a function fetchBook(String title) that fetches a Book entity with the given title. Also assume that the developer has an entity manager em. Which query can be used to return the user that holds the book titled "Java"

  • em.createQuery("SELECT u from User where :great IN u.books.title").setParameter("great", "Java")
  • em.createQuery("Select u from User u where :great IN u.books").setParameter("great", fetchBook("Java"))
  • em.createQuery("SELECT u From User u where :great MEMBER OF u.books.title").setParameter("great", "Java")
  • em.createQuery("Select u from User u where :great MEMEBER OF u.books").setParameter("great", fetchBook("Java"))

Un poco de EJB QL, para no olvidarlo en el examen. Muchas relaciones entre beans entidad se basan en colecciones, como la de la pregunta, y acceder a los beans de estas relaciones es importante. Ahora, es ilegal seleccionar elementos directamente de una relación basada en colecciones. Para evitarnos este problemita, se hace necesario el operador IN, que nos permite asignarle un identificador a un campo colección de una relación.

Pero mucho blabla, así que mejor veámolos con un ejemplo. EL siguiente query usa el operador IN para seleccionar elementos de una relación basada en colecciones. Devuelve todas las reservas de todos los clientes:

SELECT R FROM CUSTOMERS AS C, IN (C.RESERVATIONS) R

El operador IN asigna a los elementos individuales del atributo reservations el identificador R. Una vez con este identificador, podemos referenciarlos directamente e incluso referenciarlos en la sentencia EJB QL.

Se darán cuenta, que en la primera y segunda opción no hacen un uso adecuado del operador.

Por otro lado, el operador MEMBER OF es una herramienta poderosa para determianr cuando una entidad pertenece a una relación basada en colecciones específica. Por ejemplo, el siguiente query determina si una entidad Customer (como parámetro de entrada) es miembro de cualquiera de las relaciones entre Reservation y Customer.

SELECT CRS 
FROM CRUISE AS CRS, IN (CRS.RESERVATIONS) AS RES, CUSTOMER AS CUST
WHERE CUST =: MYCUSTOMER
AND
CUST MEMBER OF RES.CUSTOMERS

Se observa que este operador se presta más para la pregunta que IN. Seleccionamos la cuarta, dado que MEMBER OF se aplica sobre colecciones como u.books.







Pregunta tomada de ExamWorx

SCBCD después de mucho!: Primary-Key Classes and Composite Keys

(Henri Matisse - Pintor y Modelo)

The Java Persistenece entity LineItem defines a composite primary key that is defined by the two columns ORDERID and LINEITEM in the database. Which two are true? (Choose two)

  • LineItem must define a primary key class to represent the composite primary key
  • The composite primary key is mapped as two fields in LineItem. No extra primary key class is necesary.
  • The combination os @Embedded and @Embeddable annotations can be used to denote the composite primery key
  • The semantics of the equals and hashCode methods of the primary key must be consistent with the database equality.

Para ciertos mapeos relacionales se requiere que la llave primaria esté compuesta por varias propiedades persistentes, como ilustra la pregunta. Este tipo de llave primaria, como deben de haber visto en su cursillo de base de datos, se llaman claves compuestas. La especificación nos ofrece dos maneras de mapear este tipo de modelos: con la anotación @IdClass o con la anotación @EmbeddedId.

Usando @IdClass, la clase entidad no usa la clase de llave primaria internamente, pero si la utiliza para interactuar con el entity manager. Usamos @IdClass a nivel de clase para especificar la clase de llave primaria a usar. La clase  de llave primaria debe cumplir lo siguiente:

  • Debe ser serializable
  • Debe poseer un constructor sin argumentos
  • Debe implementar equals y hashcode

En el bean, en nuestro caso LineItem,  debemos tener las mismas propiedades que la clase de llave primaria, y estas propiedades deben estar anotadas con @Id.

Otra forma de definir la clase de llave primaria y claves compuestas es incluir la clase de llave primaria directamente en la clase del bean. Para este fin usamos las anotaciones @EmbeddedId y @Embedabble.

Por lo expuesto, la primera y la cuarta opción son correctas.




Pregunta tomada de ExamWorx

Más SCBCD : Algunos métodos de EntityManager


(Henri Matisse - Taller Rojo)

A developer has obtained a container-managed entity manager in a stateless session bean. Which to statements are correct? (Choose two)

  • Invoking the flush method without a transaction will throw an exception
  • Invoking the clear method without a transaction will throw an exception
  • Invoking the persist method without a transaction will throw an exception
  • Invoking the find method for an entity that does not exist will throw an exception

Siempre es bueno darle una mirada más a los métodos de EntityManager. El método flush escribe los cambios realizados en la transacción actual en la base de datos. De ocurrir excepciones durante flush la transacción es marcada para rollback. Este método requiere de una transacción activa , de no encontrarla, se lanza la excepción TransactionRequiredException.

El método clear() limpia el EntityManager y finaliza el contexto de persistencia. Todas las entidades administradas pasan al estado DETACHED (no administradas pues).

El método persist se utiliza para pasar instancias nuevas al esto administradas (MANAGED). En el siguiente FLUSH o COMMIT, las nuevas instancias serán insertadas en base de datos. El método persist() lanza la excepción IllegalArgumentException si la instancia a persistir no es del tipo entidad. Se lanza TransactionRequiredException si el método no es invocado desde una transacción. Sin embargo, si el entity manager corresponde a un contexto de persistencia extendido, es legal invocar persist() fuera de una transacción, y el insert se mantiene en espera hasta que el contexto de persistencia interactúe con una transacción.

Y para terminar, el método find devuelve una instancia para un tipo y una identidad proporcionadas como parámetro. Si la instancia se encuentra en el contexto de persistencia actual, se devuelve la versión en caché. Caso contrario, se construye una nueva entidad y se carga con la data presente en base de datos. Si no se encuentra una entidad con el tipo y la identidad solicitadas, este método retorna null.

Haciendo un llamado a su capacidad de comprensión de lectura, concluimos que la primera y la tercera alternativa son correctas.

Pregunta tomada de ExamWorx

Primera SCBCD del día: Requirements on the Entity Class

(Imagen: Henri Matisse - Mujer leyendo)

A developer is declaring a persistent entity that will be passed as a detached object through a remote interface to an application client. Which two characteristics must the corresponding persistent entity class have? (Choose two)

  • implement serializable
  • include a no-arg constructor
  • make instance variables public
  • implement the remote interface

Momento de enumerar los requisitos de una clase ENTIDAD

Debe poseer un constructor sin argumentos, que debe ser public o protected

Debe ser una clase, no un enum ni una interfaz, y no debe ser FINAL. Ningún método ni variable de instancia debe ser final.

Si una instancia es pasada por valor como un objeto DETACHED (a través de una interfaz remota, por ejemplo), la clase debe implementar la interfaz Serializable.

Tanto las clases concretas como las abstractas pueden ser entidades. Las entidades pueden heredar de clases no-entidad así como de clases entidad; y las clases no-entidad pueden heredar de clases entidad.

El estado de una entidad está representado por sus variables de instancia, que se corresponden con propiedades JavaBean. El estado de una entidad se hace disponible a los clientes sólamente a través de los métodos de acceso de la entidad (getters/setters) u otros métodos de negocio. Las variables de instancia deben ser private, protected o de visibilidad de paquete.

Por ende, las correctas son la primera y la segunda.

Pregunta tomada de ExamWorx

Otra SCBCD - Bean-Managed Transactions

(Imagen: Henri Matisse - Bestias del mar)

Which two are restrictions of beans with bean-managed transactions?
(Choose two)

  • The NOT_SUPPORTED transaction attribute must be chosen
  • Clients calling with a transactional context are prohibited and will result in an exception
  • A stareful session bean must commit a started transaction before a business method returns.
  • A bean that starts a transaction must complete the transaction before it starts a new transaction
  • A message-driven bean instance must commit a transaction before the onMessage method returns.

Un EJB que utiliza BMT (bean-managed transaction) debe ser un session bean o un message-driven bean.

La instancia que inicia la transacción debe completar la transacción antes que comience una nueva, así que la cuarta alternativa es cierta.

Un stateful session bean puede, pero no es obligatorio, dar commit a la transacción iniciada antes de que el método de negocio finalice, por lo que la tercera no va. Si una transacción no ha sido completada al terminar el método de negocio, el contenedor mantiene la asociación entre la transacción y la instancia a través de múltiples invocaciones del cliente hasta que se complete la transacción.

En el caso de los session bean stateless se debe dar COMMIT a la transacción antes del final del método de negocio o del método timeout callback. Esto no tiene que ver con la pregunta, pero es bueno saberlo.

Y para finalizar, un message-driven bean debe dar COMMIT a la transacción antes de la finalización del método message listener (como onMessage) o del método timeout callback, por lo que la última va; y nos quedamos con la cuarta y con la quinta.

Pregunta tomada de ExamWorx

Primera SCBCD del día: Extended Persistence Context

(Imagen: Henri Matisse - Cortina Amarilla)

Which component can use a conteainer-manager entity manager with an extended persistence context?

  • any EJB component
  • only stateful session beans
  • only stateless session beans
  • session beans and web components

Los contextos de persistencia extendidos poseen un comportamiento transaccional especial. En ellos, uno puede invocar operaciones del EntityManager como persist(), merge() y remove() sin estar en una transacción. Estos inserts, updates y deletes son puestos en espera hasta que el contexto de persistencia extendido se encuentre en una transacción activa y esta sea confirmada (commited). En otras palabras, la base de datos no es tocada hasta que el contexto de persistencia pertenezca a una transacción. También, los queries ejecutados no mantienen su conexión a base de datos después de completados.

Un contexto de persistencia manejado por el contenedor (como el de la pregunta) sólo puede ser iniciado por un stateful session bean (entonces, la segunda es nuestra respuesta). Dicho contexto existe desde el momento en el que se crea un stateful session bean que declara una dependencia en un Entity Manager del tipo PersistenceContextType.EXTENDED. Dicho contexto de persistencia es cerrado por el contenedor cuando se ejecuta el método @Remove del Stateful session bean, o cuando dicha instancia es eliminada.

Un EntityManager que usa un contexto de persistencia extendido mantiene el mismo contexto de persistencia por todo su ciclo de vida. Sin importar que esté en una transacción o no, todas las entidades devueltas por el EntityManager son administradas (managed).


Pregunta tomada de ExamWorx

La primera SCBCD del día: Entity Lifecycle Management

(Henri Matisse - Autorretrato con polo a rayas)

Which statement about an entity instance lifecycle is correct?

  • A new entity instance is an instance with a fully populated state
  • A detached entity instance is an instance with no persistent identity
  • A removed entity instance is NOT associated with a persistence context
  • A managed entity instance is the instance associated with a persistence context

Hora de revisar el ciclo de vida de una entidad. Una entidad "nueva" (new) no posee identidad de persistencia y aún no está asociada a un contexto de persistencia. Después de invocar a persist(), pasa al estado "administrada" (managed), donde ya está asociada a un contexto de persistencia.

Si invocamos remove () en una entidad administrada pasa a ser "removida" (removed). Una entidad removida posee identidad de persistencia, está asociada a un contexto de persistencia, y está marcada para ser removida de base de datos.

Una entidad no administrada (detached) posee identidad de persistencia pero ya no está asociada al contexto de persistencia. Una entidad pasa a ser no administrada después de un commit/rollback, si la entidad es pasada por valor, o si el EntityManager es cerrado. Si invocamos merge en una entidad no administrada, pasa a estar administrada.

Entonces, la cuarta dice la verdad.

Pregunta tomada de ExamWorx

Y otra SCBCD: Query.executeUpdate()

(Imagen: Henri Matisse - La conversación)

The Java Persistence API defines the Query interface. Which two statements about the Query.executeUpdate method are true? (Choose two)

  • It must always be executed within a transaction
  • It throws a PersistenceException if no entities were updated
  • It throws an IllegalStateException if called on a Query instance created with a Java Persistence SELECT query
  • All managed entity objects corresponding to database rows affected by the update will have their state changed to correspond with the update

El método executeUpdate de la interfaz Query ejecuta una sentencia update o delete. Retorna el número de entidades actualizadas o eliminadas y lanza la excepción IllegalStateException si es invocado para una sentencia SELECT. En caso no se ejecute dentro de una transacción, se lanza TransactionRequiredException.


Entonces, las alternativas correctas son la primera y la tercera.

Pregunta tomada de ExamWorx

Otra SCBCD - UserTransaction y Contenedor EJB

(Imagen: Henri Matisse - Retrato de Madame Matisse)

FooBean is an EJB 3.0 session bean that can make valid use of UserTransaction. Which is guaranteed to work ina n EJB Container for FooBeaan to obtain the userTransaction object?

  • Invoke a method on a SessionCOntext that returns a UserTransaction object
  • Perform JNDI lookup with name "java:/UserTransaction" on an InitialContext
  • Perform JNDI lookup with the name "jdbc/UserTransaction" on an InitialContext
  • Use the @TransactionManagement annotation to inject an instance variable of type UserTransaction in a bean class.

Un contenedor EJB debe incluir JTA 1.1, y debe proveer la interfaz javax.transaction.UserTransaction a los EJB's que utilicen BMT (bean-managed transaction) a través de la interfaz javax.ejb.EJBContext (recordar que SessionContext hereda- es subclase - de EJBContext) y por medio de JNDI bajo el nombre de java:comp/UserTransaction (que no fihura en ninguna de las opciones).

Respuesta corta y precisa que nos lleva a escoger la primera alternativa

Pregunta tomada de ExamWorx

SCBCD del Día: Message Driven Beans

(Imagen: Henri Matisse - Ventana Abierta)

A developer wants to create a JMS message-driven bean that responds to javax.jms.TextMessage messages. Which two statements are true? (Choose two)

  • The developer must implement ejbCreate method
  • The developer does NOT need to create a business inferface for the bean.
  • The developer must implement a method that declares javax.jms.TextMessage as an argument
  • The message-driven bean class must implement methods of the javax.jms.MessageListener interface
  • The message-driven class must implement methods of the javax.ejb.MessageDrivenBean interface.

Un MDB (message driven bean) es un EJB completo, como un bean entity o de sesión, pero guarda ciertas diferencias importantes. Un MDB posee una clase, pero no requiere una interfaz local ni remota. Estas interfaces no son necesarias dado que un MDB sólo responde a mensajes asíncronos. Por eso, nos quedamos con la segunda.

La clase de un MDB debe implementar directa o inderectamente la interfaz message listener requerida para el tipo de mensajes que soporta. Para el caso de JMS,como en la pregunta, esta interfaz es javax.jms.MessageListener. Entonces, la cuarta también va y ya tenemos nuestra respuesta: la segunda y la cuarta.

Pero dado que nuestro interés es académico y de aprendizaje (sí..claro), procederemos a revisar el resto de alternativas. La clase del MDB puede, de ser necesario pero no es imperativo, realizar lo siguiente:

  • Implementar la interfaz javax.ejb.MessaegeDrivenBean
  • Implementar la interfaz TimedObject
  • Implementar el método ejbCreate

Por eso mismo, la primera y quinta alternativa son incorrectas. Para finalizar, la tercera es incorrecta dado que la intefaz MessageListener define el método onMessage(), que toma como parámetro una instancia de Message y no de TextMessage . Dentro del método , ya es posible castear Message a TextMessage y otros tipos de mensaje definidos en JMS.

Pregunta tomada de ExamWorx