martes, 5 de mayo de 2009

Último Día, 60: Evaluación

Para poner condiciones usando las el conjunto #{} para mostrar valores en las vistas (JSF).
Un ejemplo sería el siguiente, que dependiendo si se está logueado o no aparecerá rojo o verde:
style:"color:#{(identity.loggedIn)?'rojo':'verde'}"


Despedida
Hoy ya es el último día en todos este tiempo en el que he estado en la "verdadera" programación en java y más dificil. Podría decirse que ya tengo una cierta base y más con la ayuda de mi propio blog que usaré como apuntes, pero el auténtico reto es la realidad, en el mundo laboral con las prácticas en empresa y con suerte colocarme en ellas.
Espero tener suerte y también para mis compañeros de curso.
Y sobre el blog.. espero poder mejorar las entradas de aquí en adelante y terminar las incompletas.


Por último, como hemos completado un curso (en realidad sólo la teoría) en nuestro currículum podemos ampliar la información que hemos asimilado en estos meses y para ello tenemos lo siguiente:

Systemas operativos:Windows
Lenguajes de programación:Java J2EE
Bases de datos: MySQL. Utilizo habitualmente Hibernate para mapeo O-R.
Programación Web: CSS

IDE's: Eclipse. Plugins de eclipse: subclipse(subversion), testng, jboss, m2eclipse(maven)
Servidores Web: Tomcat y Jetty
Servidores de aplicaciones: JBoss
Frameworks de desarrollo web en java: Servlets, JSP, JSTL, Struts, SpringFramework, JBoss Seam, JSF, EJB

Frameworks de pruebas: TestNG, Mockito

Herramientas de automatización y estandarización en el desarrollo: Ant, Maven, Subversion, log4j, commons-logging


Contenido del master en java j2se y j2ee
Desarrollo de Componentes Web Con Tecnología Java (84 Horas)
  • Introducción al desarrollo de Aplicaciones Web con Java
  • introducción al Control de Versiones utilizando la herramienta Subversion
  • introducción a la POO (Programación Orientada a Objetos) a través del estudio del framework de colecciones de java y su comprobación a través de pruebas con testNG
  • introducción a las excepciones, su diseño y su gestión en un programa
  • introducción al seguimiento del programa por consola (logging) y configuración. Uso de la herramienta Log de la librería commons-logging y log4j de Apache
  • introducción a Apache ANT: herramienta de automatización de tareas en el desarrollo
  • introducción al api jdbc: Java Data Base Connectivity
  • profundización en el uso y creación de anotaciones
  • introducción a la herramienta MAVEN: herramienta de estandarización del desarrollo (automatización de tareas) en proyectos java, destacando la gestión de dependencias
  • servidores web
  • desarrollo de servlets modelo 1 :listeners, filters, servlets
  • introducción a JSP - Java Server Pages. Modelo 2 de desarrollo con Servlets
  • introducción a JSTL - Java Standar Tag Library
  • introducción al patrón de desarrollo Controlador Frontal
  • introducción al patrón de desarrollo MVC - Modelo Vista Controlador

Desarrollo de Aplicaciones J2EE (56,50 Horas)
  • Arquitectura J2EE.
  • servidores de aplicaciones
  • introducción a Struts 1
  • introducción a EL - Expression Language
  • introducción a la internacionalización de aplicaciones
  • introducción a SiteMesh - Patrón Filtro Decorador
  • introducción a Hibernate "con XML"
  • introducción a Spring
  • introducción a DI - Inyección de Dependencias
  • introducción a JSF Java Server Faces

Acceso a Base de Datos. Hibernate (42 Horas)
  • Persistencia de Objetos
  • Configuración de Hibernate
  • Introducción a un proyecto con Hibernate
  • API
  • Propiedades De Hibernate
  • HQL - Hibernate Query Language
  • Hibernate Criteria Query
  • Persistencia De Colecciones

Desarrollo Aplicaciones De Negocio Enterprise JavaBeans (73,50 Horas)
  • Análisis de los componentes EJB
    • Session Beans.
      • stateless
      • statefull
    • Entity Beans.
    • MDB.
  • ciclo de vida y contextos de EJB
  • Uso del lenguaje de consulta de EJB (EJB QL)
  • Implementación de transacciones
  • Manejo de excepciones
  • Implementación de la seguridad
  • introducción a JBoss Seam como herramienta de integración de JSF y EJB


lunes, 4 de mayo de 2009

Día 59: ANT y Ejemplos JBoss-seam

Instalar ejemplos del seam

Abrir el documento "seam_reference.pdf" para tenerlo de referencia.
Mirar el capítulo 1 para lanzar los ejemplos.
Crear un proyecto de la fuente del jboss seam "jboss-seam-2.1.1.GA" para tener todo el código fuente de los ejemplos a mano.

Ejemplo 1
Desplegar el ejemplo registration
Configuraremos las propiedades del ANT

Desplegamos la carpeta "examples" y dentro el "registration" para acceder al archivo "build.xml" (o control+mayuscula+r y buscamos build.xml), aunque en realidad lo mejor es abrir el plugin de ANT (window>show view>Ant) y arrastrar el archivo a él. Trabaja también con el build.xml principal contenido el build y también utiliza un archivo properties.
El archivo "default.build.properties" contenido en el "build". Modificamos la propiedad jboss.home y le indicamos donde tenemos nuestro servidor (en mi caso: C:\Documents and Settings\javaape\Escritorio\JAVA\servers\jboss-4.2.3.GA )
(Si quisieramos arrancar el método principal del ANT nos iriamos a la carpeta del build.xml por consola y escribir "ant deploy".)
Hacemos doble click en el método principal y debería funcionar todo.
Arrancamos el servidor jboss.
Accedemos a la página "http://localhost:8080/seam-registration/register.seam" y debería ir.

Los JSF tienen el faces-config.xml
Los JPA tienen el persistence.xml
Y Los The Seam component deployment descriptor el components.xml

Ejemplo 2
Ahora desplegaremos el blog, hacemos como antes:
"Tiramos" el build.xml a la vista del ANT y arrancamos el método deploy.
Y si tenemos el jboss ya arrancado directamente podemos acceder ya al ejemplo: "http://localhost:8080/seam-blog/"
Una vez accedido a la página vamos "bicheando" un poco sobre su funcionamiento mirando sus clases java y sus archivos de configuración.

Sobre el ANT
Si se desarrolla lo ideal es hacer un explode, para que los cambios se guarden, pero si queremos lanzarlo tenemos que deshacer el explode y hacer un deploy.

Ejemplo 3
Desplegamos el ejemplo "booking" y los mismos pasos que antes.
Para acceder a él: "http://localhost:8080/seam-booking/home.seam"
Aqui se pueden ver y retomar conversaciones, por ejemplo si se está mirando en una pestaña un hotel y en otra pestaña otro hotel y podemos elegir entre los dos.


