martes, 31 de marzo de 2009

Día 46: EJB (5ª Parte) y JSF (4ª parte)

Lo más puntero hoy día es la combinación de las tecnologías JSF, EJB y JPA

El JPA son las clases persistentes, las clases java que tienen la anotación @Entity , que siempre tendran un id (@Id) que será un valor generado (@GeneratedValue) y que la clase implementará "serializable"

Los EJB son interfaces que usan la anotación "@Remote" e implementaciones que usan @Stateless o @Statefull en el que se inyectan los "entityManager" a través de la anotación "@PersistenceContext"

Los JSF son las páginas ".xhtml" que rellenan con sus formularios los datos de las acciones y un archivo de configuración "my-config.xml" los crea y los enlaza.

En resumen: Un usuario accede a un formulario lo rellena y lo envía. -> Un JSF envía los datos a unas acciones que se encargan de redirigirlas a un EJB que éste rellena los datos en una entidad (JPA) y se guardan en una base de datos.

Proyectos clave:
JPA: discografia-hibernate
EJB: ejbProject
JSF: jsf1

Lo que hoy hicimos fue lo mismo que estos dias atras, el caso de hoy es que un usuario introduce su nombre y su clave y para los que terminaran que introdujeran mejoras en el proyecto como un buscador de cantante y otro de disco metiendo nuevos métodos en el "DiscograficaDAO"

lunes, 30 de marzo de 2009

Día 45: EJB (4ª Parte) y JSF (3ª parte)


Hoy comenzamos cambiando el puerto en la que abre las aplicaciones. Para ello modificamos las propiedades de configuración del pluggin jetty de maven del proyecto que queremos arrancar (modificar el archivo "pom.xml").
Después añadimos todas las librerías que están en: "jboss-5.0.1.GA\client" a las librerías del proyecto "jsf1"

Creamos un nuevo servicio, ServicioCadenas que lo que hace es recibir una cadena de caracteres y devolver el número de su longitud.
El método para hacerlo es como lo hemos hecho anteriormente.




Consejos
Atajo del eclipse: (Alt+T) Botón secundario, Refactor y "Pull up" y marcamos los métodos que queramos "subir" de una implementación a una interfaz.
Problemas con proyectos remotos EJB: Las soluciones son varias al igual que los problemas, pero lo más común es:
  • Reponer la librería del proyecto: Run As, Maven Clean (Eliminará la librería del proyecto en el servidor JBoss) y después Run As, Maven Package (volverá a poner la librería)
  • Si se nos ha olvidado instalar el proyecto: Run As, Maven Install (Añadirá una librería del proyecto en el repositorio del maven) y después: Run As, Maven package (lo de antes, ...)
  • Lo que casi todo en la informática, reiniciar:
    > Cerrar y volver a encender el servidor jetty (Control+c y después S)
    > Cerrar y volver a encender el JBoss
    > Combinar orden de encendidos y apagados, ...
  • Se admiten más consejos

viernes, 27 de marzo de 2009

Día 44: EJB (3ª Parte) y JSF (2ª parte)

JSF

Funcionalidades del proyecto en grupo / ideas
El JSF controla la Vista y el Modelo
Usará EJBs usando tambien Entidades

Tareas con JSF-> (MVC) Reglas de navegación, formularios, botones de acciones e inyeccion de dependencias.
Tareas con Reglas de negocio (EJB) -> Acceso a persistencia, transacciones, realizará las consultas.
Tareas con Entidades -> Clases persistentes, clase Libro, clase Género, etc.
Disco disco = new Disco();
session.save(disco);, etc

