Transacciones en Java - JTA - Java Transaction API

Una transacción es una operación en la que se realizan una serie de operaciones de forma completa, o no se realiza ninguna.
Por ejemplo, si tenemos que hacer una transferencia de una cuenta a otra en un banco, las dos operaciones forman un conjunto. No sería lógico que quitásemos efectivo de una cuenta y, por alguna razón, no pudiéramos ingresar el dinero en la cuenta de destino, o se realizan las dos operaciones o ninguna.
Una vez iniciada una transacción, ningún cambio queda reflejado hasta que no se confirmen las operaciones ("commit"), o se anulen las mismas ("rollback").
El API de Java para manipular transacciones se conoce como JTA (Java Transaction Api).

Existen tres conceptos de transacciones que son importantes para el desarrollo de aplicaciones Java EE.
  • Atomicidad. Las operaciones son un conjunto completo, o todas se realizan bien o si falla alguna, fallan todas a la vez.
  • Locking and Isolation. Dicho término implica que solamente una transacción puede actualizar un dato al mismo tiempo.
  • Modelo. Cuantas transacciones pueden estar activas en un mismo thread (hilo) en particular en un momento dato.
Existen varios modelos de transacciones:
  • Anidado (Nested). Una transacción consta de varias sus transacciones que corren en paralelo todas juntas.
  • Encadenado (Chained). Una transacción consta de varias subtransacciones que corren en secuencia.
  • Plano (Flat): Una transacción no puede contener subtransacciones. La plataforma Java EE solamente soporta el modelo plano.
El servicio de transacciones distribuidas de la Plataforma J2EE involucra cinco participantes diferentes:
  • Transaction Manager (TM): Es el encargado de proveer los servicios para demarcación de transacciones, manejo de recursos transaccionales, sincronización y propagación de contexto transaccional.
  • Application Server: Implementa los servicios necesarios para proveer un entorno de ejecución para las aplicaciones. Entre estos servicios está el manejo del estado transaccional.
  • Resource Manager (RM): Ofrece a las aplicaciones acceso a recursos. Este acceso se ofrece a través de Resource Adapters. Este participa de transacciones implementado una interfaz para el manejo de recursos transaccionales, que controla la asociación a una transacción, la finalización de una transacción y la recuperación de una transacción.
  • Aplicación basada en componentes transaccionales: Esta aplicación se ejecuta sobre un servidor de aplicaciones, el cual le ofrece, entre otros servicios, control de transacciones, como por ejemplo, una aplicación basada en Enterprise Java Bean.
  • Communication Resource Manager: Encargado de la propagación del contexto transaccional permitiendo acceder a recursos transaccionales ubicados en otros dominios.
Existen dos formas de representar las transacciones sobre las cuales el sistema está sujeto:
  • Mediante programación. Existe un bean que controla la transacción. Esta forma se llama Bean-Managed Transaction (BMT).
  • De forma declarativa. El desarrollador solamente debe establecer de forma declarativa como quiere que el contenedor maneje las transacciones. Esta forma lleva el nombre de Container-Managed Transactions (CMT).
En la primera especificación de EJB se propusieron dos modelos de componentes, conocidos como Entity Bean y Session Bean. La especificación 2.0 introduce un nuevo modelo de componente llamado Message Driven Bean.  

Atributos de Transacciones

Los atributos de las transacciones se especifican mediante anotaciones u opcionalmente, en un deployment descriptor. Las anotaciones de los atributos son las siguientes:
Required  @TransactionAttribute(REQUIRED) Si un cliente está corriendo dentro una transacción e
invoca un método de un bean, el método se ejecuta dentro de la
misma transacción. 
RequiresNew  @TransactionAttribute(REQUIRES_NEW) 
Si un cliente está corriendo dentro de una transacción e invoca un
método, la transacción del cliente se suspende, se inicia una
nueva, la cual se termina al finalizar el método y se reinicia la
transacción del cliente.  
Mandatory  @TransactionAttribute(MANDATORY) Mandatory  @TransactionAttribute(MANDATORY) 
Si el cliente está corriendo dentro una transacción e invoca un método
de un bean, el método se ejecuta dentro de la misma transacción. 
NotSupported  @TransactionAttribute(NOT_SUPPORTED).
Si el cliente está corriendo dentro de una transacción e invoca un método, la transacción del cliente se suspende, cuando termina el método, la transacción del cliente se reanuda.
Si el cliente no está asociado a una transacción, el contenedor no inicia una nueva.
Supports  @TransactionAttribute(SUPPORTS) 
Si el cliente está corriendo dentro una transacción e invoca un método de un bean, el método se ejecuta dentro de la misma transacción.
Si el cliente no está asociado con una transacción, el contenedor no inicia una nueva.
Never  @TransactionAttribute(NEVER) 
 