El resto del tiempo de hoy lo dedicamos de forma libre: a continuar con el proyecto que teniamos entre manos antes de feria.. o investigar un poco estos ejemplos del jboss y tocarlos.

Consejo:Para los tipos de datos que estamos más acostumbrados, String, Objeto X, Objeto Y, usamos los métodos "getLoQueSea" o su "set" pero para los tipos primitivos de datos, por ejemplo un booleano, se debe de usar "isAlgo"

viernes, 24 de abril de 2009

Día 58: EJB y JSF (16ªP) / JBoss-Seam (9ºP)

En la página del login el seam ya tiene preinstalado unos componentes. Los campos de texto usa "credentials" y el chekbox y el botón de "Identity".
Identity es de sesión
Credentials es de evento


@Out



Consejos:
Los EntityManager no funcionará nunca si una clase no es un EJB


---Entrada incompleta---

jueves, 23 de abril de 2009

Día 57: EJB y JSF (15ªP) / JBoss-Seam (8ºP)

Proyecto final del curso
Hoy comenzamos con el plan del proyecto para la evaluación del curso.

El proyecto consiste en los ejercicios que hemos ido haciendo ultimamente desde hace una semana y pico, pero mejorarlos para que:

Componentes obligatorios:
  • Menu de navegación
  • Mensajes a usuarios
  • Login de consola
  • Gestion de excepciones
  • Consultas JPQL
  • Edición de entidades
Todo esto en las horas de clase, que incluyendo las de hoy hacen un total de 24h.

miércoles, 22 de abril de 2009

Día 56: EJB y JSF (14ªP) / JBoss-Seam (7ºP)

Hoy repasamos los interceptores que dimos el lunes y despues terminamos el ejercicio pendiente.
Sobre todo mirar página 174 del pdf "seam_reference"


Los interceptores sirve por ejemplo para:
La seguridad
Para las estadisticas
Para el Logging

(grafico del cuaderno del dia 56)
En la clase A se crea por ejemplo:

Coche coche = new Coche();
Usuario usuario = new Usuario();
usuario.setCoche(coche);
usuario.arranca();

Un objeto (A) envia un mensaje a otro objeto (B)

Primero crear objeto tipo estadistica. Tiene un objeto tipo disco
despues un objeto disco, la relacion entre ellos es N en estadisticas y en disco 1. Tiene una lista de estadisticas.




lunes, 20 de abril de 2009

Día 55: EJB y JSF (13ªP) / JBoss-Seam (6ºP)

Hoy vamos a realizar una modificación a lo que hemos hecho ya antes y que ahora una entidad tambien cumpla la función de un ejb.



Invocacion = llamar a un método


Mirar página 174 del manual del seam "seam_reference.pdf"


Crear una anotacion.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Interceptors(Espia.class)
public @interface EspiaAnotacion {

}

Si la clase espia detecta que el usuario no esta logueado lo redigirá a la pagina del login.

import org.jboss.seam.Component;
import org.jboss.seam.security.Identity;
Identity identity = (Identity) Component.getInstance("org.jboss.seam.security.identity");
boolean isloggedIn = identity.hasRole("admin");


viernes, 17 de abril de 2009

Día 54: EJB y JSF (12ªP) / JBoss-Seam (5ºP)


Ejercicio1
El objetivo del ejercicio de ahora es, que modificando el ejercicio de ayer, que el enlace de edición vaya a una acción de un ejb y que esa acción rellene un objeto de tipo Disco gracias a un componente, una clase, que hemos creado que se enlaza a la lista, y que nos rediriga a la página de edición simplemente llamando a su url, sin ninguna acción más ya que el disco ya lo tiene.
  • Duplicamos los bean (y sus interfaces): ListaDiscoBean y EditaDiscoBean y en los xhtml igualmente pero en el de lista de disco quitamos el parametro al s:link, o mejor dicho... quitamos el s:link completo y usamos mejor un h:commandButton o un h:commandLink con la acción redirigiendola a "EditaDiscoBean2"
  • Creamos una clase java, que se llame "MiComponente" con una anotación anteponiendo la clase: "@Name("miComp")".
    Le añadimos como atributo: "HtmlDataTable tabla" con sus métodos getter y setter y creamos su método principal:
    public String selecciona(){
    Object o = tabla.getRowData();
    Disco d =(Disco) o;
    return null;
    }
  • Creamos ahora el ejb con la acción que estaba enlazada la lista con el "editar"
    Lo nuevo en esta clase es que hay un objeto del tipo componente que hemos creado antes y con una anotación que lo hace dependiente:
    @In(value="miComp",create=true)
    MiComponente miComponente;

    Y su método principal:
    public String selecciona(){
    disco=(Disco) miComponente.getTabla().getRowData();
    System.out.println(">>>>>>>>>Nombre del disco: "+disco.getNombre()+"!!!!!!!!!!!!!!!!!!");
    return "/editaDisco2.xhtml";
    }

    El return puede devolver directamente la url o podria devolver un valor y poner una regla de navegación en el "pages.xml"
  • Para que a la hora de probar los enlaces la consola no se nos vaya disparada por las consultas sql que se nos muestra editaremos el archivo "persistence.xml" usando el buscador de archivos del eclipse y editamos la propiedad "hibernate.show_sql" a false

Ejercicio2
El objetivo de este segundo ejercicio es el de hacer lo mismo pero con las clases que creamos hace unos dias, específicamente con la clase "Cliente"
Hacer una lista de clientes, que haya un enlace y que se pueda editar.
Como "novedad" usaremos el mismo componente, así que simplemente duplicamos los métodos que nos hagan falta pero para la clase Cliente

Pseudo-Ejercicio3
Bueno, esto es ya a modo personal, no me enteré bien en su día y no lo llegé a hacer pero hoy si me he enterado y lo he hecho.
El objetivo del ejercicio es que a la hora de editar un disco también aparezca un menú desplegable para cambiarle su autor y que se guarde.
Podemos cojer el ejercicio 1 de hoy y mejorarlo con esto.
  • La clase "ListaDiscosBean2":
    • Añadir un nuevo Query en el método de carga que seleccione todos los cantantes.
    • Añadir también una lista de cantantes y su método getter y "subirlo" a la interfaz.
  • La página "listaDiscos2.xhtml":
    • Añadir a la tabla una columna nueva para ver el nombre del cantante (para comprobar que se ha guardado): #{d.cantante.nombre}
  • La página "editaDisco2.xhtml"
    • Añadir el select teniendo cuidado al nombre de la variable que le pongamos para mostrar la lista.
    • Primer nivel// h:selectOneMenu value="#{editaDisco2.disco.cantante}" required="true"
    • Segundo nivel// s:selectItems value="#{listaDiscos2.listaCant} var="_cantante" label="#{_cantante.nombre}" noselectionlabel="#{Selecciona cantante}" \\ cierre
    • Segundo nivel// s:convertEntity \\ cierre
    • \\cierre del primer nivel
  • En la clase persistente "Cantante" añadir el Hashcode y el equals