Ejercicio 1
Dentro del proyecto de ayer (jsf1) creamos una nueva funcionalidad, la de registro.
  • Primero creamos "registro.xhtml" y usamos las etiquetas predefinidas de "h" y colocamos un "inputText" y un "inputSecret", que serán el mail y la clave.
  • Seguidamente creamos "registroCorrecto.xhtml" que simplemente mostrará que lo hemos conseguido y mostrando el mail que introdujimos.
  • Creamos, en el paquete "es.cea", la clase "Registro" cuyas propiedades son un mail y una clave y sus métodos getter y setters.
  • Hacemos un "RegistroAction" que será la acción del registro cuando pulsamos el botón. Tendrá una propiedad de tipo "Registro" y que tenga un método llamado "registra". En el método si el mail que se recibe no es "(un email que queramos)" que devuelva nulo y si es el mail que queremos pues que devuelva "válido"
  • En el archivo de configuración "my-config.xml" añadimos el bean de registro (managed-bean) y su acción y en éste último no nos olvidemos de la inyección de la dependencia (managed-property).
  • Tampoco nos olvidemos de la regla de navegación en el "my-config.xml" (navigation-rule) sobre si el mail es válido o no.
  • Probar que funciona arrancando el jetty desde la línea de comandos en el proyecto. (recuerdo que era: "mvn jetty:run")

Ejercicio 2 (variante del 1)
Este ejercicio consiste en lo mismo que el ejercicio anterior.
Recojemos el proyecto "discografia-hibernate" y hacemos "Run As...", "Maven install" y en el proyecto que estamos trabajando, "jsf1", le añadimos la dependencia desde maven del proyecto de la discografía y hacemos lo mismo que el ejercicio anterior, que haya una página de cantante, que se introduzca su nombre, que haya una acción, que redijira, etc etc. (no vuelvo a repetir los pasos porque son los mismos)

Esqueleto de proyecto JSF-EJB-Hibernate
Unos puntos clave (ha sido muy intensa la clase así que más o menos de lo que me acuerde xD)
  • Necesitamos 3 proyectos: "discografía-hibernate" , "ejbProject" y "ejbProjectClient"
  • Debemos "empaquetar" los dos primeros proyectos. (Run As.., Maven package)
  • Arrancar el servidor JBoss y si nos falla revisar en la carpeta deploy (jboss-5.0.1.GA\server\default\deploy)
  • Abriremos la clase java "DiscograficaDAOClient" del proyecto "ejbProjectClient" que será en donde veremos que funciona toda la estructura del proyecto.
  • En los Beans "Cancion", "Cantante", "Disco" tenemos que implementar la interfaz serializable (del paquete java.io) y haciendo Control+1 (marcar la 2ª opción) añadir el serialVersionUID para que a la hora de pasar la clase persistente a travez de la red se serialice y despues se deserialice en su destino.
  • Abrimos el "pom.xml" del proyecto "ejbProject" y copiamos:
    Copiar la etiqueta "Properties" (Al principio) que es la ruta en donde se empaquetará el proyecto en el servidor JBoss
    Copiar el plugin cuyo artifactId se llama "maven-jar-plugin"
    Copiar el plugin cuyo artifactId se llama "maven-clean-plugin"
    Pegarlos todos en su respectivo lugar en el "pom.xml" del proyecto "discografia-hibernate"
  • Abrir el archivo "persistence.xml" del proyecto "discografia-hibernate" y comprobar que el nombre de la unidad persistente concuerde con el que se nombra en el archivo "discografica-ds.xml" que está en el "deploy" del server

Consejos
Sobre Ejercicio 1 y 2:
Si queremos que aparezca un mensaje de error en el jsf lo que tenemos que hacer es un control en la acción, que si no devuelve success o válido (o lo que hayamos puesto que sea afirmativo) que envíe un mensaje de error y lo hacemos de la siguiente manera:
FacesMessage message =
new FacesMessage(FacesMessage.SEVERITY_INFO,"El mail no se corresponde",null);
FacesContext.getCurrentInstance().addMessage("mail", message);
Para que funcione en la página del formulario ".xhtml" debemos indicar la etiqueta "h:messages" encima del primer input del formulario y cuando introduzcamos un valor incorrecto nos aparecerá.
Aviso!!: para que funcione no tiene que haber una regla de navegación en el "my-config.xml" (a ver si encuentro el porqué)