Ejemplo de código de una transacción:
 
@TransactionAttribute(NOT_SUPPORTED)
@Stateful
public class BeanTransacciones implements Transaction {
...
@TransactionAttribute(REQUIRES_NEW) @TransactionAttribute(REQUIRES_NEW)
public void PrimerMetodo() {...}
@TransactionAttribute(REQUIRED)
public void SegundoMetodo() {...}
public void TercerMetodo() {...}
public void CuartoMetodo() {...}
}
 
Para delimitar las transacciones JTA, se utilizan los siguientes métodos de la interfaz javax.transaction.UserTransaction:
  • begin
  • commit
  • rollback
Ejemplo:
import java.util.*;
import javax.ejb.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import javax.transaction.*; 
@Stateless
@TransactionManagement(BEAN)
public class BeanStock implements Stock {
@Resource javax.Transaction.UserTransaction mitransaccion;
@Resource javax.sql.DataSource ds1;
public void updateStock(int idstock, double precio) {
Connection con = null;
PreparedStatement prepStmt = null;
try {
con = ds1.getConnection();
mitransaccion.begin();
prepStmt = con.prepareStatement(
"UPDATE Stock set precio = ? where IdStock = ?"); 
prepStmt.setDouble(1, precio);
prepStmt.setInt(2, idstock);
int registrosafectados = prepStmt.executeUpdate();
mitransaccion.commit();
} catch (Exception ex) {
try {
mitransaccion.rollback();
} catch (SystemException ex) {
throw new EJBException ("Rollback ha fallado: " + ex.getMessage();
}
throw new EJBException("La transaccion ha fallado: " + ex.getMessage());
} finally {
try {
prepStmt.close();
con.close();
} catch (SQLException ex) {
throw new EJBException ("Error al cerrar la conexion: " + e.getMessage()); 
}
}
}

Lenguaje JPQL

JPQL es un lenguaje que permite realizar consultas como operaciones masivas sobre Entity Beans. Presenta una sintaxis similar a SQL, pero no está orientado a un modelo relacional (basado en tablas y columnas) sino a un modelo de objetos (objetos y atributos).
Las Entidades son sensibles a mayúsculas y minúsculas en los nombres de la Entidad y los campos.

Ejemplo de una Entidad Empleado.
Si queremos recuperar todos los datos de un empleado:
 
SELECT e FROM Empleado e
 
La cláusula from no se refiere a una tabla, sino a una clase, en nuestro ejemplo, la clase Empleado.
El resultado de la consulta es un Entity Bean.
Para ejecutar esta consulta:
 
Query consulta = entityManager.createQuery("SELECT e FROM Empleado e");
List<Empleado> empleados= consulta.getListResult();
 
También se utilizan las anotaciones @NamedQuery y @NamedQueries. Para definir una única consulta en la clase de un Entity Bean:
 
@Entity
@Table(name = "EMPLEADOS")
@NamedQuery(name="todosempleados", query="SELECT e FROM Empleado e")
public class Empleado {
 //Métodos y elementos de la clase Empleado
}
 
Para definir más de una consulta dentro de un entity Bean se utiliza la anotación @NamedQueries que contiene un conjunto de consultas.
 
@Entity
@Table(name = "Empleado")
@NamedQueries(value={
 @NamedQuery(name=" todosempleados", query="SELECT e FROM Empleado e")
, @NamedQuery(name=" todosempleadosorden", query="SELECT e FROM Empleado e ORDER BY e.Nombre")}
)
public class Empleado {
//Métodos y elementos de la clase Empleado
}
 
Para ejecutarlas:
 
Query consulta = entityManager.createNamedQuery("todosempleados");
List<Empleado> empleados = consulta.getResultList();
 
Para utilizar parámetros posicionales, el parámetro debe indicarse en la cláusula where de la consulta con el prefijo ?, y a continuación el número posicional del parámetro.
 
SELECT e FROM Empleado e WHERE e.Nombre = ?1
 
Luego, al ejecutarla, se establece el valor del parámetro según su posición:
 
Query consulta = entityManager.createQuery("SELECT e FROM Empleado e WHERE e.Nombre = ?1");
consulta.setParameter(1, "SHUM");
Empleado emp = consulta.getSingleResult();
 
Para utilizar parámetros por nombre, el parámetro debe indicarse en la cláusula where de la consulta con el prefijo: y a continuación el nombre del parámetro:
 
SELECT e FROM Empleado e WHERE e.Nombre = :nombreempleado
 
Posteriormente, al ejecutarla, se establece el valor del parámetro según su nombre:
 
Query consulta = entityManager.createQuery("SELECT e FROM Empleado e WHERE e.Nombre = :nombreempleado");
consulta.setParameter("nombreempleado", "SHUM");
Empleado emp = consulta.getSingleResult();
 

Persistence en Java 2 - Anotaciones POJOs - Java Persistence API

Una entidad JPA (Java Persistence API)  no es más que un POJO que dispone de una serie de anotaciones, que indican qué y cómo se persiste un objeto, es decir, anotaciones para manipular objetos en una base de datos. Estas anotaciones vinculan cada propiedad del POJO con las de la base de datos y establecen un vínculo directo. 

Resumen de Anotaciones principales:

@Entity indica que el objeto es una entidad.
@Table indica la tabla de base de datos que contiene objetos.
@Id, @IdClass, @EmbeddedId se emplean para declarar claves primarias de clases
@Transient hace que una variable no sea tomada por una base de datos.
@Column indica la columna de una @Table
@Basic indica cuando y como se debe cargar un objeto persistido
@OneToOne es usada para crear relaciones entre otras entidades que tengamos de una a una
@OneToMany hace referencia a la asociación de 1-N.
@ManyToMany hace referencia a la asociación N-N.


Anotación @Entity indica que el objeto es una entidad.
La anotación @Table indica la tabla de base de datos que contiene objetos.
Ejemplo de código:

 
@Entity 
@Table(name="PRODUCTOS") 
public class Producto { 
     @Id 
    private String nombreproducto;  
    public Producto() { } 
     //METODOS Getters y Setters  
}
 
Toda entidad debe tener una clave primaria que se debe identificar con la anotación @Id. Además, todas las entidades deben contener un constructor vacío.

Anotaciones @Id, @IdClass, @EmbeddedId se emplean para declarar claves primarias de clases, bien de forma simple @Id o compuesta @IdClass y @EmbeddedId.
En el caso de las claves compuestas se debe definir una clase para representar a la clave primaria, y redefinir el método equals para comprobar que dos instancias de una clase sean iguales.
Veamos un código utilizando @IdClass

 
@Entity 
@IdClass(PersonaId.class) 
public class Persona { 
    @Id 
    private int id; 
    @Id 
    private String nombre;  
    ... 
    public Persona() { } 
    //METODOS Getters y Setters  
} 
 
public class PersonaId { 
     int id; 
    String nombre; 
     public boolean equals(Object o) { 
        // Codigo que comprueba si las dos entidades son iguales 
    } 
}
 
Y ahora un código utilizando @EmbeddedId

 
@Entity 
public class Persona { 
  @EmbeddedId 
  @AttributeOverrides({ 
     @AttributeOverride(name = "id", column = @Column(name = "ID",  
                              nullable = false, precision = 5, scale = 0)), 
    @AttributeOverride(name = "nombre", column = @Column(name = "NOMBRE"
                       nullable = false, length = 50)), 
 }) 
    private PersonaId id; 
    public Persona() { } 
    //Métodos Getters y Setters  
} 

@Embedded 
public class PersonaId { 
     int id; 
    String nombre; 
     public PersonaId() { } 
     public boolean equals(Object o) { 
        // Codigo que comprueba si las dos entidades son iguales 
    } 
} 
 

La anotación @Transient hace que una variable no sea tomada como un campo del origen de la base de datos.
Además tenemos diferentes formas de mapear cada campo indicando nombres de columna y otros valores.

 
@Entity 
@Table(name="PRODUCTOS") 
public class Productos { 
    @Id 
    private String nombreproducto;  
    @Column(name="CATEGORIA", nullable=false) 
    private String categoria; 
    @Column(name="DESCRIPCION", nullable=false) 
    private String descripcion; 
    @Lob 
    @Basic(fetch=FetchType.LAZY) 
    private byte[] imagen; 
    public Productos() { } 
    //Métodos Getters y Setters  
} 
 
La anotación @Column permite definir varias propiedades:
La propiedad name puede especificar el nombre de la columna
La propiedad nullable indica si la columna acepta valores null o no, si no se incluye el valor por defecto es true.
La anotación @Basic sirve para marcar cualquiera de los tipos de datos que son persistidos de forma automática además de las clases que sean Serializables.
La propiedad fetch permite definir cuándo se debe cargar el campo en cuestión.
FetchType.LAZY indica que el campo se va a cargar de forma "perezosa", es decir, el campo se cargará sólo cuando se acceda a su información, esto supone una consulta más para la obtención del campo, pero en casos de gran cantidad de información es muy beneficioso.
El valor FetchType.EAGER indica que el valor será cargado cuando se cargue el resto del objeto.
El valor por defecto de la propiedad fetch es FetchType.EAGER.
La anotación @Lob indica que el contenido de un campo básico será guardado como LOB (Large Object), por ejemplo, utilizamos esta anotación para marcar un campo que contenga un String o caracteres, el framework lo mapeará a una columna CLOB (Character Large Object).
Si es de otro tipo, normalmente byte[], será mapeado a una columna de tipo BLOB (Binary Large Object).
Anotación @Embeddable forman parte del objeto entidad al que pertenecen.

 
@Entity 
@Table(name="PERSONAS") 
public class Persona { 
    @Id 
    private String nombre;  
    @Embedded 
    @AttributeOverrides({@AttributeOverride(name="codigoPostal",  
                                            column=@Column(name="CODIGOPOSTAL")), 
                         @AttributeOverride(name="direccionPostal",  
                                            column=@Column(name="DIRECCIONPOSTAL")) 
    }) 
    private Direccion direccion; 
    public Persona() { } 
    //Métodos Getters y Setters  
} 

@Embeddable  
public class Direccion implements Serializable {  
    private String direccionPostal; 
    private String ciudad; 
    private int codigoPostal; 
    private String pais; 
    public Direccion() { } 
    public boolean equals(Object o) { 
        // Codigo que comprueba si las dos entidades son iguales 
    }   
}
 
Anotación @OneToOne es usada para crear relaciones entre otras entidades que tengamos declaradas:

 
@Entity 
@Table(name="PRODUCTOS") 
public class Producto { 
    @Id 
    private String nombreproducto;  
    @Column(name="DESCRIPCION", nullable=false) 
    private String descripcion; 
    @OneToOne 
    @JoinColumn(name="CATEGORIA _ID", 
        referencedColumnName="CATEGORIA_ID", updatable=false) 
    private Categoria categoria; 
    public Producto() { } 
    //Métodos Getters y Setters  
}  
@Entity 
@Table(name="CATEGORIAS") 
public class Categoria { 
  @Id 
  @Column(name=" CATEGORIA_ID") 
  private int id; 
  @Column(name="NOMBRECATEGORIA", nullable=false) 
  private String nombrecategoria; 
  public Categoria() { } 
  //Métodos Getters y Setters  
}
 
Anotación @OneToMany hace referencia a la asociación de 1-N en la que una entidad tiene dos o más referencias de otra.
Poniendo un ejemplo, podemos tener una tabla de jugador y otra de equipo. Un equipo puede contener varios jugadores, pero un jugador sólo puede estar en un equipo.
Esta relación sería:

 
@Entity 
@Table(name="EQUIPOS") 
public class Equipo { 
    ... 
    private Set<Jugador> jugadores = new HashSet<Jugador>(0); 
    //Métodos Getters y Setters  
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,  
                                   mappedBy = "equipo") 
 public Set<Jugador> getJugadores() { return this.jugadores; } 
 public void setJugadores(Set<Jugador> jugador) { this.jugadores = jugador; }
 ... 
}  
 
La anotación @OneToMany indica que un equipo puede contener varios jugadores.
La anotación @OneToMany tiene una propiedad llamada cascade que define el tipo de operaciones se realizarán cuando se efectúen modificaciones sobre los datos de la entidad.
La propiedad Cascade, puede tomar los siguientes valores:

  • CascadeType.PERSIST: Cuando persistimos una entidad, todas las entidades que contenga esta variable serán persistidas también.
  • CascadeType.REMOVE: Cuando eliminemos una entidad, todas las entidades que contenga esta variable se borrarán del mismo modo.
  • CascadeType.REFRESH: Cuando actualicemos la entidad, todas las entidades que contenga esta variable se actualizarán.
  • CascadeType.MERGE: Cuando hagamos un "merge" de la entidad, todas las entidades que contenga esta variable realizarán la misma operación.
  • CascadeType.ALL: Todas las operaciones citadas anteriormente.
La propiedad mappedBy = "equipo" indica el nombre de la entidad Equipo en el objeto Jugador.
Anotación @ManyToMany hace referencia a la asociación N-N.
Volviendo al ejemplo de equipos y jugadores, la anotación @ManyToOne indicaría que varios jugadores pueden haber sido inscritos en diferentes equipos.
Anotaciones del ciclo de vida:

  • @EntityListeners: Se pueden definir clases listeners con métodos de ciclo de vida de una entidad.
Para hacer referencia a un listener, se debe incluir esta anotación seguido de paréntesis de la clase: @Entity
Listeners(MyListener.class)

  • @ExcludeSuperclassListeners: Indica que ningún listener de la superclase será invocado por la entidad ni por ninguna de sus subclases.
  • @ExcludeDefaultListeners: Indica que ningún listener por defecto será invocado por esta clase ni por ninguna de sus subclases.
  • @PrePersist: El método se llamará justo antes de la persistencia del objeto. Podría ser necesario para asignarle la clave primaria a la entidad a persistir en base de datos.
  • @PostPersist: El método se llamará después de la persistencia del objeto.
  • @PreRemove: El método se llamará antes de que la entidad sea eliminada.
  • @PostRemove: El método se llamará después de eliminar la entidad de la base de datos.
  • @PreUpdate: El método se llamará antes de que una entidad sea actualizada en base de datos.
  • @PostUpdate: El método se llamará después de que la entidad sea actualizada.
  • @PostLoad: El método se llamará después de que los campos de la entidad sean cargados con los valores de su entidad correspondiente de la base de datos. Se suele utilizar para inicializar valores no persistidos.
  • @FlushMode: Modo en que se ejecuta la transacción: FlushModeType.AUTO (por defecto) y FlushModeType.COMMIT.
  • @NamedQuery: Especifica el nombre del objeto query utilizado junto a un EntityManager.
Sus atributos son:

    • name - nombre del objeto query.
    • query - especifica la query a la base de datos mediante lenguaje Java Persistence Query Language (JPQL)
  • @NamedQueries: Específica varias queries como la anterior.

Búsquedas de datos en Entidades

Una vez que tenemos las entidades, podemos realizar consultas de acción sobre los objetos utilizando las clases POJO's.
La forma más sencilla de buscar en un Entity Bean es utilizar el método find(Class, Object) de la interfaz EntityManager.
Este método permite buscar un Entity por su clave primaria.
Para buscar un producto, por ejemplo, podríamos usar el siguiente código:
Producto product = entityManager.find(Producto.class, new Long(1));
El primer parámetro del método find es la clase del Entity que deseamos buscar.
El segundo parámetro, la clave primaria del Entity.
La clase que pasemos como parámetro debe ser anotada con @Entity.

Búsquedas con JPQL

JPA ofrece una API para realizar tanto consultas como operaciones masivas sobre Entity Beans (actualizaciones y eliminaciones).
Esta API involucra tres componentes:

  • Métodos de consulta del EntityManager.
  • La interfaz javax.persistence.Query.
  • El lenguaje JPQL (Java Persistence Query Language).

Conexion a una Base de Datos mediante un EJB

1.Creamos una Enterprise Aplication con modulo EJB y WAR
2.Sobre la libreria EJB agregamos la libreria JAR de Oracle para el acceso a la base de datos
3.Sobre el proyecto EJB boton derecho y creamos un SessionBean indicando que es Remote y Stateless
3.Nos vamos a la carpeta EnterpriseBeans y en la sesion bean creada pulsamos sobre Add y sobre BusinessMethod
  y lo llamamos getEmpleadosDepartamento con ReturnType java.lang.String y en Parameters recibe un
  departamento que sera un int
4.La clase nos quedara de la siguiente manera para que vuelva a ser recuperada:
@Stateless
public class SessionBeanBuscadorEmpleados implements SessionBeanBuscadorEmpleadosRemote {
    @Override
    public String getEmpleadosDepartamento(int departamento) {
        try{
            //Agregamos la variable tabla donde se veran todos los elementos a buscar
            String tabla = "";
            //Creamos los accesos a la base de datos
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
            Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","system", "123456");
            PreparedStatement st = conn.prepareStatement("SELECT NOMBRE, APELLIDOS, ID FROM EMPLEADOS WHERE ID="+departamento+"%");
            st.setInt(1, departamento);
            ResultSet rs = st.executeQuery();
            tabla = "<table border='1'>";
            while(rs.next()){
                tabla += "<tr>";
                tabla += "<td>"+rs.getString(1)+"</td>";
                tabla += "<td>"+rs.getString(2)+"</td>";
                tabla += "<td>"+rs.getString(3)+"</td>";
                tabla += "</tr>";
            }
            tabla += "</table>";
            return tabla;
        } catch (SQLException ex) {
            return "Error "+ex.toString();
        }
    }
}
5.Nos vamos al proyecto WAR y creamos un Servlet que llamara al EJB llamado ServletBuscadorEmpleados
6.Pulsamos boton derecho sobre el codigo del Servlet dentro del try y hacemos una llamada al EJB
  mediante InsertCode >> Call Enterprise Bean y seleccionamos nuestro Session bean dentro del EJB
7.El Servlet nos quedará:
@WebServlet(name = "ServletBuscadorEmpleados", urlPatterns = {"/ServletBuscadorEmpleados"})
public class ServletBuscadorEmpleados extends HttpServlet {
    @EJB
    private SessionBeanBuscadorEmpleadosRemote sessionBeanBuscadorEmpleados;
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet ServletBuscadorEmpleados</title>");           
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Tabla de Empleados:</h1>");
            int numero = Integer.parseInt(request.getParameter("txtnumerodep"));
            String tabla = sessionBeanBuscadorEmpleados.getEmpleadosDepartamento(numero);
            out.println(tabla);
            out.println("</body>");

Llamada de un EJB desde un Servlet con un JSP

1.Crearemos un proyecto EJB llamado ProyectoBeanSession marcando la opcion de tipo WAR y EJB
2.Sobre el proyecto EJB crearemos una nueva Session Bean y dejaremos el nombre por defecto NewSessionBean
  y lo incluiremos en un paquete llamado paquetebean.
3.Marcaremos la opción de tipo Session Stateful e indicaremos que será de tipo remoto y
  seleccionaremos el nombre del proyecto EJB.
4.Una vez creado el Bean, vamos a implementar un método de acción. Debemos ir al proyecto EJB, sobre la carpeta
  Enterprise Bean y seleccionamos la opción Add, Bussines Method para crearnos un método de negocio
5.Escribimos el nombre del método como getSaludo, e indicamos que el tipo que devolverá es de la clase String.
6.Nos quedará de la siguiente forma:
package paquetebean;
import javax.ejb.Stateless;
@Stateless
public class NewSessionBean implements NewSessionBeanRemote {
    @Override
    public String getSaludo() {
        return "Mensaje enviado desde un EJB @Stateless";
    }
}
7.Ahora vamos a agregar un Servlet que implementará la funcionalidad del componente EJB que nos hemos creado.
8.Sobre el proyecto WAR, seleccionaremos la opción New >> Servlet y lo llamaremos ServletLlamadaEJB
  y lo incluiremos en un paquete llamado paqueteservlets.
9.No incluiremos la información en el archivo descriptor de la aplicación, aunque si lo hiciéramos,
  la llamada al EJB seguiría siendo la misma.
10.Una vez que nos ha creado el servlet, debemos implementar la llamada, para ello utilizaremos el asistente
  de código que nos permite insertar código generado dinámicamente.
11.Sobre el código del servlet, seleccionamos la opción Insert Code
12.Nos aparecerán una serie de opciones, nosotros seleccionaremos la opción que llama a un Bean.
  Marcaremos la opción Call Enterprise Bean.
13.Al seleccionar dicha opción, nos muestra una ventana dónde debemos indicar el Bean que vamos a llamar
  desde el servlet. Buscamos el bean en el proyecto EJB y pulsamos sobre OK.
14.Podremos comprobar en el código que nos genera las librerías necesarias para realizar la llamada al
  Bean de Session:
    import javax.ejb.EJB;
    import paquetebean.NewSessionBeanRemote;
15.También nos generará un objeto para poder invocar al método getSaludo desde nuestro servlet. Dicho objeto
  podremos comprobar que contiene la anotación @EJB.
    @EJB
    private NewSessionBeanRemote newSessionBean;
16.Ahora vamos a implementar el servlet para poder escribir el saludo escrito y enviado desde el EJB:
@WebServlet(name="ServletLlamadaEJB", urlPatterns={"/ServletLlamadaEJB"})
public class ServletLlamadaEJB extends HttpServlet {
    @EJB
    private NewSessionBeanRemote newSessionBean;
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<HTML>");
            out.println("<head>");
            out.println("<title>Servlet ServletLlamadaEJB</title>"); 
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet con llamada a EJB</h1>");
            out.println(newSessionBean.getSaludo());
            out.println("</body>");
            out.println("</HTML>");
        } finally {
            out.close();
        }
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
}
17.Nos quedaría realizar la llamada al Servlet. Para ello, sobre el proyecto WAR vamos a seleccionar la página
 que trae por defecto index.html y la implementaremos.Escribiremos el siguiente código:
<%@page contentType="text/HTML" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
    <head>
        <meta http-equiv="Content-Type" content="text/HTML; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Bienvenido a la prueba de EJB</h1>
        <form name="form1" action="ServletLlamadaEJB">
            <input type="submit" value="Pulse para llamar al componente EJB">
        </form>
    </body>
</HTML>

Llamada de un EJB desde un Servlet

1.Creamos un nuevo proyecto EnterpriseAplication con el modulo EJB y WAR con GlassFishServer
2.Sobre el proyecto EJB boton derecho y creamos un SessionBean indicando que es Remote usando nuestro mismo
  proyecto EJB por si queremos usarlo en otros proyectos, con sesion Stateless(sin estado)
3.Nos vamos a la carpeta EnterpriseBeans y en la sesion bean creada pulsamos sobre Add y sobre BusinessMethod
  y lo llamamos getDoble con ReturnType java.lang.String y en Parameters agregamos un numero de tipo int
4.La clase nos quedara de la siguiente manera para que vuelva a ser recuperada:
@Stateless
public class NewSessionBean implements NewSessionBeanRemote {
    @Override
    public String getDoble(int numero) {
        int resultado = numero*2;
        return "El doble del numero es "+resultado;
    }
}
5.Nos vamos al proyecto WAR, que es el que usuario vería y el que consumiría los EJB
6.Creamos un Servlet que llamara al EJB creado dentro de la carpeta Source Packages en el WAR
7.Pulsamos boton derecho sobre el codigo del Servlet dentro del try y hacemos una llamada al EJB
  mediante InsertCode >> Call Enterprise Bean y seleccionamos nuestro Session bean dentro del EJB lo que
  nos introducirá el codigo
  @EJB
  private NewSessionBeanRemote newSessionBean;
8.En el Servlet introduciremos una variable num que recogerá el valor que venga de un futuro JSP que creemos
  int num = Integer.parseInt(request.getParameter("txtnumero"));
9.Queremos utilizar este numero para llevarlo a nuestro Bean y calcular el doble:
  String texto = newSessionBean.getDoble(num);
  out.println(texto);
10.Creamos la pagina HTML donde introduciremos el numero a calcular el doble:
    <form name="form1" action="NewServletLlamada">
            Introducir un numero: <input type="text" name="txtnumero"><br>
            <input type="submit" name="Calcular Doble">
        </form>
11.El Servlet nos quedará:
@WebServlet(name = "NewServletLlamada", urlPatterns = {"/NewServletLlamada"})
public class NewServletLlamada extends HttpServlet {
    @EJB
    private NewSessionBeanRemote newSessionBean;
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet NewServletLlamada</title>");           
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet NewServletLlamada at " + request.getContextPath() + "</h1>");
            int num = Integer.parseInt(request.getParameter("txtnumero"));
            String texto = newSessionBean.getDoble(num);
            out.println(texto);
            out.println("</body>");
            out.println("</html>");
        }
    }