Consejo:
No nos olvidemos del atajo de eclipse: Control+Shift+R para buscar un archivo que no sepamos donde está!!!

jueves, 16 de abril de 2009

Día 53: EJB y JSF (11ªP) / JBoss-Seam (4ºP)

Cambio de JBoss 5.0 Server a JBoss 4.2 Server

Al comenzar el día lo primero que hicimos fue cambiar la versión del servidor JBoss ya que la versión 5 que hemos estado utilizando presenta muchos fallos y mucho coñazo a la hora de los errores y de intentar arreglarlos.
Para cambiarnos de servidor con el proyecto que estamos usando ("seamcea") lo copiamos a JAVA/servers (que lo pusimos en el escritorio) y en el eclipse creamos un nuevo servidor desde la pestaña de servidores, se selecciona el directorio y lo reconocerá, también habrá que añadirle el proyecto y lo más importante el archivo .xml que es el datasource.
Con el servidor bien puesto ya solo hace falta configurar el proyecto al servidor para ello botón secundario encima del proyecto principal, propiedades y "Targeted Runtime" y marcaremos la versión del nuevo jboss.

Un modelo se carga a traves de acciones.
Una acción la llamamos de 2 maneras, desde el pages.xml que se llamara la accion cada vez que recargemos la pagina y a traves de un s:link que es solo 1 vez.
En el pages.xml podemos tener una condicion para limitar la carga.
La vida (SCOPE) de un modelo:
  • Por ahora usamos la vida de sesion.
  • Tambien existe de por conversacion o tarea del usuario.
    Si por ejemplo pulsamos en un enlace para editar algo es una tarea y se guarda ahi. La ventaja seria tener varias ventanas y cada ventana una tarea y varias tareas a la vez. Otra ventaja es la limpieza, que una vez terminemos con nuestra "conversacion", nuestra tarea, llamamos al método con la anotación @End y todo lo que conlleve la conversación se limpiará, se quedará a nulo.
    Tampoco hay que olvidarse de poner una etiqueta (Anotacion) nueva @Begin en el/los método/s principal/es (el de cargar o buscar algo), solo funcionara si es de tipo conversación. Después del @Begin hay que añadir un "join=false" si no queremos que las conversaciones se pisen (que abramos una segunda ventana para editar un segundo disco y cuando editamos el primero, éste pise al segundo.)
    La etiqueta @End se pondran en el/los metodo/s que termine/n la conversación/es.


Ejercicio:
Cambiar el scope del ejercicio de ayer de sesion a conversación y probar si funciona y añadir el @Begin con el join.

Para validar un calendario
rich:calendar value=... validator="#{bean.valida}"

@Name("bean")
public class MiBean{
public void valida(FacesContext fc, UIComponent ucom,Object o) throws exception{
Date fechaSel=(Date) o;
if(fechaSel) throw Excetion();
}
}


Para validar un input text cerramos la etiqueta a parte y como cuerpo le ponemos una etiqueta del tipo f:validate


miércoles, 15 de abril de 2009

Día 52: EJB y JSF (10ªP) / JBoss-Seam (3ºP)

Hoy comenzamos con un repaso al JPA (lo de las clases persistentes) porque según una encuesta al principio de la clase es lo que más cuesta.

Ejercicio:
El objetivo del ejercicio es realizar más clases persistentes y que se reflejen en la base de datos sin problemas.

  • Primero creamos una clase "Cliente"
    • Debe tener precediendo el nombre de la clase las anotaciones @Entity y @Table(name="clientes") (Puse el nombre de la tabla en plural porque ya existía una del mismo nombre y así en el resto de clases de este ejercicio)
    • La clase debe implementar la clase "Serializable"
    • Crear un atributo de tipo "Long" que es el "id", un atributo "String nombre" y un conjunto de pedidos "Set pedidos"
    • Crear sus getter y setter y precediendo a los getter añadir unas anotaciones:
      • Método getId: @Id y @GeneratedValue
      • Método getPedidos: @OneToMany(mappedBy="cliente"), la tabla clientes estará relacionada con la tabla pedidos como 1-n
      • El resto de métodos: @Column
  • Después creamos la clase "Pedido"
    • Igualmente que en la clase "Cliente" y el nombre de la tabla será "pedidos"
    • Los atributos son "Long id", "Date fecha", "Cliente cliente" y "Set lineas"
    • Las anotacciones encima de los getter:
      • Método getId: @Id y @GeneratedValue
      • Método getCliente: @ManyToOne, y así terminamos la relación con la tabla cliente.
      • Método getLineas: @OneToMany(mappedBy="pedido"), la tabla pedido se relaciona con la tabla lineapedido como 1-n
      • El resto de métodos: @Column
  • Por último creamos la clase "LineaPedido"
    • Lo mismo que en las anteriores y el nombre de la tabla es "lineapedidos"
    • Los atributos son "Long id", "Integer cantidad", "Pedido pedido",y "Disco disco"
    • Las anotaciones encima de los getter:
      • Método getId: @Id y @GeneratedValue
      • Método getPedido y método getDisco: @ManyToOne, ya que la tabla lineapedido termina la relación con pedido y también con la tabla disco (que ya esta creada de ejercicios de días anteriores y que se debe crear en la clase "Disco" su atributo lineas que es un conjunto de LineasPedido y sus métodos y su @OneToMany)

Ejercicio 2:

Lo de ahora consiste en mostrar una lista de discos, con un enlace cada uno y que cada enlace rediriga a una página para editar el nombre del disco.

Editar fecha usando rich:calendar (La fecha situada en el disco) y la fecha nueva que no sea posterior a la fecha de hoy.
Menu desplegable, grupo de musica, discos.

Modelo de rich calendar
Para añadir un calendario teniendo de base la fecha del objeto:
rich:calendar value="#{editaDisco.disco.fecha}" popup="false" datePattern="YY-MM-dd HH:mm" cellwidth="24px" cellHeight="22px" style="width:200px"/

Para añadir un desplegable:
h:selectOneMenu value="#{editaDisco.disco.cantante}"
s:selectItems value="#{listaCantantes.lista}" var="cantante" label="#{cantante.nombre}" noselectionlabel="Selecciona Cantante..."/
s:convertEntity/
/h:selectOneMenu

martes, 14 de abril de 2009

Día 51: EJB y JSF (9ªP) / JBoss-Seam (2ºP)

Una de las cosas buenas de lo que estamos haciendo ahora es que antes hacíamos los mapeos mediante archivos xml y ahora usamos anotaciones.

Spring vs EJB (Seam)