jueves, 26 de marzo de 2009

Día 43: EJB (2ª Parte) y JSF

EJB

EJB + JBoss AS
Proyecto Eclipse Configuración

Primero tener en el build path la librería de tiempo de ejecución del JBoss.

Localizaciones a recordar:
JBoss : Para que arranquen las aplicaciones debemos tener presente: JBoss/server/default/deploy/* (con extensiones como .ear, .war o .jar)
TomCat : Tomcat/webapps/*.jar

Practicar la creación de un proyecto EJB:
  • Nuevo proyecto maven
  • Crear un simple proyect
  • Group Id: nombre del paquete
    Artifac id: nombre del jar
  • Build Path, añadir libreria, server runtime, JBoss
  • Crear un paquete es.cea y dentro una interfaz: ServicioCalculadoraRemote
  • Añadir una anotación "@Remote" encima del nombre de la intefaz y crear un método "suma"
  • Crear una clase ServicioCalculadora que implemente ServicioCalculadoraRemote e implemente el método "suma" y añadir en la cabecera de la clase la etiqueta de sin estado "@Stateless"
  • Botón secundario encima del proyecto, Export y marcamos el paquete es.cea que están nuestras dos clases.
    La librería se colocará en "..\servers\jboss-5.0.1.GA\server\default\deploy\" y le ponemos de nombre "calculadora.jar"
  • También tenemos otro modo de hacer lo mismo y es botón secundario encima del proyecto, Run As.. y marcamos "Maven Package" y la librería que nos crea lo copiamos en la misma ruta antes dicha.
  • Si queremos acceder desde una clase java
  • Copiamos del proyecto de ayer la clase "PrimerBeanClient" y lo modificamos. Recordemos que llamamos a las interfaces, no a las clases.
  • El main debe quedar tal que así:
    try {
    Properties p = new Properties();
    p.put(Context.INITIAL_CONTEXT_FACTORY,
    "org.jnp.interfaces.NamingContextFactory");
    p.put(Context.URL_PKG_PREFIXES,
    "org.jboss.naming:org.jnp.interfaces");
    p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
    Context ctx = new InitialContext(p);
    Object ref = ctx.lookup("ServicioCalculadora/remote");
    ServicioCalculadoraRemote servCalc = (ServicioCalculadoraRemote) PortableRemoteObject
    .narrow(ref, ServicioCalculadoraRemote.class);
    System.out.println("1 + 2 = " + servCalc.suma(1, 2));
    } catch (NamingException e) {
    e.printStackTrace();
    }

Ejercicio:
Pequeño manual de enviar un mensaje de correo usando gmail: Manual
Teniendo este código: Java Mail
Tenemos que hacer un EJB de servicio de mail usando nuestra cuenta de GMail.
  • Primero creamos un proyecto, lo llamaremos servicioMail
  • Configuramos el "build Path" y añadimos una librería nueva de tipo "Server runtime" y seleccionamos el JBoss
  • Creamos una interfaz "ServicioMailRemote" y su clase implementación "ServicioMail" en el paquete "es.cea"
  • En la interfaz añadimos la anotación @Remote y creamos la cabecera del método de enviar el Email.
  • En la clase implementación ("ServicioMail") añadimos la anotación @Stateless e implementamos el método según el enlace que puse antes pero cambiando algunas cosas:
  • Cambiar: props.setProperty("mail.smtp.port","465");
    Añadir: props.setProperty("mail.smtp.socketFactory.class",
    "javax.net.ssl.SSLSocketFactory");
  • El código completo sería:
    // Propiedades de la conexión
    Properties props = new Properties();
    props.setProperty("mail.smtp.host", "smtp.gmail.com");
    props.setProperty("mail.smtp.starttls.enable", "true");
    props.setProperty("mail.smtp.port", "465");
    props.setProperty("mail.smtp.socketFactory.class",
    "javax.net.ssl.SSLSocketFactory");

    props.setProperty("mail.smtp.user", origen);
    props.setProperty("mail.smtp.auth", "true");
    // Preparamos la sesion
    Session session = Session.getDefaultInstance(props);
    // Construimos el mensaje
    MimeMessage message = new MimeMessage(session);
    message.setFrom(new InternetAddress(origen));
    message.addRecipient(
    Message.RecipientType.TO,
    new InternetAddress(destinatario));
    message.setSubject(asunto);
    message.setText(mensaje);
    // Lo enviamos.
    Transport t = session.getTransport("smtp");
    t.connect(origen, password);
    t.sendMessage(message, message.getAllRecipients());
    // Cierre.
    t.close();
  • Despues de esto exportamos el paquete al JBoss como explicamos antes.
  • Run As.. Java Application y listo

Ejercicio expandido (opcional):
Usando el mismo ejercicio usar el ANT para automatizar copiar el jar a la carpeta de destino del servidor y otra tarea de borrar para "desinstalar" la aplicación.

JSF
Java Server Faces

Es una herramienta de modelo vista controlador (MVC)

Más información AQUÍ

Abrimos el proyecto "jsf1" que sólo arrancará desde el jetty y desde la línea de comandos (mvn jetty:run)
Vamos al localhost/jsf1/ y ahí lo veremos.

El proyecto consiste en que hay unas clases bean (Modelo), un xhtml y unos archivos de configuración.
Un xhtml (Vista) tiene un formulario, cuyo botón de submit se envía a una clase de acción que controlará (controlador) el formulario. Un archivo xml enlazará todo y si recibe de los controladores el "success" mostrará los xhtml de respuesta.

Consejo:
Toda página que hagamos tiene que ser xhtml y no html

miércoles, 25 de marzo de 2009

Día 42: EJB

EJB

Las aplicaciones EJB solo se pueden arrancar en un Servidor de aplicaciones como JBoss y los servlet, jsp y demás sólo en servidores web como el tomcat o el jetty.
Gracias al SPRING podemos usar aplicaciones EJB en servidores web. STRUTS sin SPRING no podría usar hibernate.

Servicios de los tipos de EJB

Pooling: Una lista de objetos que cada cual tiene una capacidad de usuarios, si uno se "desborda" desvia el usuario nuevo al siguiente objeto para optimizar el rendimiento.
Thread safety: cuando un usuario está conectado a un objeto lo hace mediante un "hilo" y otro usuario que se conecte tendrá que esperar hasta que el primer usuario acabe.
State Management: Cuando un usuario mete datos en un objeto y pasa cierto tiempo el objeto se serializa en un archivo y cuando vuelve a la actividad se desserializa.
Transactions: A la hora de inicializar una transaccion se utilizan X componentes y cuando se termina la transacción también.
Segurity: Que el usuario cuando acceda al componente tenga los permisos adecuados, que rol tiene.
Interceptors: Los EJB pueden interceptarse. En la comunicación de 2 componentes hay algo en medio que ninguno sabe que puede cambiar el valor de llegada y salida. No interviene en los métodos del componente de destino, simplemente intercepta.
Remote Access: Permite acceder de forma remota y obtener los objetos de esa aplicación.




Tipos de EJB:
SESSION STATEFULL
SESSION STATELESS
ENTITIES
MDB

Instalación de JBoss
Primero cojemos la carpeta "jboss-5.0.1.GA" y la introducimos a la carpeta de servidores que hicimos el primer dia para introducir el tomcat.
Entramos en el servidor, vamos a la carpeta "bin" y ejecutamos el "run.bat" para arrancar el servidor desde consola.
Para levantar el servidor desde el Eclipse nos vamos a la vista de servidores, creamos uno nuevo, seleccionamos que es un JBoss de versión 5.0 y le indicamos la ruta de la carpeta de los servidores.

Un EJB es un POJO, que no hereda de nadie.

Unas anotaciones importantes:
@Remote - Indica que es una interfaz remota.
@StateLess - Indica que la clase está sin estado y podrá ser accedido. (Es el tipo EJB de sesión remota)
@Local - Indica que la clase es local y accederá a una remota.
Si queremos añadir alguna librería al jboss la ruta es la siguiente: JBoss/Server/default/deploy/cea.jar

Ejercicio:
Tenemos que practicar el primer ejercicio de acceso remoto a un método para ello tenemos que hacer lo siguiente:
  • Usar el proyecto "JavaEECea" y en el paquete "server.cap02" en el source folder "src/main/java" añadir las clases "SegundoBean" y "SegundoBeanRemote"
  • Primero editamos el "SegundoBeanRemote" que será una interfaz con un método cualquiera.
  • Seguidamente editamos el "SegundoBean" que implementará el método del "SegundoBeanRemote"
  • Hacemos botón derecho del ratón en el proyecto y procederemos a exportar estas clases remotas. Export, tipo "JAR file", y marcaremos estas dos clases, o si están solas, el paquete entero, y le damos a "Browse..." y meteremos la nueva librería a la carpeta del jboss: "JBoss/Server/default/deploy" poniendole el nombre que queramos.
  • Vamos al paquete "client.cap02" del source folder "src/test/java" y creamos una clase nueva llamada "SegundoBeanClient". En esta clase podemos copiar lo que hay en "PrimerBeanClient" y editar el nombre de la clase remota que hicimos, su objeto, el nombre del método y lo más importante decirel nombre de la clase a la que vamos a acceder: Object ref = ctx.lookup("SegundoBean/remote");

Un EJB es una aplicación distribuida por la web que podrá ser accedido por una aplicación de escritorio (un chat por ejemplo) o una aplicación web.

Ejercicio2:
Este ejercicio consiste en hacer un servlet que acceda a un método de una clase remota.

  • Creamos un proyecto llamado "webyejbs"
  • Creamos una clase servlet "Bienvenida.java" en un paquete "es.cea"
  • En el servlet añadimos un método privado que sea "suma" lo que hará este método es hacer es casi lo mismo que la clase "PrimerBeanClient" del proyecto anterior, lo copiamos todo a excepción de que en vez de usar un println usamos un return.
  • En el método Get del servlet comprobamos que hay escritos dos parametros en la dirección y que llame al método "suma" que hemos hecho.
Para que ésto funcione tenemos que:
  • Añadir todas las librerías que están en la carpeta "JBoss/client/*.jar" en la carpeta del "tomcat/lib/"
  • Arrancar el servidor Tomcat a la vez que aún está desplegado el servidor JBoss, para ello deben tener puertos distintos.

martes, 24 de marzo de 2009

Día 41: Hibernate (2ª parte)

Hibernate
Hoy hicimos un repaso del ejercicio que teníamos que hacer ayer ya que casi la mitad de la clase faltó.
Después del repaso continuamos con el ejercicio para terminarlo.

Usando etiquetas para clases persistentes.
Sólo encima de las clases:
@Entity : Entidad
@Table(name="") : Nombre de la tabla
Para los métodos:
@Id : Indica que es la clave primaria
@GeneratedValue : Que se autoincremente
@Column : Es una columna en la tabla
@ManyToOne : Indica que el campo es una clave ajena para el que le referencia.
@OneToMany(mappedby="la propia clase pero con notación de objeto") : Indica que es una clave ajena.
@ManyToMany : Para indicar una relacion de muchos-muchos, para ello tendremos que usar un grupo de anotaciones en ambas clases. En una primera clase:
@ManyToMany @JoinTable(name="DiscoProductora",
joinColumns= @JoinColumn(name="productora_id", referencedColumnName="id"),
inverseJoinColumns= @JoinColumn(name="disco_id", referencedColumnName="id")
)
@IndexColumn(name="orden")


y en una segunda:

@ManyToMany @JoinTable(name="DiscoProductora",
joinColumns= @JoinColumn(name="disco_id",referencedColumnName="id"), inverseJoinColumns= @JoinColumn(name="productora_id", referencedColumnName="id") )

@Transient : Hibernate ignora el método que le siga, porque por defecto no hace falta usar @Column.

POJO
Plain Old Java Object, son objetos que no heredan, no implementan interfaces y son independientes con sus métodos getters y setters. Éste tipo de objetos son los que usamos en hibernate, las clases persistentes.
Más información AQUÍ

lunes, 23 de marzo de 2009

Día 40: Acceso a Base de Datos. Hibernate

Hibernate
Cuando recojemos algún dato de una base de datos mediante objetos lo que se hará es por ejemplo:
GrupoMusica g = m.getGrupoMusica();
List discos = g.getDiscos();
Hibernate por debajo hará la consulta SQL:
select * from discos where grupo_id = 1;

La carga perezosa, o lazy-loading, consiste en que no se realiza ningún select hasta que invoquemos un método get, de no ser así cada vez que creamos un objeto sin llenarlo el hibernate hará un select cada vez y haría que nuestra aplicación fuera más lenta.
Por suerte nuestra está siempre por defecto a "true"

Nos vamos a la página 159 del PDF "hibernate_reference"

Sobre la problemática de la herencia:
Tenemos una clase padre Usuario y otras 3 clases hijas que heredan de ésta.
Usuario tiene los campos id y nombre.
Registrado tiene además el campo dirección.
Administrador tiene un campo clave y permisos.
Para que todo esto funcione tiene que haber una tabla que tenga todos los campos de todas las clases que usamos además del campo "tipo" que indicará si es registrado o administrador.

Ejercicio
El ejercicio de hoy consiste en crear una estructura de clases usando hibernate y también crear las tablas, aunque nos centraremos simplemente en las clases y sus relaciones.

La estructura de relaciones del ejercicio es la siguiente:
  • Un GrupoMusica tiene muchos Músico y un Músico solo tiene 1 GrupoMusica
  • Un GrupoMusica tiene muchos Disco y un Disco solo tiene 1 GrupoMusica
  • Un Disco tiene muchas Cancion y una Cancion solo tiene 1 Disco
  • Un Disco tiene muchas Productora y una Productora tiene muchos Disco
  • Un Disco tiene muchos Pedido y un Pedido solo tiene 1 Disco
  • Un Pedido solo tiene 1 Cliente y un Cliente tiene muchos Pedido

Los métodos que deben tener, además del id y del nombre (método en plural=Colección de ...):
  • GrupoMusica: +musicos / +discos.
  • Musico: +grupoMusica
  • Disco: +grupoMusica / +productoras / +pedidos / +canciones
  • Productora: +discos
  • Cancion: +disco
  • Pedido: +disco / +cliente
  • Cliente: +pedidos

Los pasos a seguir son:
  • Crear los modelos de cada tabla, es decir, crear cada clase de lo que vayamos a hacer. GrupoMusica, Musico, Disco, Cancion, Productora, Pedido y Cliente.
    Cada una de ellas se tiene que crear en el proyecto modelo "libreria-model" y haremos un paquete nuevo que lo distinga.
  • Crear cada archivo ".hbm.xml" de cada clase indicando los campos que aparecerán en la base de datos y sus relaciones.
  • Actualizar el archivo "hibernate.cfg.xml" para que se apliquen las clases persistentes.
  • Actualizar el archivo "import.sql" para que añada datos de ejemplo.
  • Ejecutar un test para que se verifique que funciona todo.