Acceso de un Java Beans a una Base de Datos Oracle mediante un JSP

Enterprise Java Beans (EJB) es una plataforma para construir aplicaciones de negocio portables, reutilizables y escalables usando el lenguaje de programación Java.
Todo EJB está compuesto por dos capas:
- Capa Interfaz, indica a las clases que consuman los métodos y características del EJB.
- Capa Implementación es una clase que implementa la capa de Interfaz.


EJEMPLO:
 
1.Dibujaremos un control HTML Select que mantendrá el elemento seleccionado cuando enviemos una petición al
  servidor.
2.Creaamos un nuevo proyecto Web Application llamado ProyectoJSPJavaBeans y utilizaremos el servidor GlassFish
3.Sobre las librerías vamos a agregar el conector JAR para Oracle
4.Creamos una clase Java que será la que dibujará los elementos en el Select y los mantendrá seleccionados
  y la llamaremos BeanDesplegable y crearemos un paquete llamado paquetebeans:
package paquetebeans;
import java.sql.*;
public class BeanDesplegable {
    Connection cn = null;
    java.sql.Statement st = null;
    final String usuario = "system";
    final String password = "12345";
    final String cadenaconexion = "jdbc:oracle:thin:@localhost:1521:XE";
    public BeanDesplegable () {

    }
    public void conectar() throws SQLException, Exception
    {
        try
            {
                 // 1.- Cargamos el driver
                 DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
                // 2.- Nos conectamos, paso el nombre de la conexion, usuario y contraseña.
                this.cn = DriverManager.getConnection(cadenaconexion, usuario, password);
            } catch (SQLException e)
            {
                System.out.println(e.toString());
            }
    }