Ejercicio:
Terminamos el ejercicio de ayer pero con la añadidura que ahora pasemos a editar.
Repaso todos los pasos para hacer el ejercicio hasta la edición.
El objetivo del ejercicio completo es crear una página que introduzcamos el nombre de un cantante y nos aparezca una tabla con la lista de discos que tiene y en la tabla haber un enlace que rediriga a una página que lo edite y ahí editar el nombre del disco y que permanezca en la base de datos el cambio.
Pasos:
  1. Crear una interfaz y una clase que implemente algunos métodos como:
    • String begin() con una anotación @Begin precediéndolo con un log.info marcando el inicio de la conversación.
    • String end() con una anotación @End precediéndolo con un log.info marcando el fin de la conversación.
    • void destroy() con las anotaciones @Destroy y @Remove precediéndolo.
    • String increment() que será el método principal para buscar un disco dado un nombre aportado por el formulario, para ello crearemos un query usando un entityManager (que debe de tener la anotación @PersistenceContext) y también una lista simple para recojer todos los discos que devuelva la consulta con sus métodos get..() y set..() que también deben de estar en la interfaz.
  2. En la clase implementación no se nos debe olvidar poner el estado y el nombre para ello usaremos las anotaciones @StateFul y @Name("cantante")
  3. Crear un ".xhtml" que será la vista y que nos muestre el formulario inicial para buscar un cantante y que después también nos mostrará la tabla con los discos del cantante.
    Para el formulario de búsqueda del cantante:
    • Primero usamos un encabezado h1 poniendo la propiedad de la clase implementación que queramos mostrar, por ejemplo el nombre, que creamos un String nombre en la clase con sus get y set: #{cantante.nombre}
    • Colocamos la entrada de texto usando h:inputText y de valor la misma propiedad
    • Finalmente colocamos un h:commandButton que es el encargado de asociar el valor del formulario con la acción de la clase. En el botón usaremos el action="#{cantante.increment}" y ya debería encontrarnos y mostrarnos de forma simple el cantante que queramos.
    Para mostrar la lista de discos del cantante:
    • En la misma página usaremos un h:dataTable de valor la propiedad de la clase que hicimos que era una lista simple: value="#{cantante.resultados}" y nombramos una variable para acceder a él: var="discos"
    • En la tabla, antes de cerrar la etiqueta, colocamos las columnas que queramos mostrar, el nombre del cantante, el id, el nombre y un enlace especial para la edición del disco que queramos. h:column>#{discos.cantante.nombre}<
    • El enlace sería usando la etiqueta s:link y la acción es la de una clase que tendremos que hacer que sería el método principal para mostrar el disco seleccionado y un view="/editaDisco.xhtml" que redirigirá a una nueva página.
    • Antes de cerrar el enlace usamos una etiqueta f:param de nombre id y de valor discos.id, que lo que hará es pasar el id del disco por parámetro para que la página de edición encuentre el disco marcado.
  4. Creamos una interfaz y su implementación y pondremos casi los mismos métodos, no los mismos, el principal seria inicia() y otro secundario guarda()
    • El método inicia() usa un log.info("") para saber que va bien y guardamos en un objeto de tipo Disco el resultado de este método: entityManager.find(Disco.class,id); que lo que hace es devolver un objeto de tipo Disco dado un id, que es el id que pasamos antes por enlace.
    • El método guarda() simplemente llama al método merge() del entityManager metiendole el disco para que se guarde en la base de datos.
  5. Para la vista crearemos la página editaDisco.xhtml con un inputText y un commandButton al mismo estilo como hicimos en la otra vista.



En el resto del día hicimos ejercicios parecidos.

lunes, 13 de abril de 2009

Día 50: EJB y JSF (8ªP) / JBoss-Seam (1ºP)

JBoss-Seam
Para facilitar EJB
Utiliza ANT

Más información AQUÍ

Lo utilizaremos para facilitarnos el desarrollo de proyectos que utilicen JSF y EJB

Primer proyecto seam
Creamos un nuevo proyecto, de tipo "seam web project"
Lo llamaremos "seamcea"
De target runtime seleccionamos un servidor de aplicaciones "JBoss 5.0 Runtime"
Y en configuración el Seam 2.1 y "Next >"
Nos saltamos las dos siguientes con "Next >"

En Seam Runtime le añadimos el seam que nos daron que hemos copiado en el workspace (jboss-seam-2.1.1.GA)
Seleccionamos el despliege de tipo EAR = EJB
Seleccionamos la base de datos y le añadimos un nuevo perfil de conexión. A la altura de los "Drivers" pulsamos el botón "New Driver definition". En Name/Type seleccionamos el mysql versión 5 y en el jar lo borramos y buscamos el que tiene el JBoss (el servidor) en default/lib y al aceptar le decimos que base de datos acceder su contraseña y demás.
Después de terminar el perfil de conexión marcamos la 2ª casilla que recree la base de datos.
Cambiamos el nombre de los paquetes que queden de tal manera "es.cea.seamcea.session", "es.cea...."
Y ya estará.

Se crearán 4 proyectos que son en realidad el mismo. El proyecto principal ya se autopublicará en el servidor JBoss y para que a la hora de que se publiquen cualquier cambio que hagamos hacemos doble click en el servidor y en "publishing" le decimos que revise si hay cambios a cada segundo.

Dentro del proyecto "seamcea-ejb" en el sourceFolder ejbModule en el paquete que tiene le damos boton derecho, Seam Action y creamos una nueva acción "miAccion" de método "saluda" y de página "bienvenida".
Con esto se creará de forma automática una acción con su bean y un xhtml que muestra una página de bienvenida con un botón que muestra una cadena al pulsar.
Para practicar un poquito duplicamos el método de "saluda()" y lo renombramos a "despedida()" tanto en la implementación (MiAccionBean) como en la interfaz (MiAccion) y añadimos un nuevo CommandButton en "bienvenida.xhtml"

De ahora en adelante una acción es una clase sin estado "Stateless". Nos crea una interfaz local con un EJB y su página.
Una clase con estado (Statefull) se le llama conversación.

En el proyecto "seamcea-ejb" creamos una nueva conversación y lo llamamos contador. Con esto hará lo mismo que antes pero hay que comenzar incrementar lo que se quiera y terminar.

El servidor jboss se encarga de mantener vivo un componente con estado para que cada usuario tenga el suyo mientras que uno sin estado lo crea y destruye. Los con estado ya son serializables.

Una clase con estado debe de ser serializable, con la anotación Destroy y Remove.
Existen varios estados: De Evento, de página, de conversación y de sesión.
Estos estados se pueden especificar con la anotación "@Scope(ScopeType.X)"

Borramos la librería de discografica-hibernate de la carpeta "deploy" del JBoss y copiamos el paquete "com.enjava.discografica.model" al source folder del proyecto ejb del que estamos trabajando.
Borramos las líneas de las propiedades de catalogo y de esquema en persistence.xml y realizamos un full publish.

