La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Java y Tecnologías J2EE Universidad de Murcia Noviembre 2009

Presentaciones similares


Presentación del tema: "Java y Tecnologías J2EE Universidad de Murcia Noviembre 2009"— Transcripción de la presentación:

1 Java y Tecnologías J2EE Universidad de Murcia Noviembre 2009
Curso Formación del PAS Noviembre 2009 Juan José Meroño Sánchez

2 Contenidos I Objetivos del Curso Herramientas de Desarrollo
Curso de introducción al mundo de Java EE. Dirigido a: Desarrolladores sin experiencia en Java EE. Analistas/Jefes de Proyecto inmersos en proyectos Java EE. Cualquier profesional con ánimo de conocer Java EE. Para saber más: FundeWeb. Herramientas de Desarrollo Nociones básicas de Eclipse. Mención especial a otras herramientas importantes. Lenguaje Java Nociones básicas de POO. Nociones básicas de POA. Nociones básicas de Java y novedades de Java 1.5. Patrones de Diseño Ideas generales de patrones de diseño. Patrones de diseño Web. El Patrón MVC.

3 Contenidos II Arquitectura Java EE Tecnologías Java EE
Modelo de Capas Contenedores y Servicios Java EE Ensamblado y Empaquetado Java EE. Eclipse y Java EE. Tecnologías Java EE Tecnologías de la Vista: JSF y Facelets Tecnologías de Control: EJB Tecnologías del Modelo: JPA Tecnologías Avanzadas Java EE Servicios WEB: JAXWS Autenticación Java EE Portlets El Proyecto del Curso Un periódico digital con teletipo.

4 Herramientas de Desarrollo

5 I. Herramientas de Desarrollo
Multitud de Herramientas Jdeveloper, NetBeans, IntelliJ, Eclipse,… La decisión es clara: Eclipse. Modular y ampliable mediante plugins. Muy utilizada y en constante desarrollo. En realidad todas las citadas tienen gran calidad. Es la que se emplea en FundeWeb. No sólo sirve para desarrollar Java.

6 I. Herramientas de Desarrollo
1.Menu: Incluye todas las opciones del entorno y algunos iconos de acceso directo a las más empleadas. 2.Perspectiva: Permite alternar entre las diferentes perspectivas que haya abiertas. 3.Control Proyecto: Permite controlar el contenido del proyecto, los archivos que lo componen. 4.Editor: La zona más amplia para editar el contenido de los archivos ya sea visualmente o en modo texto. 5.Propiedades: Utilizada en muchas ocasiones para editar propiedades del archivo editado. 6.Control Ejecución: Incluye todo lo necesario para controlar y monitorizar la ejecución de nuestro proyecto.

7 I. Herramientas de Desarrollo
Terminología de Eclipse Espacio de Trabajo: Workspace Directorio en el que se almacenan los proyectos y configuraciones específicas. Se puede cambiar de espacio de trabajo de forma sencilla. Recomendación: No tener todos los proyectos en un ET. Perspectivas Configuración predeterminada de las zonas de trabajo adecuadas para un tipo de tarea concreta: Proyectos Web, Swing, BBDD, etc… Vistas Pestañas que se ubican en las zonas de trabajo y que permiten hacer tareas concretas: Editor, Console, Navigator, Server,… Artefactos de desarrollo: Vistas que nos ayudan a editar el proyecto. Artefactos de runtime: Vistas que nos ayudan a monitorizar y testar el proyecto. Configuración y Actualización de Eclipse Window >> Preferences. Podemos ampliar las funcionalidades del IDE según nuestras necesidades. Help >> Software Updates.

8 I. Herramientas de Desarrollo
Subversion. Eclipse incluye su control de versiones local por sesión, pero no es suficiente. Mediante el plugin “Subclipse”, se incorporan a nuestros proyectos todas las posibilidades del control de versiones. Importante emplear Subversión de forma correcta: Liberar versiones. Emplear comentarios adecuados. Crear ramas.

9 I. Herramientas de Desarrollo
Maven. Gestor de proyectos. Forma de compartir el conocimiento de la metainformación de un proyecto. <project xmlns=" xmlns:xsi=" xsi:schemaLocation=" <modelVersion>4.0.0</modelVersion> <groupId>org.um.atica</groupId> <artifactId>Prueba_Maven</artifactId> <name>Prueba_Maven</name> <version>0.0.1-SNAPSHOT</version> <description>Ejemplo de archivo POM de Maven.</description> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.4</version> <scope>test</scope> </dependency> </dependencies> </project>

10 I. Herramientas de Desarrollo
Maven. Incorporar alguien a un proyecto. Sin Maven Instalación del software. Descarga de fuentes. Descarga de librerías. Configurar la herramienta para compilar y ejecutar. Con Maven Ejecución de tarea maven.

11 I. Herramientas de Desarrollo
Hudson. Servidores de integración contínua. Todas las fases de generación de mi proyecto automatizadas. No necesito personas supervisando tareas automáticas. Servidor de Integración Contínua Repositorio Subversion Desarrollador 1. Commit 2. Update 4. Resultados de la Fase de Test 3. Rehace el Proyecto con Maven

12 I. Herramientas de Desarrollo
Prácticas I Introducción a Eclipse Crea un proyecto Java. Crea dos clases. Cambia la perspectiva entre Java y Resource. Perspectivas Modifica las vistas que aparecen en la perspectiva Resource. Elimina la vista Project Explorer. Incluye la vista Navigator y Package Explorer. Incluye la vista Problemas. Restaura el estado original de la perspectiva. Configuración Modifica aspectos generales del editor, colores, tipos de letra, etc… Amplia la funcionalidad de eclipse con algún plugin.

13 I. Herramientas de Desarrollo
Crea un proyecto Java.

14 I. Herramientas de Desarrollo
Crea dos clases Java.

15 I. Herramientas de Desarrollo
Instalar un Plugin: Subversion.

16 I. Herramientas de Desarrollo
Prácticas II Gestión de Proyectos Modifica las clases Java: Crea un “Hola Mundo”. Compara ambas clases. Incluye tareas pendientes en ambas clases. Visualiza las tareas pendientes. Ejecución de Proyectos Ejecuta alguna de las clases creadas. Incluye puntos de ruptura. Observa las posibilidades del Debug. Compartir Proyectos Comparte tu proyecto en un repositorio. Descarga un proyecto desde el repositorio.

17 I. Herramientas de Desarrollo
Gestionar Proyectos.

18 II. Lenguaje Java

19 II. Lenguaje Java Definición:
“Lenguaje de programación orientado a objetos desarrollado por Sun Microsystems a principios de los años 90. El lenguaje toma mucha de su sintaxis de C y C++, pero tiene un modelo de objetos más simple y elimina herramientas de bajo nivel, que suelen inducir a muchos errores, como la manipulación directa de punteros o memoria.”

20 II. Lenguaje Java Programación Orientada a Objetos Conceptos de Diseño
Clase Definición de propiedades y comportamiento de un tipo. Objeto Instancia de una clase, dispone de unas propiedades concretas. Método Algoritmo asociado a un objeto que se lanza tras recibir un mensaje. Atributo Contenedor de un tipo de dato asociado a un objeto. Notación punto. Mensaje Comunicación dirigida a un objeto. Notación punto.