    public ResultSet crearResultSet(String consulta) throws Exception
    {
        ResultSet rs = null;
        st = cn.createStatement();
        rs = st.executeQuery(consulta);
        return rs;
    }

    public String cargarCombo(ResultSet rs, String nombreselect, String valorseleccionado)
    {
        String combo;
        try
        {
            combo = "<select name='"+nombreselect+"'>";
            while (rs.next())
            {
                if (rs.getString(1).equals(valorseleccionado))
                {
                    combo+="<option SELECTED ";
                }else{
                    combo+="<option ";
                }
                combo+="value='"+rs.getString(1)+"'>";
                combo+=rs.getString(2);
                combo+="</option>";
            }
            combo += "</select>";
            return combo;
        } catch (SQLException ex) {
            return ex.toString();
        }
    }
}
5.Utilizamos la página index.jsp del proyecto para poder realizar la llamada al Bean y mostrar los datos de
  los departamentos.
<%@page import="java.sql.ResultSet"%>
<%@page contentType="text/HTML" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<jsp:useBean id="practica" scope="session" class="paquetebeans.BeanDesplegable "/>
<HTML>
    <head>
        <meta http-equiv="Content-Type" content="text/HTML; charset=UTF-8">
        <title>Cargar Desplegable</title>
    </head>
    <body>
        <form name="form1" action="index.jsp" method="post">
            Seleccione un departamento:
          <%
          practica.conectar();
          ResultSet rs =practica.crearResultSet("SELECT DEPTNO,DNAME FROM DEPT");
          String combo;
          String etiqueta="";
          if (request.getParameter("cmbdept")!=null)
          {
                String dept = request.getParameter("cmbdept");
                combo = practica.cargarCombo(rs, "cmbdept", dept);
                etiqueta = "<div>Elemento seleccionado:"+dept+"</div>";
          }else{
                combo = practica.cargarCombo(rs, "cmbdept", "");
          }

          %>
          <%=combo%>
          <input type="submit" value="Enviar formulario">
          <%=etiqueta%>
        </form>
    </body>