Ejercicio:
El objetivo del ejercicio es hacer lo mismo de antes, crear un bean con una acción y una página, pero en vez de forma automatizada, hacerlo de forma manual.
Pasos:
  • Crear la interfaz con las cabeceras de los métodos. No nos olvidemos de los métodos "begin", "end" y "destroy" con las anotaciones @Begin, @End y "@Destroy @Remove" que son esenciales (sobre todo el último método) para el funcionamiento de todo.
  • Implementar la interfaz. Crear un método "increment" que incremente un valor y mediante un query que consulte un nombre dado en la tabla cantantes.
  • Crear la página .xhtml mostrando los datos.


viernes, 3 de abril de 2009

Día 49: JSF (7ª parte)

Modelo de objetos -> JSF -> web - ...html

binding: es cuando una etiqueta de un archivo .xhtml, un jsf, está representado en el código java de una clase.

Hoy empezamos con un ejemplo de "bindeo" de una página xhtml con una clase java y que al rellenar el formulario ocurría una acción que se mostraba en la página.
  • Primero crear un archivo .xhtml, que lo llamaremos "ejemplo.xhtml"
  • Incluir en un formulario una etiqueta outputText, inputText y commandButton
  • En cada etiqueta que estará asociado a un objeto le añadimos una propiedad a la etiqueta que es "binding" y la asociamos al nombre del objeto de la clase que esté.
  • Les añadimos un value y debería quedar tal que así: "h:commandButton binding="#{ejemploAction.miBoton}" action="#{ejemploAction.pulsar}" value="No me toques!""
  • Crear la clase "EjemploAction" que será la que contenga las acciones y los elementos del formulario.
  • Cada elemento estará asociado a un objeto, por ejemplo el "commandButton" de antes: "HtmlCommandButton miBoton;" y tendrá un método llamado pulsar que gestionará los objetos del formulario.

Eventos en JSF
ActionEvent -> Cuando una acción ocurre. Propiedad en las etiquetas CommandButton: actionListener
ValueChangeEvent -> Cuando un valor cambia.
Propiedad en las etiquetas: valueChangeListener

jueves, 2 de abril de 2009

Día 48: EJB (7ª Parte) y JSF (6ª parte)

Si queremos inyectar un valor de un parametro hacemos lo de siempre pero con el value de tal forma: "#{param.id}" (id, por ejemplo)

Hoy continuamos con los ejercicios de siempre y esta vez que haya un buscador de canciones dado un disco además de que en la tabla que aparezca de los resultados nos muestre un enlace especial de tipo "h:commandLink" que haga una acción y que se muestren los detalles de la canción.

miércoles, 1 de abril de 2009

Día 47: EJB (6ª Parte) y JSF (5ª parte)

Siempre que hagamos algún cambio en nuestros proyectos de JSF, EJB o JPA debemos hacer en la consola "mvn clean install"

Formulario de busqueda de disco por nombre. Llama a una página que muestra los datos del disco encontrado.
Formulario por nombre del disco y nombre del autor.

Antes de acabar la clase: hacer pruebas en aislamiento en el EJB, en el JPA y en el JSF y usando el mockito.


Hoy terminamos el ejercicio que dejamos ayer pendiente sobre la búsqueda del disco y del cantante.
Este ejercicio lo hice a mi manera y me funciona, pero se puede hacer de otra manera.
Los pasos para que funcione son los siguientes:

JPA (Java Persistence API) >Usado en el proyecto
"discografía-hibernate" // Saber Más
  • Tener la clase "Disco" creada implementando "Serializable" con sus parámetros: id, nombre, cantante (de tipo Cantante) y canciones (Conjunto de Canciones) con sus anotaciones "@Entity" y "@Table" al comienzo de la clase y las anotaciones "@Id" y "@GeneratedValue" en el método getter del Id y "@Column" en los getter del resto de parámetros.
  • Tener la clase "Cantante" creada, implementando también "Serializable" y sus parámetros son: id, nombre y discos (Conjunto de Discos) y con las mismas anotaciones de "Disco"
  • Vamos a la consola y limpiamos del repositorio el proyecto y lo volvemos a instalar introduciendo el comando mvn clean install (C:\workspace\discografica-hibernate>mvn clean install)

EJB (Enterprise JavaBeans) >Usado en el proyecto "ejbProject" // Saber Más
  • Primeramente debemos tener creada la interfaz "DiscograficaDAORemote" encabezando los métodos para buscar un cantante introduciendole un nombre y devolviendo un "Cantante" y otro método para buscar un disco que le introducimos el nombre del disco y el nombre del cantante y devolviendo un "Disco"
  • Creamos la clase "DiscograficaDAO" que implemente la interfaz "DiscograficaDAORemote" y rellenando los métodos de búsqueda.
    El método para buscar el cantante quedaría así:
    • Query query = entityManager.createQuery("" +
      "from Cantante ca where " +
      "ca.nombre=:nombre");
      query.setParameter("nombre", nombre);
      try{
      Cantante resultadoConsulta = (Cantante) query.getSingleResult();
      return resultadoConsulta;
      }catch (NoResultException e) {
      e.printStackTrace();
      return null;
      }

    El método para buscar el Disco quedaría así:
    • Query query = entityManager.createQuery(""
      "from Disco d " +
      "where d.nombre=:nombreDisco and " +
      "d.cantante.nombre=:nombreCantante");
      query.setParameter("nombreDisco", nombreDisco);
      query.setParameter("nombreCantante", nombreCantante);
      try{
      Disco resultadoConsulta = (Disco) query.getSingleResult();
      return resultadoConsulta;
      }catch (NoResultException e) {
      e.printStackTrace();
      return null;
      }
  • Vamos a la consola, en este proyecto y realizamos un "mvn clean install"