21 II. Lenguaje Java Programación Orientada a Objetos Sintaxis en Java
public class Triangulo { // Propiedades del triángulo public int base; public int altura; // Métodos del triángulo public float area() { return (base*altura)/2; } } // Ejemplo de Uso Triangulo t = new Triangulo(); t.Altura = 10; t.base = 2; System.out.println(“Area: ”+t.area());

22 II. Lenguaje Java Programación Orientada a Objetos
Conceptos de Análisis Abstracción Características esenciales del objeto. Ocultación Exponer una interface. Encapsulamiento Aumentar la cohesión. Polimorfismo Comportamientos diferentes asociados a objetos diferentes pero con igual nombre. Herencia Las clases se relacionan a través de una jerarquía.

23 II. Lenguaje Java Programación Orientada a Objetos Análisis en Java
Figura abstract float area(); Triangulo float area(); Cuadrado float area();

24 II. Lenguaje Java Programación Orientada a Aspectos Conceptos Básicos
Funcionalidad transversal a implementar. Join Point Punto de la ejecución donde puede conectarse un aspecto. Advice Implementación del aspecto. Pointcut Define los aspectos a aplicar en cada Join Point. Introduction Permite añadir métodos o atributos a clases ya existentes. Target Clase a la que se añade el aspecto. Proxy Objeto creado después de aplicar el aspecto. Weaving Proceso de aplicar aspectos a los objetos.

25 II. Lenguaje Java Programación Orientada a Aspectos: AspectJ

26 II. Lenguaje Java Programación Orientada a Aspectos
Interceptores en Java Una de las formas en las que podemos encontrar este tipo de programación es con los interceptores. Ciertos objetos disponen de un ciclo de vida. Interceptando este ciclo podemos añadir funcionalidad sin modificar el código del objeto. Ejemplo: Auditar los accesos a una aplicación. Se puede hacer interceptando el ciclo de vida de las sesiones del servidor. Añadiendo esta funcionalidad en el evento de creación.

27 II. Lenguaje Java Plataforma Java Ediciones Desarrollo vs Ejecución
Lenguaje: Veremos sus características. JVM: Máquina virtual. API: Biblioteca de librerías. Ediciones Java ME: Micro Edition. Java SE: Standart Edition. Java EE: Enterprise Edition. Desarrollo vs Ejecución JSDK: Kit de desarrollo. JRE: Kit de runtime.

28 II. Lenguaje Java Elementos del Lenguaje Package, Clase
Herencia, Implementación package curso.ejemplos; import curso.interfaces.Dibujable; public class Cuadrado extends Figura implements Dibujable { private int lado; public void dibujar() { … } }

29 II. Lenguaje Java Elementos del Lenguaje Variables
Tipos primitivos: char, byte, short, int, long, float, double y boolean. Objetos y Arrays. El ámbito marcado por los bloques { … }. Accesibilidad: public, protected, private. Ejemplos de declaración: int x; int y=1; Clase c; Clase d = new Clase(); int [] array; int [] array = {1,2,3,4}; Clase [] array = new Clase[] {c,d};

30 II. Lenguaje Java Elementos del Lenguaje Operadores
Aritméticos: +, -, *, /, % Asignación: =, += , -=, *=, /=, %=. Incrementales: ++, --. Relacionales: >, >=, <, <=, ==, !=. Lógicos: &&, ||, !. Cadenas: +. Bits: >>, <<, &, |, ^, ~. Estructuras de Control Comentarios: // y /* … */ Bifurcaciones: if (cond) { … } else { … } Bucles: while (cond) { … }, for (init; cond; inc) { … }

31 II. Lenguaje Java Elementos del Lenguaje Excepciones
Control de errores dentro del propio lenguaje. Implícitas: RuntimeException. Generadas por errores de programación. Explícitas: Resto de Exception. El compilador obliga a chequear estas excepciones. public void ejemplo (String n, String c) throws Exception { try { int num = Integer.parseInt(n); Class.forName(c); } catch (NumberFormatException nfe) { throw nfe; } catch (ClassNotFoundException cnfe) { throw cnfe; } finally { } }

32 II. Lenguaje Java Elementos del Lenguaje Multithreading
Capacidad de ejecución en paralelo. Extender Thread o Implementar Runnable. Arranque y Parada. Suspender y Reanudar. public static void main(String[] args) { HiloThread hil=new HiloThread (); hil.setName(”Hilo 1″); HiloThread hi2=new HiloThread (); hil2.setName(“Hilo 2”); HiloThread hi3=new HiloThread (); hi3.setName(”Hilo 3″); hil.start(); hi2.start(); hi3.start(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { String cmd = br.readLine(); while (!cmd.equals("")) { if (cmd.equals("1")) hil.stop(); if (cmd.equals("2")) hi2.stop(); if (cmd.equals("3")) hi3.stop(); cmd = br.readLine(); } } catch (Exception ex) {} }   public class HiloThread extends Thread {   public void run() { for(int i=0;i<15;i++) { try { this.sleep(500); System.out.println(this.getName()+” en bucle “+i); } catch(InterruptedException e) { System.out.println(this.getName()+” se cayo intentando dormir”); } } }   public class HiloThread implements Runnable { private Thread t; private String name; public HiloThread() { t = new Thread(this); } public void setName(String n) { name = n; } public String getName() { return name; }   public void run() { for(int i=0;i<15;i++) { try { this.sleep(500); System.out.println(this.getName()+” en bucle “+i); } catch(InterruptedException e) { System.out.println(this.getName()+” se cayo intentando dormir”); } } public void start() { t.start(); } 

33 II. Lenguaje Java Elementos del Lenguaje Multithreading
Comunicación entre hilos. public class Contenedor { private int dato; private boolean hayDato = false; public synchronized int get() { if (!hayDato) { try { wait(); } catch (InterruptedException e) { } } hayDato = false; notifyAll(); return dato; } public synchronized void put(int valor) { if (hayDato) { try { wait(); } catch (InterruptedException e) { } } dato = valor; hayDato = true; public class ProductorConsumidorTest { public static void main(String[] args) { Contenedor c = new Contenedor (); Productor produce = new Productor (c); Consumidor consume = new Consumidor (c); produce.start(); consume.start(); } public class Productor extends Thread { private Contenedor contenedor; public Productor (Contenedor c) { contenedor = c; } public void run() { for (int i = 0; i < 10; i++) { contenedor.put(i); System.out.println("Productor. put: " + i); try { sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { } } public class Consumidor extends Thread { private Contenedor contenedor; public Consumidor (Contenedor c) { contenedor= c; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = contenedor.get(); System.out.println("Consumidor. get: " + value); }

34 II. Lenguaje Java Elementos del Lenguaje: Novedades Java 1.5
Tipos Parametrizados Vector<String> v = new Vector<String>(); String s = v.elementAt(0); // No requiere casting. Autoboxing Vector<Integer> v = new Vector<Integer>(); v.addElement(30); // No requiere conversión int – Integer. Bucles Simples for (String c: v) System.out.println(c); Tipo “enum” enum EstadoCivil { soltero, casado, divorciado }; EstadoCivil ec = EstadoCivil.casado; Import Estático import static java.lang.Math; double raiz = sqrt(1245); Argumentos Variables public void miFunc(String p1,int … args) { for (int i:args) { … } } Metainformación Anotaciones

35 II. Lenguaje Java Prácticas I Crea un proyecto Java: Calculadora.
Crea una calculadora para las 4 operaciones básicas. Como interface usaremos los argumentos de entrada. java Calculadora 3 * 5 Maneja las excepciones oportunas.

36 II. Lenguaje Java Crea un proyecto Java: Calculadora.
public class Calculator { public static enum Operador { suma , resta, multiplica, divide }; public static double suma(String a,String b) throws CalculatorError { try { return Double.parseDouble(a)+Double.parseDouble(b); } catch (Exception ex) { throw new CalculatorError("CalculatorError: "+ex.getMessage()); } } public static double resta(String a,String b) throws Exception { return Double.parseDouble(a)-Double.parseDouble(b); public static double multiplica(String a,String b) throws Exception { try { return Double.parseDouble(a)*Double.parseDouble(b); } catch (Exception ex) { System.out.println("CalculatorError en Multiplica."); throw ex; } public static double divide(String a,String b) throws NumberFormatException { try { return Double.parseDouble(a)/Double.parseDouble(b); } catch (NumberFormatException nfe) { throw nfe; } public static Operador aOperador(String op) throws CalculatorError { if (op!=null) { if (op.toLowerCase().equals("mas")) return Operador.suma; if (op.toLowerCase().equals("menos")) return Operador.resta; if (op.toLowerCase().equals("por")) return Operador.multiplica; if (op.toLowerCase().equals("entre")) return Operador.divide; throw new CalculatorError("CalculatorError: Operador incorrecto."); public class Calculadora { public static void main(String[] args) { try { double resultado = 0; switch (Calculator.aOperador(args[1])) { case suma: resultado = Calculator.suma(args[0],args[2]); break; case resta: resultado = Calculator.resta(args[0],args[2]); break; case multiplica: resultado = Calculator.multiplica(args[0],args[2]); break; case divide: resultado = Calculator.divide(args[0],args[2]); break; } System.out.println(args[0]+" "+args[1]+" "+args[2]+" = "+resultado); } catch (Exception ex) { ex.printStackTrace(); public class CalculatorError extends Exception { public CalculatorError(String msg) { super(msg); } }

37 II. Lenguaje Java Prácticas II: El diario digital.
La práctica global del curso consiste en la creación de un Diario Digital. El Diario es un simple listado de noticias, y cada noticia pertenece a una categoría. La portada del Diario estará formada por las noticias de última hora (novedades). Las noticias se componen de un título, una fecha y el contenido. Crea las clases que creas necesarias y una sencilla interface para testarlas.

38 II. Lenguaje Java Prácticas II: El diario digital.
public class Noticia { private int codigo; private String contenido; private Date fecha; private boolean portada; private String titulo; private Categoria categoria; public Noticia() { } public int getCodigo() { return this.codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getContenido() { return this.contenido; } public void setContenido(String contenido) { this.contenido = contenido; } public Date getFecha() { return this.fecha; } public void setFecha(Date fecha) { this.fecha = fecha; } public boolean isPortada() { return this.portada; } public void setPortada(boolean portada) { this.portada = portada; } public String getTitulo() { return this.titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public Categoria getCategoria() { return this.categoria; } public void setCategoria(Categoria categoria) { this.categoria = categoria; } } public class Categoria { private int codigo; private String nombre; private List<Noticia> noticias; public Categoria() { } public int getCodigo() { return this.codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getNombre() { return this.nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public List<Noticia> getNoticias() { return this.noticias; } public void setNoticias(List<Noticia> noticias) { this.noticias = noticias; } }

39 III. Patrones de Diseño

40 III. Patrones de Diseño Definición: Motivación:
“Esquemas predefinidos aplicables en diversas situaciones que garantizan ciertas cualidades al diseño obtenido.” Motivación: Un porcentaje muy elevado de los problemas a los que nos enfrentamos ya han sido resueltos anteriormente por otras personas. “Design Patterns”, Gang of Four, (Erich Gamma, Richard Helm, Ralph Johnson y John Vlisides)

41 III. Patrones de Diseño División GoF
Patrones Creacionales: Abstraer el proceso de creación de los objetos. Abstract Factory, Builder, Factory Method, Prototype y Singleton.

42 III. Patrones de Diseño Abstract Factory: Crear familias de objetos.
DocumentBuilderFactory fac = new DocumentBuilderFactory(); DocumentBuilder builder = fac.newDocumentBuilder(); // Retorna una implementación de Builder Concreto Builder: Simplificar la creación en si. DocumentBuilder builder = fac.newDocumentBuilder(); Document doc = builder.newDocument(); // Retorna un documento vacío Document doc = builder.parse(cadena); // Retorna un documento tras parsear la cadena Abstract Factory: Permite crear un builder diferente según la implementación de XML disponible. Builder: Simplifica procesos de creación complejos para un documento.

43 III. Patrones de Diseño División GoF
Patrones Estructurales: Combinar objetos para crear estructuras de mayor tamaño. Adapter, Bridge, Composite, Decorator, Facade, Flyweight y Proxy.

44 III. Patrones de Diseño Decorator: Añadir funcionalidad a un objeto.
JFrame frame = new JFrame(); frame.getComponentPane().add(JLabel(“Un Texto”)); frame.getComponentPane().add(JLabelConBorde(“Un Texto”)); frame.getComponentPane().add(JLabelResizable(“Un Texto”)); frame.getComponentPane().add(new BorderDecorator(JLabel(“Un Texto”))); frame.getComponentPane().add(new ResizableDecorator(JLabel(“Un Texto”))); frame.getComponentPane().add(new ResizableDecorator(new BorderDecorator(JLabel(“Un Texto”)))); public class BorderDecorator extends JComponent { protected JComponent child; // decorated component public BorderDecorator(JComponent component) { child = component; this.setLayout(new BorderLayout()); this.add(child); } public void paint(Graphics g) { super.paint(g); g.drawRect(0, 0, this.getWidth() - 1, this.getHeight() - 1);

45 III. Patrones de Diseño División GoF
Patrones Comportamiento: Definir interacción entre objetos reduciendo el acoplamiento. Chain of Responsability, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method y Visitor.

46 III. Patrones de Diseño Observer: Patrón muy empleado.
public class ObservableValue extends Observable { private int n = 0; public ObservableValue(int n) { this.n = n; } public void setValue(int n) { this.n = n; setChanged(); notifyObservers(); } public int getValue() { return n; } public class TextObserver implements Observer { public void update(Observable obs, Object obj) { System.out.println(((ObservableValue)ov).getValue()); } public static void main(String[] args) { ObservableValue ov = new ObservableValue(0); TextObserver to = new TextObserver(); ov.addObserver(to); ov.setValue(145); // Este cambio se notifica al Observer

47 III. Patrones de Diseño Patrones Web
Al amparo de los patrones de diseño del GoF aparecen otra serie de patrones específicos del mundo Web. Se distribuyen en tres capas: Presentación, Negocio e Integración. De entre todos los patrones Web existentes el más conocido y empleado es el MVC.

48

49 III. Patrones de Diseño Modelo Vista Control: Descrito en 1979.
Modelo: Representación específica de la información. Vista: Representación del modelo en un formato adecuado para que el usuario interactúe. Control: Responde a la interacción del usuario con la vista provocando cambios en el modelo.

50 III. Patrones de Diseño Modelo Simplificado
public class Cliente extends Observable { private String link = ""; public void link(String l) { link = l; setChanged(); notifyObservers(); } public String getLink() { return link; } public static void main(String[] args) { Cliente c = new Cliente(); c.addObserver(new Server()); // Petición Inicial c.link(“Index"); // Verifico c.link(“Verify"); // Envio Formulario c.link(“Send"); public class Server implements Observer { private boolean enviado = false; @Override public void update(Observable o, Object arg) { String action = ((Cliente)o).getLink(); // Se pincha un enlace if (action.equals(“Index")) { System.out.println("Retorno Página Index !!"); } else if (action.equals(“Send")) { enviado = true; System.out.println("Respuesta de Send !!"); } else if (action.equals(“Verify")) { if (enviado) System.out.println("Send ya ejecutado !!"); else System.out.println("Send no ejecutado !!"); }

51 III. Patrones de Diseño Modelo Simplificado VISTA MODELO
public class Vista { private String text; public Vista(String t) { text = t; } public void send() { System.out.println(text); } } MODELO public class Modelo { private boolean enviado = false; public void setEnviado(boolean enviado) { this.enviado = enviado; } public boolean isEnviado() { return enviado; } public class Server implements Observer { private Control control = new Control(); @Override public void update(Observable o, Object arg) { String action = ((Cliente)o).getLink(); Vista vista = control.doAction(action); vista.send(); } public class Control { private Modelo model = new Modelo(); public Vista doAction(String action) { try { return (Vista)this.getClass().getMethod("do"+action, new Class[]{}).invoke(this,new Object[]{}); } catch (Exception e) { return new Vista("Error: "+e); } public Vista doIndex() { return new Vista("Retorno Página Index."); public Vista doSend() { model.setEnviado(true); return new Vista("Respuesta de Send."); public Vista doVerify() { if (model.isEnviado()) return new Vista("Send ya ejecutado."); return new Vista("Send no ejecutado.");

52 III. Patrones de Diseño Modelo Vista Control
Unidos a este modelo aparecen otras dos estrategias. Inversión de Control (IoC) Empleada en todos los frameworks de desarrollo. Principio Hollywood: “No me llames, ya te llamo yo”. Inyección de Dependencias (DI) Configurar vs Programar. Simplifica la obtención de recursos comunes. Utilización de las anotaciones.

53 III. Patrones de Diseño Inversión de Control public class Control {
public Vista doAction(String action) { try { return (Vista)this.getClass().getMethod("do"+action, new Class[]{}).invoke(this,new Object[]{}); } catch (Exception e) { return new Vista("Error: "+e); } public class SubControl extends Control { private Modelo model = new Modelo(); public Vista doIndex() { return new Vista("Retorno Página Index."); } public Vista doSend() { model.setEnviado(true); return new Vista("Respuesta de Send."); public Vista doVerify() { if (model.isEnviado()) return new Vista("Send ya ejecutado."); return new Vista("Send no ejecutado.");

54 III. Patrones de Diseño Inyección de Dependencias
public class Server implements Observer { private Control control; public Server() { // Código que instancia un objeto de la subclase de control // adecuada para manejar las peticiones de la aplicación } @Override public void update(Observable o, Object arg) { String action = ((Cliente)o).getLink(); Vista vista = control.doAction(action); vista.send(); public class Server implements Observer { @Controlador(name=SubControl) private Control control; @Override public void update(Observable o, Object arg) { String action = ((Cliente)o).getLink(); Vista vista = control.doAction(action); vista.send(); }

55 III. Patrones de Diseño Prácticas
Repasa los diferentes patrones del GoF y localiza los más adecuados para estos problemas: Dotar de un sistema de undo/redo a un editor. Crear un sistema gestor de ventanas que permita crear ventanas con diferentes características. Crear un sistema de actualizaciones automáticas en función de la variación de diversos objetos. Crear números aleatorios permitiendo emplear diversas API’s de generadores de números aleatorios. Asegurar la aleatoriedad de dichos números.

56 III. Patrones de Diseño Prácticas Memento. Decorator. Observer.
Dotar de un sistema de undo/redo a un editor. Es un patrón específico para este tipo de trabajo. Decorator. Crear un sistema gestor de ventanas que permita crear ventanas con diferentes características. De este modo se pueden crear ventanas que mezclen diferentes características sin necesidad de crear todas las combinaciones. Observer. Crear un sistema de actualizaciones automáticas en función de la variación de diversos objetos. Abstract Factory. Crear números aleatorios permitiendo emplear diversas API’s de generadores de números aleatorios. Builder puede ser excesivo mejor para tratar de simplificar la construcción. Singleton Asegurar la aleatoriedad de dichos números.

57 IV. Arquitectura Java EE

58 IV. Arquitectura Java EE
Modelo de Capas A medida que evolucionan las aplicaciones Web, surge la necesidad de organizarlas. Inicialmente se emplean 3 capas. Actualmente es más adecuado el uso de 4.

59 IV. Arquitectura Java EE
Contenedores Java EE Entorno de ejecución específico para un conjunto de objetos de un determinado tipo y con unos fines concretos.

60 IV. Arquitectura Java EE
Servicios Java EE Para cada contenedor Java EE proporciona una serie de servicios, como por ejemplo: Java Transaction API (JTA) Java Persistence API (JPA) Java Message Service (JMS) Java Naming Direct Interface (JNDI) JavaMail Java Beans Active Framework (JAF) Java API for XML Procesing (JAXP) Java EE Connector Arquitecture Java Authentication and Authorization Service (JAAS) Servicios Web (JAXWS)

61 IV. Arquitectura Java EE
Ensamblado y Empaquetado Módulo EAR Contienen una aplicación completa. /*.war /*.jar /META-INF/application.xml <?xml version="1.0" encoding="ASCII"?> <application xmlns:xsi=" xmlns=" xmlns:application=" xsi:schemaLocation=" version="5"> <display-name>EjemploEAR</display-name> <module> <web> <web-uri>Ejemplo.war</web-uri> <context-root>Ejemplo</context-root> </web> </module> </application>

62 IV. Arquitectura Java EE
Ensamblado y Empaquetado Módulo WEB Contienen un módulo web. /*.* /WEB-INF/web.xml /WEB-INF/classes/*.class /WEB-INF/lib/*.jar Dentro del módulo web: Servlets Filters Listeners El contenido varia mucho en función del tipo de desarrollo utilizado.

63 IV. Arquitectura Java EE
Ensamblado y Empaquetado: Módulo WEB <web-app … id="DiarioDigital" version="2.5"> <display-name>DiarioDigital</display-name> <description>DiarioDigital</description> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <listener><listener-class>com.sun.faces.config.ConfigureListener</listener-class></listener> <servlet> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <url-pattern>*.jsf</url-pattern> </servlet-mapping> </web-app>

64 IV. Arquitectura Java EE
Ensamblado y Empaquetado Módulo EJB Contienen un módulo EJB. /*.class /META-INF/ejb-jar.xml El uso de anotaciones simplifica el contenido del descriptor. <?xml version="1.0" encoding="UTF-8"?> <ejb-jar version="3.0" xmlns=" xmlns:xsi=" xsi:schemaLocation=" <display-name>SimpleEJB</display-name> </ejb-jar>

65 IV. Arquitectura Java EE
Servlets Clase Java con un ciclo de vida concreto. Init: Ejecutado al cargarse la primera vez. doGet/doPost/do…: Ejecutados al recibirse peticiones de cada tipo concreto. Destroy: Ejecutado al finalizar. Importante: Se ejecuta en un hilo. Request/Response/Session.

66 IV. Arquitectura Java EE
JSP’s Al estilo de otros lenguajes, escribir código Java dentro de HTML. Se compila y se convierte en un servlet. Maneja los mismos objetos. Custom Tags. Ampliar la sintaxis de HTML. page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Ejemplo</title> </head> <body> Hola <%=request.getParameter("nombre") %>. </body> </html> public class MiServlet extends HttpServlet { public MiServlet() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("<html>"); response.getWriter().println("<head><title>Ejemplo</title></head>"); response.getWriter().println("<body>Hola "+request.getParameter("nombre")+"</body>"); response.getWriter().println("</html>"); }

67 IV. Arquitectura Java EE
Custom Tags fichero.jsp prefix="t" uri="MisTags" %> page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <t:mitag/> </body> </html> package tag; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; public class MiTag extends SimpleTagSupport { public void doTag() throws JspException { PageContext pageContext = (PageContext) getJspContext(); JspWriter out = pageContext.getOut(); try { out.println("Hello World"); } catch (Exception e) { } } /WEB-INF/tlds/MiTag.tld <?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns=" xmlns:xsi=" xsi:schemaLocation=" web-jsptaglibrary_2_0.xsd">   <tlib-version>1.0</tlib-version>  <short-name>MTags</short-name>  <uri>MisTags</uri>  <tag>    <name>mitag</name>    <tag-class>tag.MiTag</tag-class>    <body-content>empty</body-content>  </tag> </taglib>

68 IV. Arquitectura Java EE
Custom Tags: Argumentos. fichero.jsp prefix="t" uri="MisTags" %> page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <t:mitag propiedad=“Una Propiedad”/> <t:mitag propiedad=“${param[‘nombre’]}”/> </body> </html> package tag; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; public class MiTag extends SimpleTagSupport { private String propiedad; public void setPropiedad(String p) { propiedad = p; } public void doTag() throws JspException { PageContext pageContext = (PageContext) getJspContext(); JspWriter out = pageContext.getOut(); try { out.println("Hello World: "+propiedad); } catch (Exception e) { } } /WEB-INF/tlds/MiTag.tld <?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns=" xmlns:xsi=" xsi:schemaLocation=" web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version>  <short-name>MTags</short-name>  <uri>MisTags</uri>  <tag>    <name>mitag</name>    <tag-class>tag.MiTag</tag-class>    <body-content>empty</body-content> <attribute> <name>propiedad</name> <rtexprvalue>true</rtexprvalue> <required>false</required> </attribute>  </tag> </taglib>

69 IV. Arquitectura Java EE
Custom Tags: Body package tag; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; public class MiTag extends SimpleTagSupport { public void doTag() throws JspException { JspFragment body = getJspBody(); PageContext pageContext = (PageContext) getJspContext(); JspWriter out = pageContext.getOut(); try { StringWriter stringWriter = new StringWriter(); StringBuffer buff = stringWriter.getBuffer(); buff.append("<h1>"); body.invoke(stringWriter); buff.append("</h1>"); out.println(stringWriter); } catch (Exception e) { } } /WEB-INF/tlds/MiTag.tld <?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns=" xmlns:xsi=" xsi:schemaLocation=" web-jsptaglibrary_2_0.xsd">   <tlib-version>1.0</tlib-version>  <short-name>MTags</short-name>  <uri>MisTags</uri>  <tag>    <name>mitag</name>    <tag-class>tag.MiTag</tag-class>  </tag> </taglib> fichero.jsp prefix="t" uri="MisTags" %> page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <t:mitag>Texto Interno</t:mitag> </body> </html>

70 IV. Arquitectura Java EE
Custom Tags: Simplificado /WEB-INF/tags/mitag.tag * Simple * Hola Mundo !! * Con Parámetros * name="color" required="true" %> <font color=“${pageScope.color}”>Hola Mundo!!</font> <%String theColor = (String) pageContext.getAttribute("color"); %> <font color=“<%=theColor%>”>Hola Mundo!!</font> * Con Contenido * <font color=“${pageScope.color}”><jsp:doBody/></font> <jsp:doBody var="theBody"/> <%String bc = (String) pageContext.getAttribute("theBody"); %> <font color=“${pageScope.color}”><%= bc.toUpperCase() %></font> fichero.jsp taglib prefix="t" tagdir="/WEB-INF/tags" %> page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <t:mitag/> <t:mitag color=“red”/> <t:mitag color=“red”>Texto</t:mitag> </body> </html>

71 IV. Arquitectura Java EE
Prácticas Crea un Server WebLogic11g. Crea un Dynamic Web Project sobre el servidor. Añade un Servlet/JSP/CustomTag. Añade un Filtro. Añade un Listener. Añade una página index con un enlace al servlet/jsp. Incluye la vista “TCP/IP Monitor” y úsala.

72 IV. Arquitectura Java EE
Crea un Servidor WebLogic.

73 IV. Arquitectura Java EE
Crea un Dynamic Web Project.

74 IV. Arquitectura Java EE
Añade un Servlet. protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletOutputStream out = response.getOutputStream(); out.println("<html>"); out.println("<head><title>MiServlet</title></head>"); out.println("<body>"); long numero = 0; HttpSession session = request.getSession(true); if (session.isNew()) { out.println("<h1>Acabo de pensar un número del 1 al 10, adivina cuál es:</h1>"); session.setAttribute("MiNumero", Math.round(Math.random()*10+1)); } else { out.println("<h1>Tengo pensado un número del 1 al 10, adivina cuál es:</h1>"); numero = (Long)session.getAttribute("MiNumero"); } if (request.getParameter("number")!=null) { try { if (Long.parseLong(request.getParameter("number")) == numero) { out.println("<h2>¡ Has Acertado !</h2>"); } else { out.println("<h2>Lo siento, vuelve a intentarlo.</h2>"); } } catch (NumberFormatException nfe) { out.println("<h2>Debes escribir un número.</h2>"); } out.println("<form method=\"post\">"); out.println("<label>Tu numero:</label><input type=\"text\" name=\"number\"/>"); out.println("</form>"); out.println("</body>"); out.println("</html>"); out.flush(); out.close();

75 IV. Arquitectura Java EE
Añade un Filtro. int minHour = 0; int maxHour = 24; public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,ServletException { int hora = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); if (hora>=minHour && hora<=maxHour)chain.doFilter(request, response); else { ServletOutputStream out = res.getOutputStream(); out.println("<html>"); out.println("<head><title>MiServlet</title></head>"); out.println("<body><h1>Sólo juego de "+minHour+" a "+maxHour+".</h1></body>"); out.println("</html>"); out.flush(); out.close(); } public void init(FilterConfig fConfig) throws ServletException { try { minHour = Integer.parseInt(fConfig.getInitParameter("minimo")); maxHour = Integer.parseInt(fConfig.getInitParameter("maximo")); if (minHour>23 || minHour<0 || maxHour>23 || maxHour<0 || minHour>maxHour) throw new Exception("Hora no válida."); } catch (Exception ex) { System.out.println("Formato Hora Incorrecto!");

76 IV. Arquitectura Java EE
Añade un Listener. public void attributeRemoved(HttpSessionBindingEvent arg0) { } public void attributeAdded(HttpSessionBindingEvent arg0) { System.out.println("Acaba de Pensarse en el: "+arg0.getSession().getAttribute("MiNumero")); } public void attributeReplaced(HttpSessionBindingEvent arg0) { }

77 V. Tecnologías Java EE

78 V. Tecnologías Java EE Tecnologías Vista: JSF
Estándar SUN: Existen muchas alternativas. Comunidad de desarrollo amplia. Apoyo tecnológico de las principales compañías. Adaptación de las mejores ideas de otros. Lentitud en asimilar nuevas tecnologías. Modificaciones o mejoras lentas. Dependencia de implementaciones de terceros.

79 V. Tecnologías Java EE Tecnologías Vista: JSF Componentes de JSF:
API + Implementación de Referencia. Representan componentes UI y manejan su estado, eventos, validaciones, navegación, etc… Librería de Etiquetas. Etiquetas personalizadas de JSP para dibujar los componentes UI dentro de las páginas JSP.

80 V. Tecnologías Java EE Ciclo de Vida JSF
Las peticiones Faces no se limitan a petición-respuesta, disponen de un ciclo de vida. El ciclo de vida depende del tipo de petición. Respuesta No-Faces: Respuesta generada al margen de la fase de renderizar respuesta de faces. Respuesta Faces: Respuesta generada en la fase de renderizar respuesta de faces. Petición No-Faces: Petición enviada a un componente no faces. Petición Faces: Petición enviada desde una respuesta faces previamente generada. El escenario normal Peticion faces/Respuesta faces.

81 V. Tecnologías Java EE Ciclo de Vida JSF

82 V. Tecnologías Java EE Ciclo de Vida JSF
Reconstruir el árbol de componentes. Se construye el árbol de componentes faces. Aplicar valores a la petición. Se asocian a los componentes los nuevos valores desde los parámetros de la petición. Procesar validaciones. Se procesan las validaciones para los componentes. Actualizar los valores del modelo. Una vez es válido se actualizan los valores del modelo. Invocar aplicación. En este punto se manejan los eventos a nivel de aplicación. Renderizar respuesta. Por último se dibujan los componentes del árbol.

83 V. Tecnologías Java EE Componentes JSF Se emplean las etiquetas.
Conjunto de clases UIComponent. Representan los componentes. Modelo de renderizado. Forma de visualizar el componente. Modelo de eventos. Forma de manejar los eventos lanzados. Modelo de conversión. Conectar conversores de datos al componente. Modelo de validación. Forma de registrar validadores para el componente. Se emplean las etiquetas. RichFaces, ICEFaces: Librerías de etiquetas.

84 V. Tecnologías Java EE Componentes JSF
<h:dataTable id="noticias" value="#{Noticias.listadoCategoria}" var="noti"> <h:column> <f:facet name="header"><h:outputText value="Titular"/></f:facet> <h:outputText value="#{noti.titulo}" /> </h:column> <f:facet name="header"><h:outputText value="Contenido"/></f:facet> <h:outputText value="#{noti.contenido}" /> </h:dataTable> <h:form id=“NoticiaForm”> <h:outputText value="Código:"/> <h:inputText id="codigo" value="#{GestorNoticias.noticia.codigo}" required="true" /><br/> <h:outputText value="Titulo:"/> <h:inputText id="titulo" value="#{GestorNoticias.noticia.titulo}" required="true" /><br/> <h:outputText value="Contenido:"/> <h:inputText id="contenido" value="#{GestorNoticias.noticia.contenido}" required="true" /><br/> <h:outputText value="Fecha:"/> <h:inputText id="fecha" value="#{GestorNoticias.noticia.fecha}" required="true"> <f:convertDateTime pattern="dd/MM/yyyy"/> </h:inputText><br/> <h:outputText value="Portada:"/> <h:selectBooleanCheckbox id="portada" value="#{GestorNoticias.noticia.portada}" required="true" /><br/> <h:outputText value="Categoria:"/> <h:selectOneMenu id="categoria" value="#{GestorNoticias.categoriaId}"> <f:selectItems value="#{GestorNoticias.selectCategorias}" /> </h:selectOneMenu><br/> <h:commandButton value="Guardar" action="#{GestorNoticias.saveNoticia}" /> </h:form>

85 V. Tecnologías Java EE Faces-Config.xml
Archivo de configuración principal. Describe los bean manejados. Describe las reglas de navegación. <managed-bean> <description>Noticiero</description> <managed-bean-name>GestorNoticias</managed-bean-name> <managed-bean-class>web.GestorNoticias</managed-bean-class> <managed-bean-scope>application/session/request/none</managed-bean-scope> </managed-bean> <context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.xml,/WEB-INF/faces-beans.xml</param-value> </context-param> <navigation-rule> <from-view-id>/editar/editar.xhtml</from-view-id> <navigation-case> <from-outcome>nuevaCategoria</from-outcome> <to-view-id>/editar/new/categoria.xhtml</to-view-id> </navigation-case> <from-outcome>nuevaNoticia</from-outcome> <to-view-id>/editar/new/noticia.xhtml</to-view-id> </navigation-rule>

86 V. Tecnologías Java EE JSF Paso a Paso Ciclo de Vida
Podemos crear un Listener. Escucha la fase indicada en getPhaseId. public class PhaseListener implements javax.faces.event.PhaseListener { public void afterPhase(PhaseEvent event) { System.out.println("AFTER - "+event.getPhaseId()); } public void beforePhase(PhaseEvent event) { System.out.println("BEFORE - "+event.getPhaseId()); } public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } } /WEB-INF/faces-config.xml <lifecycle> <phase-listener>lst.PhaseListener</phase-listener> </lifecycle>

87 V. Tecnologías Java EE JSF Paso a Paso Mapear Componentes Con Objetos
Mapear Valores Fijos <h:outputText value=“Hola Mundo !!"/> Mapear Propiedades del Sistema <h:outputText value=“#{initParam.version}"/> <h:outputText value=“#{param[‘nombre’]}"/> Mapear Propiedades de un Bean Manejado Siguen convenciones JavaBean. <h:outputText value="#{managedBeans.propiedad}"/> <managed-bean> <managed-bean-name>managedBeans</managed-bean-name> <managed-bean-class>mbeans.ManagedBeans</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>propiedad</property-name> <value>Hola Mundo !!</value> </managed-property> </managed-bean>

88 V. Tecnologías Java EE JSF Paso a Paso Mapear Componentes
Mapear Componentes Completos Backing Beans <h:outputText binding="#{managedBeans.component}"/> package mbeans; import javax.faces.component.UIOutput; public class ManagedBeans { private UIOutput component; public void setComponent(UIOutput ui) { component = ui; component.setValue("Hola Mundito !!"); } public UIOutput getComponent() { return component; }

89 V. Tecnologías Java EE JSF Paso a Paso Invocar Métodos
Métodos de Validación Utilizados sólo en UIInput. Reciben el FacesContext y el componente a validar y su valor. <h:messages/> <h:inputText validator="#{managedBeans.validate }"/> public void validate (FacesContext ctx, UIComponent cmp, Object obj) { String = (String)obj; if { ((UIInput)cmp).setValid(false); ctx.addMessage(cmp.getClientId(ctx), new FacesMessage("Mail Incorrecto", "")); } else ((UIInput)cmp).setValid(true); }

90 V. Tecnologías Java EE JSF Paso a Paso Invocar Métodos
Manejadores de Acciones Se utiliza en UICommand y UIButton. Reciben el evento. <h:commandButton value="Pulsa" actionListener="#{managedBeans.ejecutaAccion}“/> public void ejecutaAccion(ActionEvent ev) { System.out.println("Se ejecuta la acción !!"); }

91 V. Tecnologías Java EE JSF Paso a Paso Invocar Métodos
Manejadores de Navegación Se utiliza en UICommand y UIButton. Retornan una cadena de navegación. <h:commandLink value="Pincha" action="#{managedBeans.onlyAction}“/> public String onlyAction() { return “success"; }

92 V. Tecnologías Java EE JSF Paso a Paso Invocar Métodos
Manejadores de Cambios Capturar cambios sobre componentes UIInput. <h:selectBooleanCheckbox valueChangeListener="#{managedBeans.changeColor}" onchange="submit()"/> public void changeColor(ValueChangeEvent event) { boolean flag = ((Boolean)event.getNewValue()).booleanValue(); System.out.println("Check: "+flag); }

93 V. Tecnologías Java EE JSF Paso a Paso Controlar Navegación
Conjunto de reglas para seleccionar la siguiente página a la que moverse. La selección depende de: Página actual. Action ejecutado por el componente que navega. Cadena retornada por el action (outcome). Admite patrones en from-view-id. <navigation-rule> <from-view-id>/logon.jsp</from-view-id> <navigation-case> <from-action>#{LogonForm.logon}</from-action> <from-outcome>success</from-outcome> <to-view-id>/continue.jsp</to-view-id> </navigation-case> </navigation-rule>

94 Enlace en /pages/logon.jsp Enlace en /pages/otra.jsp
V. Tecnologías Java EE JSF Paso a Paso Controlar Navegación. Ejemplos. <navigation-rule> <from-view-id>/pages/logon.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/continue1.jsp</to-view-id> </navigation-case> <from-action>#{m.acc}</from-action> <to-view-id>/continue2.jsp</to-view-id> </navigation-rule> Enlace en /pages/logon.jsp Destino <h:commandButton action=“success" value="Submit" /> continue1.jsp <h:commandButton action=“#{m.acc}" value="Submit" /> continue2.jsp <h:commandButton action=“error" value="Submit" /> error.jsp Enlace en /pages/otra.jsp Destino <h:commandButton action=“success" value="Submit" /> continue3.jsp <h:commandButton action=“#{m.acc}" value="Submit" /> <h:commandButton action=“error" value="Submit" /> error.jsp <navigation-rule> <from-view-id>/pages/*</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/continue3.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <navigation-case> <from-outcome>error</from-outcome> <to-view-id>/error.jsp</to-view-id> </navigation-case> </navigation-rule>

95 V. Tecnologías Java EE JSF Paso a Paso
Crear el adivinador de números JSF. Crear un bean para calcular el número aleatorio. El mismo bean puede recoger el número introducido. Crea el JSP para solicitar el número, valida la entrada con validateLongRange. Configura la navegación adecuada.

96 V. Tecnologías Java EE Crea un Hola Mundo JSF.

97 V. Tecnologías Java EE Crea un Hola Mundo JSF.

98 V. Tecnologías Java EE JSF Paso a Paso
Crear el adivinador de números JSF. page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> taglib prefix="f" uri=" taglib prefix="h" uri=" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <f:view> <h:outputText rendered="#{adivina.intentado}" value="Lo siento, vuelve a probar !!"/> He pensado un número entre <h:outputText value="#{adivina.minimo}"/> y <h:outputText value="#{adivina.maximo}"/>, adivina !! <h:form> <h:messages showDetail="true"/> <h:selectOneMenu onchange="submit()" valueChangeListener="#{adivina.cambiaIdioma}" immediate="true"> <f:selectItem itemLabel="#{msg.castellano}" itemValue="es"/> <f:selectItem itemLabel="#{msg.ingles}" itemValue="en"/> </h:selectOneMenu> <h:inputText value="#{adivina.numero}"> <f:validateDoubleRange minimum="#{adivina.minimo}" maximum="#{adivina.maximo}"/> </h:inputText> <h:commandButton value="Prueba" action="#{adivina.adivinar}"/> </h:form> </f:view> </body> </html> Internacionalizar i18n <application> <locale-config> <default-locale>es</default-locale> <supported-locale>en</supported-locale> </locale-config> <message-bundle>msg.mensajes</message-bundle> <resource-bundle> <base-name>msg.mensajes</base-name> <var>msg</var> </resource-bundle> </application> <f:loadBundle basename="msg.mensajes" var="msg"/> <h:messages showDetail=“true” showSummary=“true”/> <h:outputText value="#{msg.titulo}"/> Archivo de Propiedades: msg/mensajes.properties, msg/mensajes_en.properties, … titulo=Pienso en un número entre javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE=Sumario javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE_detail=Valor fuera de rango {0} - {1}. <managed-bean> <managed-bean-name>adivina</managed-bean-name> <managed-bean-class>mbeans.Adivina</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>minimo</property-name> <value>1</value> </managed-property> <property-name>maximo</property-name> <value>10</value> </managed-bean> <navigation-rule> <from-view-id>/index.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/next.jsp</to-view-id> </navigation-case> <from-outcome>fail</from-outcome> <to-view-id>/index.jsp</to-view-id> </navigation-rule> public class Adivina { private long numeroPensado; private int numero; private int minimo; private int maximo; public Adivina() { numeroPensado = Math.round(Math.random()*10); } public int getNumero() { return numero; } public void setNumero(int n) { numero = n; } public int getMinimo() { return minimo;} public void setMinimo(int minimo) { this.minimo = minimo; } public int getMaximo() { return maximo; } public void setMaximo(int maximo) {this.maximo = maximo; } public String adivinar() { return (numeroPensado==numero)? "success“:"fail"; } public boolean isIntentado() { return numero!=0; } public void cambiaIdioma(ValueChangeEvent event) { FacesContext.getCurrentInstance().getViewRoot().setLocale(new Locale((String)event.getNewValue())); // Cortocircuito !! FacesContext.getCurrentInstance().renderResponse(); } page language="java" contentType="text/html; charset=ISO " pageEncoding="ISO "%> taglib prefix="f" uri=" taglib prefix="h" uri=" <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO "> <title>Insert title here</title> </head> <body> <f:view> Has acertado, era el <h:outputText value="#{adivina.numero}"/> !! </f:view> </body> </html>

99 V. Tecnologías Java EE Facelets Complemento ideal para JSF.
Definir una plantilla para tu portal y emplearla en todas tus páginas. <ui:include src=“cabecera.xhtml”/> <ui:include src=“pie.xhtml”/> <ui:include src=“menu.xhtml”/> /pagina.xhtml <ui:composition template=“/plantilla.xhtml”> <ui:define name=“body”> </ui:define> </ui:composition> <ui:insert name=“body”/>

100 V. Tecnologías Java EE Crea una plantilla facelets.
Añadir la librería Facelets: jsf-facelets B1.jar Nota: web.xml y faces-config.xml los modifica eclipse !! <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " > <html xmlns=" xmlns:ui=" xmlns:h=" xmlns:f=" <f:view contentType="text/html"/> <head> <meta http-equiv="Content-Type" content="text/xhtml+xml; charset=UTF-8" /> <title>Simple JSF</title> <link href="stylesheet/theme.css" rel="stylesheet" type="text/css" /> </head> <body> <div id="content"> <div id="header"><ui:include src="header.xhtml" /></div> <div id="menu" style="float:left;width:200px;"><ui:include src="menu.xhtml" /></div> <div id="body" style="float:left;"><ui:insert name="body" >Default Content</ui:insert></div> <div id="footer"><ui:include src="footer.xhtml" /></div> </div> </body> </html> Debemos cambiar las vistas y las reglas del faces-config.xml los id de las vistas pasan de .jsp a .xhtml.

101 V. Tecnologías Java EE Usar RichFaces.
<!-- RichFaces en web.xml --> <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>blueSky</param-value> </context-param> <!-- RichFaces + Facelets --> <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name> <param-value>com.sun.facelets.FaceletViewHandler</param-value> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <!-- Ya no es necesario modificar faces-config.xml --> <!-- application> <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> </application --> Para Usar RichFaces Añadir Librerías: commons-beanutils jar commons-digester-1.8.jar commons-logging jar richfaces-api GA.jar richfaces-impl GA.jar richfaces-ui GA.jar Nota: Hay que configurar a mano !! <?xml version="1.0" encoding="UTF-8"?> <html … xmlns:a4j=" xmlns:rich=" <body bgcolor="white"> <rich:panel id="panelRoot" > <rich:spacer height="5" title="Here is a spacer..."/><br /> <rich:separator lineType="beveled" height="8" width="100%" align="center"/> <rich:separator height="2" lineType="dotted"/><br /> </rich:panel> </body> </html> Y muchos componentes más: RichFaces Live Demo.

102 V. Tecnologías Java EE Tecnologías Control: EJB
Dar más servicios a los objetos empleados en las aplicaciones web. Contenedor específico para desplegar y ejecutar este tipo de objetos. Posibilidad de compartir lógica a través de estos objetos. Necesario un Contenedor de EJB. Servidor JEE.

103 V. Tecnologías Java EE Tecnologías Control: EJB Tipos de EJB
Session Beans: Sitos en la lógica de negocio. Stateless: Sin información de estado. Stateful: Mantienen el estado entre peticiones. Message Driven Beans: Utilizados para invocar métodos de forma asíncrona. Entity Beans: Empleados en la capa de persistencia para representar datos del modelo.

104 V. Tecnologías Java EE Tecnologías Control: EJB Ciclo de Vida
Creación, Destrucción, Pasivación (Stateful).

105 V. Tecnologías Java EE Tecnologías Control: EJB Callbacks
Siempre que tenemos un ciclo de vida. Posibilidad de emplear AOP. @PostConstruct @PreDestroy @PreActivate @PostActivate Interceptores Siempre que empleamos contenedores IoC y Ciclos de Vida. Default Clase Método

106 V. Tecnologías Java EE Tecnologías Control: EJB Anotaciones.
Forma de simplificar la definición del EJB. @Stateful @Stateless @Stateless public class PlaceBidBean implements PlaceBid { @Interceptors(ActionBazaarLogger.class) public void addBid(Bid bid) { ... } public class ActionBazaarLogger { @AroundInvoke public Object logMethodEntry(InvocationContext invocationContext) throws Exception { System.out.println(”Entering: ”+ invocationContext.getMethod().getName()); return invocationContext.proceed();

107 V. Tecnologías Java EE Prácticas II Crea un proyecto EJB.
Liga tu proyecto EJB a una aplicación Web. Emplea los EJB’s creados desde la aplicación Web. Crea los EJB necesarios para Diario Digital.

108 V. Tecnologías Java EE Crea un proyecto EJB.

109 V. Tecnologías Java EE Crea un EJB. @Stateless
public class Ejemplo implements EjemploLocal { double numero; public Ejemplo() { System.out.println("Stateless!!!"); numero = Math.floor(Math.random()*10+1); } @Override public String getMensaje() { numero++; return "Mensaje ["+numero+"]"; @Stateful public class EjemploB implements EjemploBLocal { double numero; public EjemploB() { System.out.println("Stateful!!!"); numero = Math.floor(Math.random()*10+1); } @Override public String getMensaje() { numero++; return "MensajeB ["+numero+"]"; public class JSFBean { @EJB public EjemploBLocal ejemplo; public String getMensaje() { return ejemplo.getMensaje(); } } Faces-config.xml <managed-bean> <managed-bean-name>jSFBean</managed-bean-name> <managed-bean-class>mb.JSFBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> Página <h:outputText value="#{jSFBean.mensaje}" />

110 V. Tecnologías Java EE Crea un EJB.

111 V. Tecnologías Java EE Tecnologías Modelo: JPA
Muchos proyectos diferentes ORM. IBatis, Hibernate, JDO, TopLink,… Necesario unificar: JPA.

112 V. Tecnologías Java EE Tecnologías Modelo: JPA
Contextos de Persistencia <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns=" xmlns:xsi=" xsi:schemaLocation=" version="1.0"> <persistence-unit name="defaultPU" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>jdbc/NombreDataSource</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="validate"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.default_shema" value="NOMBRE"/> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> <property name="hibernate.transaction.manager_lookup_class“ value="org.hibernate.transaction.OC4JTransactionManagerLookup"/> <property name="hibernate.query.factory_class“ value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory" /> <property name="hibernate.transaction.flush_before_completion" value="true"/> <property name="hibernate.cache.provider_class“ value="org.hibernate.cache.HashtableCacheProvider"/> </properties> </persistence-unit> </persistence> Transacciones JTA: Empleada en Servidores de Aplicaciones JavaEE Transacciones RESOURCE_LOCAL: Empleada en Aplicaciones C/S.

113 V. Tecnologías Java EE Tecnologías Modelo: JPA Empleo de Persistencia
Declarar un EntityManager ligado a la Unidad que necesites. class NoticiasBean implements Noticias,Serializable { @PersistenceContext(unitName="diarioPU") protected EntityManager entityManager; private List<Noticia> listado; public List<Noticia> getListado() { listado = entityManager.createQuery("from noticias.Noticia noti").getResultList(); return listado; } public void nuevaNoticia(Noticia not) { entityManager.persist(not); }

114 V. Tecnologías Java EE Tecnologías Modelo: JPA
Ciclo de Vida: Entity Beans

115 V. Tecnologías Java EE Tecnologías Modelo: JPA
Anotaciones Básicas: Entidades y Claves @Entity @Table(name="USUARIOS") public class Usuario { @Id private String nick; ... public Usuario() { } // Getters y Setters } Clave Simple @Entity public class Entidad { @EmbeddedId @AttributeOverrides({ @AttributeOverride(name = "id", column = "ID", nullable = false, precision = 5, scale = 0)), @AttributeOverride(name = "nombre", column = "NOMBRE", nullable = false, length = 50)), }) private EntidadId id; public Entidad() { } // Getters y Setters } @Embedded public class EntidadId { int id; String nombre; public EntidadId() { } public boolean equals(Object o) { /* Comprueba si son iguales */ } public int hashCode() { /* Buenas practicas equals() -> hashCode() */ } Clave Compuesta

116 V. Tecnologías Java EE Tecnologías Modelo: JPA
Anotaciones Básicas: Atributos @Entity @Table(name="USUARIOS") public class Usuario { @Id private String nick; @Column(name="PASSWORD", nullable=false) private String pass; @Column(name=" ", nullable=false) private String mail; @Lob @Basic(fetch=FetchType.LAZY) private byte[] imagen; ... public Usuario() { } // Getters y Setters } Atributo Simple @Entity @Table(name="USUARIOS") public class Usuario { @Id private String nick; @Embedded @AttributeOverrides({ }) private Direccion direccion; public Usuario() { } // Getters y Setters } @Embeddable public class Direccion implements Serializable { private String direccionPostal; private String ciudad; private int codigoPostal; private String pais; public Direccion() { } public boolean equals(Object o) { /* Comprueba si las dos entidades son iguales */ } public int hashCode() { /* Buenas practicas equals() -> hashCode() */ } Atributo Compuesto

117 V. Tecnologías Java EE Tecnologías Modelo: JPA
Anotaciones Básicas: Relaciones @Entity @Table(name="USUARIOS") public class Usuario { @Id private String nick; @Column(name="PASSWORD", nullable=false) private String pass; @OneToOne @JoinColumn(name="PERFIL_USUARIO_ID",referencedColumnName="PERFIL_ID", updatable=false) private Perfil perfil; private Set<Noticia> noticias = new HashSet<Noticia>(0); @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,mappedBy = "usuario") public Set<Noticia> getNoticias() { return this.noticias; } public void setNoticias(Set<Noticia> noticias) { this.noticias = noticias; ... @Table(name="PERFILES") public class Perfil { @Column(name="PERFIL_ID") private int id; @Table(name = "NOTICIA") public class Noticia implements java.io.Serializable { private Usuario usuario; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "USUARIO", nullable = false) @NotNull public Usuario getUsuario() { return this.usuario; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } OneToOne ManyToOne CascadeType.PERSIST: Cuando persistamos la entidad todas las entidades que contenga esta variable serán persistidas también. CascadeType.REMOVE: Cuando borremos la entidad todas las entidades que contenga esta variable se borrarán del mismo modo. CascadeType.REFRESH: Cuando actualicemos la entidad todas las entidades que contenga esta variable se actualizarán. CascadeType.MERGE: Cuando hagamos un "merge" de la entidad todas las entidades que contenga esta variable realizarán la misma operación. CascadeType.ALL: Todas las operaciones citadas anteriormente. ManyToMany: Muy similar a ManyToOne pero simétrica en ambas clases.

118 V. Tecnologías Java EE Tecnologías Modelo: JPA
Anotaciones Avanzadas: Querys Personalizadas @NamedNativeQuery ( name="nativeResult", query="SELECT USUARIO_ID,NOMBRE,APELLIDOS FROM USUARIOS WHERE USUARIO_ID= 123", resultSetMapping = "usuarioNamedMapping") @SqlResultSetMapping ( name="usuarioNamedMapping", entities = ( entityClass = mi.clase.Usuario.class, fields = ( name="usuarioId", column="USUARIO_ID"), @FieldResult ( name="nombre", column="NOMBRE"), name="apellidos", column="APELLIDOS") } )

119 V. Tecnologías Java EE Tecnologías Modelo: JPA
Anotaciones Avanzadas: Procedimientos Almacenados create or replace procedure findUsersLike(res out sys_refcursor, str in string) as   begin      open res for select u.* from users u where u.username like concat(str, '%');   end findUsersLike;   @NamedNativeQuery (name = "User.findLike",      resultClass = User.class,      query = "{call findUsersLike(?,:VAR)}",      hints = {      }   )   @org.hibernate.annotations.NamedNativeQuery (name=“User.findLike”,    callable = true, readOnly = true)   Query query = em.createNamedQuery("User.findLike");   query.setParameter("VAR","lt");   List users = query.getResultList();  

120 V. Tecnologías Java EE Aplicación Completa: JSF+EJB3+JPA
Emplear EJB Session Bean Facade.

121 V. Tecnologías Java EE Prácticas III
Crea un ejemplo de Bean de Entidad. Incluye atributos de diferentes tipos. Relaciona varias entidades. Convierte los objetos del Diario Digital en entidades JPA para dotarlas de persistencia.

122 V. Tecnologías Java EE Crea un ejemplo de Bean de Entidad.

123 V. Tecnologías Java EE Crea un ejemplo de Bean de Entidad.

124 V. Tecnologías Java EE Crea un ejemplo de Bean de Entidad.

125 V. Tecnologías Java EE Crea un ejemplo de Bean de Entidad.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns=" xmlns:xsi=" xsi:schemaLocation=" <persistence-unit name="DiarioJPA" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>DiarioDataSource</jta-data-source> <non-jta-data-source>DiarioDataSource</non-jta-data-source> <class>data.Categoria</class> <class>data.Noticia</class> <properties> <property name="eclipselink.target-server" value="WebLogic_10"/> <property name="eclipselink.logging.level" value="FINEST"/> </properties> </persistence-unit> </persistence>

126 VI. Tecnologías Avanzadas

127 VI. Tecnologías Avanzadas
Servicios WEB Forma de interactuar.

128 VI. Tecnologías Avanzadas
Servicios WEB Buscar servicios Web: UDDI. Catálogo de Servicios. Invocar Servicios Web: WSDL. Descriptor del Servicio. Intercambio de Información: SOAP. Documentos XML. Las herramientas nos simplifican el trabajo. A partir de un método podemos crear un servicio. A partir de un WSDL podemos crear un cliente.

129 VI. Tecnologías Avanzadas
Servicios WEB Implementaciones Diversas: Tratan de automatizar la creación de servicios y clientes. Axis2 JAXWS CXF Usaremos JAXWS. En FundeWeb se usará CXF, pero el curso se centra en la interacción y no en las implementaciones.

130 VI. Tecnologías Avanzadas
Prácticas I Crea un Sencillo Servicio Web. Pruébalo con el “Web Service Explorer” Genera un cliente a partir del WSDL. Crea el Servicio Web “Teletipo”. Incluye en el Diario Digital las noticias del “Teletipo”.

131 VI. Tecnologías Avanzadas
Crea un Sencillo Servicio Web.

132 VI. Tecnologías Avanzadas
Crea un Sencillo Servicio Web. @WebService public class Titulares { @EJB private NoticiasLocal misNoticias; @WebMethod public List<Titular> listTitulares() { ArrayList<Titular> lista = new ArrayList<Titular>(); for (Noticia n:misNoticias.getListadoPortada()) { Titular t = new Titular(); t.setTitulo(n.getTitulo()); t.setFecha(n.getDia()); lista.add(t); } return lista; public class Titular implements Serializable { private String titulo; private Date fecha; public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public Date getFecha() { return fecha; } public void setFecha(Date fecha) { this.fecha = fecha; } }

133 VI. Tecnologías Avanzadas
Crea un Sencillo Servicio Web. public List<Titular> getTitulares() { TitularesService ts = new TitularesService(); return ts.getTitularesPort().listTitulares(); }

134 VI. Tecnologías Avanzadas
Autenticación JAAS Java EE permite emplear roles para securizar recursos de una aplicación. <security-role> <role-name>administrador</role-name> </security-role> <role-name>usuario</role-name> <orion-application …> ... <jazn provider="XML" location="./jazn-data.xml" default-realm="example.com"> <property name="jaas.username.simple" value="false"/> </jazn> </orion-application> <jazn-data xmlns:xsi=" xsi:noNamespaceSchemaLocation=" filepath="" OC4J_INSTANCE_ID=""> <jazn-realm> <realm> <name>example.com</name> <users><user><name>admin</name><credentials>!admin</credentials></user></users> <roles> <role><name>administrador</name><members><member><type>user</type><name>admin</name></member></members></role> </roles> </realm> </jazn-realm> </jazn-data>

135 VI. Tecnologías Avanzadas
Autenticación JAAS Java EE permite emplear roles para securizar recursos de una aplicación. @DeclareRoles({"administrador", "usuario"}) public class Ejemplo extends HttpServlet { protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (req.isUserInRole("administrador")) { // El usuario Autenticado tiene el rol administrador } <security-constraint> <web-resource-collection> <web-resource-name>Permiso Ejemplo</web-resource-name> <url-pattern>/Ejemplo</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>administrador</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <!-- LOGIN CONFIGURATION--> <login-config> <auth-method>BASIC</auth-method> </login-config>

136 VI. Tecnologías Avanzadas
Prácticas II Crea roles en una aplicación. Añade seguridad a diferentes recursos. Securiza la creación de noticias en el Diario Digital.

137 VI. Tecnologías Avanzadas
Crea roles en una aplicación. <!-- ROLES DE SEGURIDAD --> <security-role> <role-name>redactor</role-name> </security-role> <role-name>usuario</role-name> <security-constraint> <web-resource-collection> <web-resource-name>Redaccion del Diario</web-resource-name> <url-pattern>/editar/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <!-- LOGIN CONFIGURATION--> <login-config> <auth-method>BASIC</auth-method> </login-config> <wls:security-role-assignment> <wls:role-name>redactor</wls:role-name> <wls:principal-name>Administrators</wls:principal-name> </wls:security-role-assignment> <wls:role-name>usuario</wls:role-name> <wls:principal-name>AppTesters</wls:principal-name>

138 VI. Tecnologías Avanzadas
Portales y Portlets Idea similar a la de los servlets. Componentes configurables y reubicables. Pensados para su uso en portales. Especificación JSR 168.

139 VI. Tecnologías Avanzadas
Portales y Portlets Ventajas Desarrollo independiente y reutilizable. Personalización dinámica. Seguridad ante fallos. El fallo de un portlet no afecta al resto del portal. Adoptado por otras tecnologías. PHP Portlet. Inconvenientes Tecnología relativamente nueva. Genera portales con poca personalidad.

140 A. Diario Digital

141 A. Diario Digital Práctica Global
Muestra las noticias de un diario y un teletipo. EAR Application EJB Module WEB Module Web Service JSF Application Database

142 ¡ Gracias !


Descargar ppt "Java y Tecnologías J2EE Universidad de Murcia Noviembre 2009"

Presentaciones similares


Anuncios Google