</HTML>

Interface en Enterprise Java Beans EJB

CREACION Y LLAMADA DE UN JAVABEANS CON INTERFAZ
1.Creamos un nuevo proyecto de JavaAplication y vamos a agregar una Interfaz que será el contrato.
2.Boton derecho sobre el paquete y seleccionamos JavaInterface y llamaremos a nuestra Interfaz: InterfazEJB
3.Escribimos el siguiente código en la Interfaz.
package javaapplication1;
public interface InterfazEJB {
    public void GetMensaje(String nombre);
}
4.A continuación, nos crearemos una clase sobre el mismo paquete que llamaremos ClaseEJB.
  Dicha clase se encargará de implementar la Interfaz de contrato EJB.
5.Debemos utilizar el espacio de nombres siguiente: import javax.ejb.Stateless
6.Al no reconocer la librería de los EJB, tendremos que incluirla manualmente para poder trabajar con dichas
  clases.
7.Boton derecho sobre la carpeta Libraries y pulsamos "Agregar archivo JAR/carpeta". Buscamos la librería de
  ejb que hayamos descargado desde la pagina oficial de Oracle
8.Implementamos la Interfaz sobre la ClaseEJB. Para ello escribimos el siguiente código:
  public class ClaseEJB implements InterfazEJB {
9.Eso nos dará un fallo debido a que tenemos que implementar todos los métodos que contenga la Interfaz
  Debemos pulsar sobre el símbolo de la bombilla de la izquierda del código y nos aparecerá una opción para
  Implementar los métodos abstractos.
10.Una vez que tenemos todos los métodos implementados, escribimos el siguiente código dentro de la clase
  llamada ClaseEJB. Donde el @Override significa sobreescribir el metodo anteriormente definido.
package javaapplication1;
import javax.ejb.Stateless;
public class ClaseEJB implements InterfazEJB
{
    @Override
    public void GetMensaje(String nombre) {
        System.out.println("Primer EJB, Bienvenido a la tecnología " + nombre);
    }
}
11.Creamos un cliente que consuma nuestro bean. Aagregamos una nueva clase sobre el paquete creado y
  la llamaremos ClienteEJB.
package javaapplication1;
import javax.ejb.EJB;
public class ClienteEJB {
@EJB
private ClaseEJB BeanEJB;
    void MetodoCliente()
    {
        BeanEJB = new ClaseEJB();
        BeanEJB.GetMensaje("Usuario de EJB");
    }
}
12.Ahora iremos a la clase inicial de los proyectos de J2SE llamada Main.java. Implementamos el siguiente código:
package javaapplication1;
public class Main {
    public static void main(String[] args) {
        ClienteEJB cliente = new ClienteEJB();