JSF (JavaServer Faces) >usado en el proyecto "jsf1" // Saber Más
  • Primero creamos un archivo ".xhtml" en "src/main/webapp" que será el que muestre un formulario de la búsqueda. Hacemos 2 formularios con distintos id.
    Formulario 1:
    • Usando la etiqueta de jsf "h:inputText" le introducimos un valor "#{busquedaBean.cantante.nombre}" que lo que hace es rellenar una propiedad de una clase llamada "BusquedaBean" y que el campo sea requerido y al final un "h:commandButton" de action: "#{busquedaAction.busca1}" que lo que hará será llamar un método de una clase llamada "BusquedaAction"
    Formulario 2:
    • Lo mismo que el primer formulario pero que introduzca el nombre del disco.
  • Creamos una clase llamada "BusquedaBean" que tenga como atributos cantante (de tipo Cantante) y disco (de tipo Disco) con sus métodos getter y setter.
  • Creamos una clase llamada "BusquedaAction" que será la que enlazará con el EJB DiscograficaDAO y sus métodos.
    Añadimos un método que será el que recoja de forma remota la clase DiscograficaDAO, lo hacemos método porque el código es algo engorroso y feo:
    • private DiscograficaDAORemote getDiscograficaDAO() throws NamingException {
      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("DiscograficaDAO/remote");
      DiscograficaDAORemote discograficaDAORemote = (DiscograficaDAORemote) PortableRemoteObject
      .narrow(ref, DiscograficaDAORemote.class);
      return discograficaDAORemote;
      }

    Creamos los métodos que llaman los formularios que a su vez llaman a los métodos que creamos de búsqueda en el EJB DiscograficaDAO
    También tendrá como atributo la clase "BusquedaBean" que creamos antes y que usaremos aquí. Por ejemplo el método para buscar un cantante:
    • public String busca1(){ //Buscar el cantante
      DiscograficaDAORemote discograficaDAORemote;
      try {
      discograficaDAORemote = getDiscograficaDAO();
      } catch (NamingException e) {
      throw new RuntimeException(e);
      }
      Cantante cantante = discograficaDAORemote
      .buscaCant(busquedaBean.getCantante().getNombre());
      if(cantante!=null)
      return ("cantanteEncontrado");
      else
      return("cantanteNEncontrado");
      }
  • Lo siguiente sería enlazar y asignar un nombre al Bean y a las acciones y que el formulario de la página lo use. Para ello tenemos que editar el archivo de configuración "my-config.xml" situado en "src/main/webapp/WEB-INF"
    • Añadimos una etiqueta "managed-bean" y le asignamos un nombre "busquedaBean", seleccionamos la clase (en cuál paquete está ubicado y el nombre de la clase) y que tenga un tiempo de vida de tipo petición.
    • Hacemos de nuevo lo mismo pero de nombre "busquedaAction" y le añadimos una propiedad (managed-property) que de nombre es el bean (busquedaBean) y de valor (value) sera "#{busquedaBean}". Con esto lo que estamos haciendo es que se inyecte la clase bean en la clase de la accion ya que necesitamos de ella.
  • En este proyecto no hace falta hacer la instalación


Ejercicio
Ampliamos nuestro ejercicio y esta vez en vez de solamente hacer una búsqueda que borre y guarde en la base de datos.

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.

martes, 10 de marzo de 2009

Día 39: Más ración de Spring

Información varia sobre lo último que hemos hablado:
Los EJB necesitan un contenedor de aplicaciones. Las clases tenían que heredar de una clase padre. Tenían muchos archivos de configuración xml. Todo esto hace la programación algo pesada.
El Spring hace una inyección de dependencias mediante xml. Aplicar interceptores, que son como los filtros cuando usábamos los servlet.

Ejercicio
Guión:
Añadir al formulario web del libro un campo género para introducirlo y modificar el archivo libroEditAction.

Pasos:
  • Primeramente editamos la acción "libroFormAction.java" añadiendole una lista de géneros, sus métodos getter y setter y preparándolo en el método "execute()"
  • En el "libroForm.jsp" añadimos el campo "select" para que se muestre el listado de géneros.
  • En "libroEditAction.java" creamos el objeto Genero y sus métodos getter y setter además del indentificador de éste. También inicializamos el objeto género para que luego el siguiente jsp lo recoja y lo muestre.
  • En "libroEdit.jsp" añadimos el campo del género para que se muestre.

lunes, 9 de marzo de 2009

Día 38: Struts2, Spring e Hibernate

Struts 2

Deja de haber un struts-config para ahora ser un struts.xml y su ubicación también cambia y pasa de estar en el WEB-INF a estar en el src/main/resources.
En el archivo "struts.properties" se puede cambiar por dónde escucharán las acciones en el campo "struts.action.extension".
En el archivo "applicationContext.xml" podemos ver el primer uso de spring.
En las etiquetas "bean" lo que hace es como en java crear objetos, por ejemplo "bean id="helloWorldAction" class="es.cea.HelloWorldAction" singleton="false""
Tambien tiene sus propias versiones a los "getters y setters" con los "property" y sus "value"

Ejercicio
El ejercicio consiste en la creación de un nuevo formulario sobre un libro, que introduzcamos el título del libro y su referencia y después el formulario se enviará a editLibro.action que aparezcan los valores en pantalla.

Para que el ejercicio funcione correctamente debemos hacer lo siguiente (se puede variar el orden, así es como yo lo hice):
  • Primeramente crear el Action, que tenga de valores el título y la referencia.
    Colocar antes de la clase la anotación "@Validation".
    Introducir sus métodos getters y setters.
    Introducir antes de cada getter y setter de cada campo la anotación de validación. "@RequiredStringValidator(...)"
    Y por último el método "execute()"
  • Lo segundo es hacer el primer jsp, poniendo la base del formulario con el s:form y los s:textfield poniendo como "name" el nombre exacto de cada campo del libro que hicimos antes.
  • El segundo jsp pondremos directamente un mensaje diciendo que nuestro titulo y referencia es: y ahí ponemos "s:property" y de "value" el nombre del campo del libro
  • Ahora continuemos con la configuración y funcionamiento interno. Nos vamos a "applicationContext.xml" y abajo del todo haremos un nuevo "bean" de "id" el que queramos y de "class" la clase Action que creamos al principio.
  • En "struts.xml" creamos una nueva "action" de "class" con el mismo nombre que el id que pusimos antes y de "name" el nombre de la acción (que será lo que pondremos en el navegador para acceder a él, yo puse "crearLibro")
    Dentro de la etiqueta "action" ponemos un par de etiquetas llamadas "result", la primera de "name": "input" que será la página de la que enviará el formulario y el otro result, sin "name" será a la que redirigirá.

Con todos estos pasos hechos debería funcionar y a la hora de escribir "http://localhost:8080/struts2/crearLibro.action" debería salir el formulario de entrada y al enviarlo mostrar lo que escribimos.

Spring
El Spring Framework hace de factoría de objetos. Crea los objetos y los contiene además de que lo gestiona.
Como dijimos anteriormente en esta misma entrada:
"
En las etiquetas "bean" lo que hace es como en java crear objetos, por ejemplo "bean id="helloWorldAction" class="es.cea.HelloWorldAction" singleton="false""
Tambien tiene sus propias versiones a los "getters y setters" con los "property" y sus "value"
"
También recibe objetos y es que en vez de usar "value" para introducir una cadena, un valor, a un parametros, usaremos "ref" para referenciar a otro objeto, otro bean.

Conozcamos algo más de spring AQUI

Ejercicio
Crear clases: Coche con marca y Motor con 2 tipos de motor, gasolina y diesel. Creando también sus test y sus respectivos applicationContext.xml

Los pasos del ejercicio serían:
  • Nos creamos dos clases: Clase Motor: contendrá la propiedad Tipo. Clase Coche: contendrá las propiedades Marca y Motor de tipo Motor.
    Creamos sus getter y setters.
  • Creamos un applicationContext.xml nuevo, que lo llamaremos "applicationContextCoches.xml" y crearemos los objetos de tipo Motor y de tipo Coche según Spring. "bean id=motorGasolina class=eticom.di.model.Motor" con un "property name=tipo value=Gasolina" y cerramos el "/bean"
    Haremos lo mismo otra vez pero esta vez de tipo Diesel.
    Con esto lo que hacemos es crear un objeto de tipo motor con el parametro "tipo" (que es String) con el valor que le indiquemos.
  • Hacemos dentro del "applicationContextCoches.xml" los objetos del Coche. "bean id=cocheGasolina class=eticom.di.model.Coche" y sus property "property name=marca value=Ford" y el más importante: "property name=motor ref=motorGasolina" y cerramos el "/bean"
    Con el "ref" lo que hacemos es rellenar la propiedad "Motor" de tipo Motor en el objeto Coche haciendo referencia al objeto que hemos hecho de tipo motor a través de Spring.
  • Creamos un test que compruebe que las marcas, los tipos y demás propiedades sean correctas.
    Para ello debemos tener un método con la anotación "@BeforeClass" que importe el xml del cual podamos acceder.
    Resource resource = new FileSystemResource("src/main/resources/applicationContextCoches.xml");
    factory = new XmlBeanFactory(resource);

    Y en cada método que vayamos a hacer la comprobación haremos:
    Object bean = factory.getBean("motorGasolina");
    En "motorGasolina" pondremos el objeto que queramos recuperar que hizo el spring.


Hibernate

Ejercicio
Guión:
Crear clase género con un ID y un NOMBRE (En el proyecto "libreria-model")
Crear un fichero de mapeo genero.hbm.xml
(el resto es del proyecto "libreria-dao-hibernate-xml")
Incluimos el nuevo mapeo en el fichero de configuración de hibernate hibernate.cfg.xml
Modificamos import.sql
Hacemos una prueba

Pasos:
  • Primeramente creamos un bean llamado genero, con un id y un nombre.
  • Creamos un fichero nuevo de mapeo llamado Genero.hbm.xml que llama a la clase que hemos creado y nombramos la tabla que creará: "generos" además de escecificarle el id y la propiedad nombre.
  • Añadimos una nueva ruta de mapeo en el archivo de configuración de hibernate "hibernate.cfg.xml" que será el archivo que hemos creado de mapeo de generos.
  • Modificamos el import.sql para que añada dos campos nuevos.
  • Creamos un test nuevo para comprobar que nos funciona pero para ello necesitaremos crear un método nuevo en "LibreriaDAOHibernate.java" que devuelva un género dada el id y otro que devuelve una lista de géneros sin decirle nada.


Ejercicio mejorado
Guión:
Relacionar la clase libro con la clase género.
La relación es: un libro tiene siempre un género, un género puede tener 0 o muchos libros.
En genero crear un get libros.
En libro crear el genero, para que haya una relación.

Pasos:
  • Añadimos una propiedad "genero" de tipo Genero en la clase Libro y añadimos en Genero una propiedad "libros" de tipo Set y por supuesto, sus métodos getters y setters.
  • Actualizamos Genero.hbm.xml y Libro.hbm.xml añadiendo las relaciones y valores necesarios.
  • Actualizamos el import.sql
  • No nos olvidemos de actualizar el applicationContext.xml de nuestra aplicación.
  • Actualizar el import.sql de nuestra aplicación.
  • INSTALAR los proyectos que hemos modificado (libreria-model, libreria-dao-hibernate, ....

viernes, 6 de marzo de 2009

Día 37: Ant y Mockito

ANT
Sirve para automatizar las tareas de desarrollo
Las tareas las definimos nosotros en un .xml, cuando en maven ya están predefinidas.

Si queremos probar el ant abrimos la vista de Ant en la opción "Window" en el eclipse.
Recojemos el archivo de configuración xml del ant y lo arrastramos a la ventana de ANT y nos aparecerán los "métodos" que tiene el archivo. Si hacemos doble click en algunos de ellos se arrancará dicho método.

El ant ya tiene propiedades predefinidas a los que podemos acceder mediante ${nombrePropiedad}

Para saber más ir AQUÍ

Ejercicio
El ejercicio consiste en crear una estructura básica de un proyecto vacío usando ant.
Todo proyecto web debe de tener como mínimo la siguiente estructura:






app/WEB-INFclassespaqueteMiClase.class
""/libmiLibreria.jar-
""/web.xml--
"/index.html---
"/index.jsp---
"/css---

El ejercicio sería crear nuevos "target" o "métodos" en el ".xml" del ejercicio "ant-ejemplos" creando la estructura de la tabla, usando también las dependencias (que se llamen los target unos a otros) y usando propiedades del archivo ".properties"

Mockito

Para ver el funcionamiento de un test funcionando bajo mockito copiamos los archivos Primero y el Segundo a

jueves, 5 de marzo de 2009

Día 36: Struts, continuación2 e Hibernate

Hibernate, pequeta introducción
Resuelve uno de los patrones de desarrollo (ORM - Object Related Mapping)
Está entre el modelo de objetos (nuestro programa) y el modelo relacional (la base de datos) y los enlaza. Esto es una nueva capa entre un DAO y una base de datos.
En resumen: un DAO habla con el ORM (el hibernate) y éste se encarga de hablar con la base de datos. La base de datos es indiferente, simplemente le indicamos al hibernate que driver utilizar.
HSQLB, es otro motor de base de datos, tiene gran rapidez y lo tiene el open office.

Para que hibernate relacione cada clase (los modelos) de nuestra aplicación con las tablas de la base de datos necesita haber un archivo xml con la configuración, por ejemplo "Autor.hbm.xml" que le indique cada campo del modelo.

Si quisieramos tener hibernate funcionando en alguna aplicación lo mínimo es:
Un archivo sql: "import.sql"
El archivo de configuración: "hibernate.cfg.xml"
El mapeo de las clases, por ejemplo "
Autor.hbm.xml"
Y la librería del hibernate: "hibernate-core.jar"

Para saber más de Hibernate miremos AQUÍ

Continuación con el proyecto struts-avanzado
Continuamos con la creación, edición y borrado de elementos.


miércoles, 4 de marzo de 2009

Día 35: Struts, continuación

Servidores web java
Pueden ejecutar Servlets y Jsps

Dos servidores web java conocidos son el tomcat y el jetty
El jetty en un servidor web más moderno que tomcat y más liviano.
Una gran ventaja del jetty es que se autoactualiza si realizamos algún cambio, por ejemplo, en algún jsp.
Para arrancar el jetty desde el maven por consola es: "mvn jetty:run" si le indicamos "-war" después del comando descrito antes, creará un archivo ".war" y lo ejecutará pero no se autoactualizará ante los cambios.
Un comando interesante del maven es el "source:jar install" que instala en el repositorio también los archivos source.
El servidor jetty suele dar un error de tipo "PerGem Space" de vez en cuando y para solucionarlo... como todo en la informática, reiniciarlo.

En el Eclipse nos vamos a las preferencias, escribimos "maven" y marcamos las opciones "Download Artifacts Sources" y "Download Artifact JavaDoc"


Ejercicio
El ejercicio de hoy consiste en que la aplicación pueda añadir, modificar o borrar calquier elemento.


Plugin
Es un complemento, una clase java, que se crea al arrancar la aplicación.

Sitemesh
Es una herramienta para embellecer la vista.
Es una librería, una dependencia, hay que implementarlo en el xml.
También se tiene un .xml que se llama "decorators.xml" que se encarga de redistribuir la información de nuestras páginas según una plantilla llamada "layout.jsp", aunque claro, todo se puede personalizar y cambiar.

martes, 3 de marzo de 2009

Día 34: Struts

STRUTS

Recordamos en esencia qué es el struts:
Es un framework de componenetes para desarrollo MVC.

> Para utilizar struts debemos tener su librería en el pom.xml
> Debemos definir un controlador en el web.xml que llamará al servlet "ActionServlet" que contiene los métodos que usará el struts. Añadir que es un controlador frontal que escuchará todo terminado en ".do"
> En el xml de la configuración debe contener un documento descriptor de documentos o DTD y el cual tiene varias versiones.
> Todas las peticiones que sean ".do" deben ser escuchadas por alguna clase que extienda de Action.
> Una acción necesita un formulario para poder manejar sus datos
Un ActionForm puede vivir en el "request" o en el "session"
> Las acciones de Struts nos dejan acceder al "request" y al "response"
> Aquel que necesite algo, la dependencia que necesita de otro, éste se la inyecta.

> Una dependencia es algo de lo que dependemos para realizar cualquier cosa, por ejemplo:
class Servicio{
Calculadora calculadora;
public int suma(int x,int y){
return calculadora.suma(x,y);
}
}
Inyección de dependencias. La idea es crear un objeto para muchos servicios para economizar recursos y no hacer un objeto para cada servicio.
Un ejemplo de inyección:
servicio = new Servicio();
servicio.calculadora = new Calculadora();
servicio.suma(5,6);

Componentes:
Servlet, hace de controlador.
Los TAG son para la vista.
Y los ActionForm hacen la función de modelo.

Proyecto struts-avanzado
JPQL: Java Persistence Query Languaje.

Modificación 1 (Ejercicio 1):
En la página del libro lo que debemos hacer es mostrar un enlace para ver todos sus detalles.
En los detalles del libro debemos añadir un enlace para ver con detalles los datos de su autor y también mostrar sus editoriales y otro enlace para verlos con detalles.
La página de detalles del autor mostrar simplemente sus datos.
La página de detalles de la editorial mostrar sus datos.

Modificación 2 (Ejercicio 2):
Ahora hacer que se puedan ver los capítulos e internacionalizar los textos.
Antes usábamos la etiqueta "fmt:message key=""" pero ahora usaremos "struts-bean:message key=""" ya que el struts se encarga ahora de eso.

lunes, 2 de marzo de 2009

Día 33: Internacionalización y STRUTS

Proyecto i18n
Recojemos del servidor el proyecto i18n y lo colocamos en el workspace, creamos un nuevo proyecto con el mismo nombre y lo abrirá.
Una vez abierto botón derecho, run as, maven build ... y en Goals: "tomcat:run-war"
Ahora podremos acceder al proyecto a la siguiente dirección: "http://localhost:8080/i18n/" y veremos un mensaje de salida que variará según el idioma que tengamos configurado en el navegador.

Ejercicio:
Ampliaremos los idiomas haciendo más archivos ".properties" al italiano.


--- STRUTS ---

Es un framework para desarrollar aplicaciones web a través de servlets.
Los jsp tendrá etiquetas de struts.
Todos los servlets deberían escuchar por un ".do" ya que todo lo que se hace son acciones.
En el archivo struts-config.xml es donde se configuran todas las acciones.
Para más información sobre el struts: Struts

Añadido 1 (Ejercicio1):
Añadiremos un nuevo "forward" que si recibe la petición "conocido" que redirija a un jsp que crearemos ahora: "/usuarioConocido.jsp"
En "SaludoAction" creamos una condicional:
if(saludoForm.getNombre().equals("pepe"))
actionForward= mapping.findForward("conocido");
else
actionForward= mapping.findForward("ok");


Añadido 2 (Ejercicio2):
Un formulario que hereda de LibroForm y que a su vez a ActionForm, el LibroForm es como un bean de libro, con su título y lo que queramos con sus métodos getters y setters.
Una vez que se rellena el formulario y se envía llamamos a la accion libro.do
Tendremos una clase LibroAction que reconocerá el título del libro y llamará a una acción que estará configurada en el archivo "struts-config.xml".
En la acción pondremos que si es un libro Y da error llamando al archivo "errorLibro.jsp" y si el libro esperado X redirija a "libroOk.jsp"

Añadido 3 (Ejercicio3):
La siguiente añadidura consiste en realizar practicamente lo mismo pero con un club.
La idea es que un usuario de nombre X y edad Y no supere los 100 años y ni sea inferior a 18, en ambos casos redirigirán a sus páginas de error y si es entre 18 y 100 que entre en el club.
La página de inicio es "club.jsp" con un formulario de "ClubForm"
El "ClubAction" se encargará de "filtrar" la edad y en la configuración del struts una acción dedicada para el formulario del club y dependiendo de la edad redirigir a una página jsp u otra.

Explicación validación:
En "traducciones.properties" tenemos 2 mensajes de error que son para el ejercicio original cuando un usuario no introduce el nombre y el apellido.
El cómo acceder a ellos, pues es fácil.
Utilizamos la etiqueta "struts-html:errors" con la propiedad "nombre", por ejemplo, aunque esto es simplemente para acceder a una propiedad dentro de un método, el cual está contenido en el "bean" o el xForm.java, que consiste en sobrescribir el método "ActionErrors validate" y realizamos lo siguiente:
if(request.getParameter("nombre")==null || request.getParameter("nombre").equals("")){
actionErrors.add("nombre", new ActionMessage("error.nombreVacio"));
}
Lo que hace es recojer el parámetro "nombre" del formulario de usuario y comprobar que no está vacío y si lo está que acceda al archivo ".properties" al campo "error.nombreVacio" y entonces se mostraría el mensaje, la propiedad de ese mensaje se le llamó "nombre" tal y como dije al principio con la etiqueta del struts de error.