arquitecturas software de varios niveles en java
TRANSCRIPT
A. Goñi. Dpto. LSI, UPV/EHU
1
INGENIERÍA del SOFTWARECurso 2006/07
Ingeniería en InformáticaFacultad de Informática
UPV/EHU
Departamento de Lenguajes y Sistemas Informáticos
A. Goñi. Dpto. LSI, UPV/EHU
2
Tema 2:Arquitecturas Software de varios niveles en Java
A. Goñi. Dpto. LSI, UPV/EHU
3
Índice• Arquitecturas Software de varios niveles• Construcción de interfaces gráficas en Java: AWT y
Swing• Conexión con BDs relacionales en Java: JDBC• Persistencia de objetos en Java: mecanismos de
serialización• Introducción a la computación distribuida en Java:
RMI• Tecnología Java para la construcción de aplicaciones
web: Applets, JSPs• Servicios Web
A. Goñi. Dpto. LSI, UPV/EHU
4
1. Arquitecturas Software de varios niveles
A. Goñi. Dpto. LSI, UPV/EHU
5
Índice
• Introducción• Arquitectura lógica del software en
niveles: presentación, lógica del negocio y datos.
• Arquitectura física en 2 niveles: cliente gordo/servidor flaco
• Arquitectura física en 2 niveles: cliente flaco/servidor gordo
• Arquitectura física en 3 (o más) niveles
A. Goñi. Dpto. LSI, UPV/EHU
6
Introducción
• Algunas aplicaciones deben soportar a varios usuarios que de manera concurrente, segura, fiable y eficiente ejecutan varias operaciones.
• Ejemplos:– bancos con cajeros conectados a un servidor central– distribuidores de ventas al por menor– terminales donde se pueden comprar entradas para
espectáculos• En estos casos es útil una arquitectura con
despliegue de componentes software en el lado del servidor (server side component architecture)– Componente: código que implementa un conjunto
conocido de interfaces
A. Goñi. Dpto. LSI, UPV/EHU
7
Ejemplo: comprar billetes para espectáculos
BASE DE DATOS
Se puede implementar en una sola clase (véase PedirBilleteNO3NIVELES) en nodos cliente, dejando la base de datos en un nodo servidor
A. Goñi. Dpto. LSI, UPV/EHU
8
public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !!
JLabel jLabel1 = new JLabel(“Nombre:”);JButton jButton1 = new JButton(“Pedir Billete”);
public PedirBilleteNO3NIVELES() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); }
void jButton1_actionPerformed(ActionEvent e) {
ResultSet rs = sentencia.executeQuery("SELECT NUMERO FROM"+" BILLETES WHERE ESTADO=\'LIBRE\'");
if (rs.next()) {int act = sentencia.executeUpdate("UPDATE BILLETES"+" SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+" WHERE NUMERO="+rs.getString("NUMERO")+" AND ESTADO='LIBRE'");
if (act>0) jTextArea1.append("Asignado. \nReferencia: "+n+"\n");else jTextArea1.append("Error al asignar billete"); }}
public static void main (String []arg) {PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES();b.setVisible(true);}}
A. Goñi. Dpto. LSI, UPV/EHU
9
public class PedirBilleteNO3NIVELES extends JFrame {// Nota: NO ESTÁ COMPLETA !!
JLabel jLabel1 = new JLabel(“Nombre:”);JButton jButton1 = new JButton(“Pedir Billete”);
public PedirBilleteNO3NIVELES() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); }
void jButton1_actionPerformed(ActionEvent e) {
ResultSet rs = sentencia.executeQuery("SELECT NUMERO FROM"+" BILLETES WHERE ESTADO=\'LIBRE\'");
if (rs.next()) {int act = sentencia.executeUpdate("UPDATE BILLETES"+" SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+" WHERE NUMERO="+rs.getString("NUMERO")+" AND ESTADO='LIBRE'");
if (act>0) jTextArea1.append("Asignado. \nReferencia: "+n+"\n");else jTextArea1.append("Error al asignar billete"); }}
public static void main (String []arg) {PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES();b.setVisible(true);}}
PRESENTACIÓN
A. Goñi. Dpto. LSI, UPV/EHU
10
public class PedirBilleteNO3NIVELES extends JFrame {// Nota: NO ESTÁ COMPLETA !!
JLabel jLabel1 = new JLabel(“Nombre:”);JButton jButton1 = new JButton(“Pedir Billete”);
public PedirBilleteNO3NIVELES() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); }
void jButton1_actionPerformed(ActionEvent e) {
ResultSet rs = sentencia.executeQuery("SELECT NUMERO FROM"+" BILLETES WHERE ESTADO=\'LIBRE\'");
if (rs.next()) {int act = sentencia.executeUpdate("UPDATE BILLETES"+" SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+" WHERE NUMERO="+rs.getString("NUMERO")+" AND ESTADO='LIBRE'");
if (act>0) jTextArea1.append("Asignado. \nReferencia: "+n+"\n");else jTextArea1.append("Error al asignar billete"); }}
public static void main (String []arg) {PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES();b.setVisible(true);}}
ACCESO A DATOS
A. Goñi. Dpto. LSI, UPV/EHU
11
public class PedirBilleteNO3NIVELES extends JFrame {// Nota: NO ESTÁ COMPLETA !!
JLabel jLabel1 = new JLabel(“Nombre:”);JButton jButton1 = new JButton(“Pedir Billete”);
public PedirBilleteNO3NIVELES() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); }
void jButton1_actionPerformed(ActionEvent e) {
ResultSet rs = sentencia.executeQuery("SELECT NUMERO FROM"+" BILLETES WHERE ESTADO=\'LIBRE\'");
if (rs.next()) {int act = sentencia.executeUpdate("UPDATE BILLETES"+" SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+" WHERE NUMERO="+rs.getString("NUMERO")+" AND ESTADO='LIBRE'");
if (act>0) jTextArea1.append("Asignado. \nReferencia: "+n+"\n");else jTextArea1.append("Error al asignar billete"); }}
public static void main (String []arg) {PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES();b.setVisible(true);}}
LÓGICA DEL NEGOCIO
A. Goñi. Dpto. LSI, UPV/EHU
12
Arquitectura lógica del software en niveles
NIVEL DE PRESENTACIÓN
INTERFAZ GRÁFICO DE USUARIO:
Frame o Applet
Nombre:
Pedir Billete
public class GBimplements GestorBilletes {
... public Billete getBillete
(String nom) {...}
NIVEL DE LÓGICA DEL NEGOCIO
CLASES CON OPERACIONES PROPIAS DEL NEGOCIO
- inicializarSala- getBillete,...
Aquí se pueden aplicar reglas del negocio: por cada 10 billetes comprados se regala uno, etc...
NIVEL DE DATOS
SELECT ...INSERT ...
BASE DE DATOS
ES MEJOR SEPARAR EL CÓDIGO EN NIVELES: USAR CLASES DISTINTAS
A. Goñi. Dpto. LSI, UPV/EHU
13Arquitectura lógica del software en niveles
• NIVEL DE PRESENTACIÓN– contiene componentes que implementan las interfaces
de usuario y la interacción con el mismo– se construye mediante clases (ej: Frames, Applets),
páginas HTML, JSPs,…• NIVEL DE LÓGICA DEL NEGOCIO
– contiene componentes que resuelven los problemas del negocio; proporciona servicios u operaciones que implementan las reglas propias del negocio.
– se construye mediante clases Java con los servicios/operaciones de la lógica del negocio
• Se consigue más extensibilidad si la lógica del negocio se define mediante interfaces Java.
• NIVEL DE DATOS– utilizado por el nivel lógica del negocio para conseguir
la persistencia de datos. Es una o más BDs.
A. Goñi. Dpto. LSI, UPV/EHU
14
Arquitectura lógica del software en niveles
• Ventaja: AISLAR UN NIVEL DE LOS OTROS– Se puede cambiar el nivel de presentación minimizando
los cambios en los niveles de lógica del negocio y de datos
– Se puede cambiar alguna de las reglas del negocio con pocos cambios en el resto
– Se puede cambiar la base de datos con pocos cambios en el resto
UNA ARQUITECTURA LÓGICA DEL SOFTWARE EN VARIOS NIVELES FAVORECE LA EXTENSIBILIDAD
Y REUTILIZACIÓN DEL SOFTWARE
A. Goñi. Dpto. LSI, UPV/EHU
15
El análisis y diseño de los casos de uso seguía una filosofía en varios niveles…
A. Goñi. Dpto. LSI, UPV/EHU
16Los diagramas de colaboración (análisis) del PUD siguen filosofía 3 niveles
NIVEL DE PRESENTACIÓN
NIVEL DE LÓGICA DEL NEGOCIO
NIVEL DE DATOS
A. Goñi. Dpto. LSI, UPV/EHU
17Los diagramas de colaboración (análisis) del PUD siguen filosofía 3 niveles
• Clases FRONTERA
• Clases CONTROL
• Clases ENTIDAD
NIVEL DE PRESENTACIÓN
NIVEL DE LÓGICA DEL NEGOCIO
NIVEL DE DATOS
representan
representan
representan
A. Goñi. Dpto. LSI, UPV/EHU
18
: Usuario : PedirBillete
Proporcionar nombre y solicitar billete
: GestorBilletes
getBillete(nombre)
: GestorBD
executeQuery:=executeQuery( P1)
: ResultSet
new()
next()
next()
[hay libres] : get("NUMERO")
executeUpdate:=executeUpdate(P2)
num
b : Billete
new(num, nom)
[no hay libres]: new(-1, "")
b
Y también los de secuencia (diseño)
Presentación
Lógica del Negocio
Datos
A. Goñi. Dpto. LSI, UPV/EHU
19Arquitectura física del software en niveles
• La separación FÍSICA de los niveles lógicos admite distintas posibilidades:
• Arquitectura en 2 niveles físicos– 2 de los niveles se juntan en un nodo– 2 posibilidades:
• la lógica del negocio se junta con la presentación• parte de la lógica del negocio se junta con los datos
• Arquitectura en 3 niveles físicos– Cada nivel lógico en un nodo distinto
• Aplicaciones de más niveles físicos – nivel de presentación instalado en el servidor
Web y ejecutado en cliente (navegador Web)
A. Goñi. Dpto. LSI, UPV/EHU
20
Arquitectura física en 2 niveles: cliente gordo/servidor flaco• El nivel de presentación y el de la lógica
del negocio se unen en un nodo. En el otro queda el nivel de datos.
NIVEL DE PRESENTACIÓN
NIVEL DE LÓGICA DEL NEGOCIO
NIVEL DEDATOS
CLIENTE SERVIDOR
• Comunicación entre Cliente y Servidor en SQL• Se necesitan APIs como por ejemplo JDBC y/o ODBC• Deben instalarse DRIVERS de la BD en todos los clientes
A. Goñi. Dpto. LSI, UPV/EHU
21
CLIENTEpublic class PedirBillete2NivCliGordo extends JFrame {GestorBilletes2NivCliGordo gestorBilletes; void jButton1_actionPerformed(ActionEvent e) {
int res = gestorBilletes.getBillete(jTextField1.getText()).getNum();if (res<0) jTextArea1.append("Error al asignar billete");else jTextArea1.append("Asignado. \nReferencia: "+res+"\n");} }
public class GestorBilletesBDimplements GestorBilletes2NivCliGordo
{ public GestorBilletesBD() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes");}public Billete getBillete(String nom){ResultSet rs = sent.executeQuery("SELECT NUMERO…";);
int act = sent.executeUpdate("UPDATE BILLETES …“);if (act>0) return new Billete(n,nom); // Núm. billete asignadoelse return new Billete(-1,"");; } // No había ninguno libre}}}
INSTALAR LA CLASE sun.jdbc.odbc.JdbcOdbcDriver
Y DEFINIR FUENTE DATOS ODBC “Billetes”
SERVIDOR
BD
Presentación
Lógica del NegocioDatos
A. Goñi. Dpto. LSI, UPV/EHU
22
SERVIDOR
BD
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
Sentencia SQLRespuesta
CLIENTEsun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriversun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
¡¡ CADA CLIENTE UNA CONEXIÓN
ABIERTA CON LA BD!!
A. Goñi. Dpto. LSI, UPV/EHU
23
Arquitectura física en 2 niveles: cliente gordo/servidor flaco
• El despliegue de la aplicación es alto: instalar drivers y configurar todos los clientes
• Cambiar de SGBD requiere reinstalar todos los clientes• Cambiar el esquema de la BD puede afectar a los clientes• Cambiar la lógica del negocio implica recompilar y
desplegar en todos los clientes• Costos de conexión con la BD son altos. Cada cliente una
conexión.• La red se puede sobrecargar. Cada sentencia SQL usa la
red.
A. Goñi. Dpto. LSI, UPV/EHU
24Arquitectura física en 2 niveles: cliente flaco/servidor gordo
• Parte de la lógica del negocio se combina con el nivel de datos
NIVEL DE PRESENTACIÓN
NIVEL DE LÓGICA DEL NEGOCIO 1
NIVEL DEDATOS + LÓGICA DEL NEGOCIO 2
CLIENTE SERVIDOR
• Se usan procedimientos almacenados (stored procedures) en la BD. Un procedimiento almacenado puede servir para ejecutar una serie de sentencias SQL.• Comunicación Cliente/Servidor en SQL + Proc. almacenados• Se necesitan APIs como por ejemplo JDBC y/o ODBC• Deben instalarse DRIVERS de la BD en todos los clientes
A. Goñi. Dpto. LSI, UPV/EHU
25
Arquitectura física en 3 niveles
CLIENTE CLIENTE CLIENTE
SERVIDOR SERVIDOR
BASE DE DATOS
Nivel de Presentación
Nivel de Lógica del Negocio(en SERVIDORES DE
APLICACIONES)
Nivel de Datos
A. Goñi. Dpto. LSI, UPV/EHU
26
CLIENTEpublic class PedirBillete extends JFrame {GestorBilletes gestorBilletes; void jButton1_actionPerformed(ActionEvent e) {
int res = gestorBilletes.getBillete(jTextField1.getText()).getNum();if (res<0) jTextArea1.append("Error al asignar billete");else jTextArea1.append("Asignado. \nReferencia: "+res+"\n");} }
public class ServidorGestorBilletesBDimplements GestorBilletes
{ public ServidorGestorBilletesBD() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes");}public Billete getBillete(String nom){ResultSet rs = sent.executeQuery("SELECT NUMERO…";);
int act = sent.executeUpdate("UPDATE BILLETES …“);if (act>0) return new Billete(n,nom); // Núm. billete asignadoelse return new Billete(-1,"");; } // No había ninguno libre}}}
INSTALAR LA CLASE
sun.jdbc.odbc. JdbcOdbcDriver
Y DEFINIR FUENTE
DATOS ODBC “Billetes”
SERVIDOR DATOS
BDPresentación
Lógica del Negocio
Datos
SERVIDOR APLICACIONES
A. Goñi. Dpto. LSI, UPV/EHU
27
sun.jdbc.odbc.JdbcOdbcDriver SERVIDOR DATOS
BD
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTE
SERVIDOR APLICACIONES
SERVIDOR APLICACIONES
SERVIDOR APLICACIONES
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
¡¡ SÓLO LOS SERVIDORES DE APLICACIONES TIENEN
CONEXIONES ABIERTAS CON LA BD!!
A. Goñi. Dpto. LSI, UPV/EHU
28
Arquitectura física en 3 niveles
• Sólo hay que instalar los drivers de la BD en los nodos donde se encuentre la lógica del negocio (nodos servidores)
• Cambiar de SGBD/esquema de la BD NO requiere reinstalar todos los clientes. Sólo los de la lógica del negocio.
• Cambiar la lógica del negocio NO implica recompilar y desplegar en todos los clientes.
• Costos de conexión con la BD NO son tan altos. Los clientes no realizan conexiones con la BD. Sólo los servidores con la lógica del negocio lo hacen.
En general, se MEJORA en EFICIENCIA, MANTENIMIENTO y EXTENSIBILIDAD
A. Goñi. Dpto. LSI, UPV/EHU
29Las aplicaciones Web permiten más niveles
SERVIDOR WEB
SERVIDOR APLICACIONES
BASE DE DATOS
Nivel de Presentación(instalación)
Nivel de Lógica del Negocio
Nivel de Datos
CLIENTE (Nav. Web)
CLIENTE (Nav. Web)
CLIENTE (Nav. Web)
CLIENTE (Nav. Web)
Nivel de Presentación(ejecución)
SERVIDOR APLICACIONES
SERVIDOR WEB
SERVIDOR WEB
A. Goñi. Dpto. LSI, UPV/EHU
30
public class ServidorGestorBilletesBDimplements GestorBilletes
{ public ServidorGestorBilletesBD() {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Billetes");}public Billete getBillete(String nom){ResultSet rs = sent.executeQuery("SELECT NUMERO…";);
int act = sent.executeUpdate("UPDATE BILLETES …“);if (act>0) return new Billete(n,nom); // Núm. billete asignadoelse return new Billete(-1,"");; } // No había ninguno libre}}}
INSTALAR LA CLASE
sun.jdbc.odbc. JdbcOdbcDriver
Y DEFINIR FUENTE
DATOS ODBC “Billetes”
SERVIDOR DATOS
BD
Lógica del Negocio
Datos
SERVIDOR APLICACIONES
CLIENTE
Ejecutar Presentación
Navegador Web
SERVIDOR WEB
Instalar Presentación
HTML + JSP + Bean
A. Goñi. Dpto. LSI, UPV/EHU
31
sun.jdbc.odbc.JdbcOdbcDriver
SERVIDOR DATOS
BD
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTECLIENTE
CLIENTE
SERVIDOR APLICACIONES
SERVIDOR APLICACIONES
SERVIDOR APLICACIONES
sun.jdbc.odbc.JdbcOdbcDriver
sun.jdbc.odbc.JdbcOdbcDriver
EN LOS CLIENTES NO HAY QUE INSTALAR NADA
(EXCEPTO NAVEGADOR WEB+ INTERNET)
SERVIDOR WEB
SERVIDOR WEB
A. Goñi. Dpto. LSI, UPV/EHU
32
Arquitectura física en 3 niveles
• Existe tecnología que permite construir aplicaciones siguiendo esta filosofía de componentes y objetos distribuidos (server-side components)– Entreprise JavaBeans (EJBs) es la arquitectura de
componentes para la plataforma Java 2 Enterprise Edition(J2EE). Definido por Sun Microsystems
• El nivel de presentación se puede dividir más usando Java Applets, Servlets y/o JSPs
– CORBA es una arquitectura para comunicación entre objetos distribuidos a través de ORBs (Object RequestBrokers). Es un estándar definido por OMG.
– DCOM/COM+ y la plataforma .NET es la tecnología equivalente desarrollada por Microsoft
A. Goñi. Dpto. LSI, UPV/EHU
33
Arquitectura física en 3 niveles
• Pero también se puede conseguir con tecnología “sencilla” de Java:– Construcción de interfaces gráficas en Java (AWT y
SWING) para definir el NIVEL DE PRESENTACIÓN– Ejecución del NIVEL DE PRESENTACIÓN EN UN
navegador WEB (Págs. con Applets o Págs. JSPs)– Computación con objetos distribuidos (RMI) para
definir el NIVEL LÓGICA DEL NEGOCIO e invocarlo desde el NIVEL DE PRESENTACIÓN
– Llamadas a JSPs y de ellos a JavaBeans– Conexión con BDs relacionales (JDBC) para
conseguir la comunicación entre NIVEL LÓGICA DEL NEGOCIO y DATOS
A. Goñi. Dpto. LSI, UPV/EHU
34
Preguntas: ¿qué cambios habría que realizar si…?
• Se quisiera cambiar el SGBD de Access a MySQL
• Si se quisiera cambiar la BD: por ejemplo tabla BILLETES => ENTRADAS
• Quisiéramos una nueva regla del negocio: no permitir comprar más de 6 entradas a la misma persona
• Se desea que la respuesta salga en otra ventana
A. Goñi. Dpto. LSI, UPV/EHU
35
2. Construcción de interfaces gráficas en Java
AWT y Swing
A. Goñi. Dpto. LSI, UPV/EHU
36
Índice
• Introducción– Objetivos– La jerarquía de clases: patrón de diseño Composite
• Componentes principales– Contenedores de AWT/Swing– Componentes de AWT/Swing– Administradores de diseño
• Gestión de Eventos– Eventos de bajo y alto nivel– Listeners– Adapters
• Separación entre Nivel de Presentación y Lógicadel Negocio usando interfaces Java.
A. Goñi. Dpto. LSI, UPV/EHU
37
Introducción• Es interesante disponer de herramientas
de ayuda para la construcción de interfaces gráficas de usuario (GUI).
• Java proporciona clases para conseguir:– Diseño y programación de interfaces fácil y
rápido.– Diseño de Applets para la Web.
• En concreto, Java proporciona– clases AWT (Abstract Windowing Toolkit)– clases Swing
• Swing es posterior a AWT y tiene más componentes
A. Goñi. Dpto. LSI, UPV/EHU
38
Introducción
• Objetivos– Entender la jerarquía de clases diseñada en
Java que permite construir interfaces de usuario– Entender cómo se realiza la gestión de eventos– NO es objetivo aprender los nombres de todas
las clases, listeners... Al fin y al cabo se pueden construir interfaces de usuario usando herramientas de desarrollo Java (ej: JDeveloper)
A. Goñi. Dpto. LSI, UPV/EHU
39
AWT. Componentes principales
• Jerarquía de clases de AWT:
COMPONENTE
CONTENEDOR (todo contenedor es un componente)
Applet
A. Goñi. Dpto. LSI, UPV/EHU
40
La jerarquía de clases de AWT sigue un patrón de diseño COMPOSITE
Componente
Contenedor
Un contenedor se compone de varios componentes, los cuales pueden ser componentes concretos o pueden ser contenedores. Estos contenedores pueden estar a su vez compuestos de varios componentes.
ComConc1 ComConcN
ContConc1 ContConcM
add (Componente c)
Clase Contenedor
-- el método add añade-- componentes-- al contenedor
A. Goñi. Dpto. LSI, UPV/EHU
41
La jerarquía de clases de AWT sigue un patrón de diseño COMPOSITE
COMPONENTE
CONTENEDOR (todo contenedor es un componente)
Applet
Las posibilidades son infinitas…
- Una ventana formada por 2 cajas de texto, 2 campos de texto, 3 botones, 1 panel que contenga 5 casillas de validación y una lista desplegable.-Una ventana formada por 2 etiquetas, 2 campos de texto y un botón-…Además, añadir nuevos tipos de contenedores y de componentes no sería muy costoso (estaríamos ante una solución extensible)
A. Goñi. Dpto. LSI, UPV/EHU
42
Un diseño de clases como este sería francamente malo …
Frame
Button
CheckBox
TextField…
- Se necesitarían métodos addButton, addCheckBox, addTextField,addFrame en la clase Frame (y los correspondientes a todos los que faltan)- Además el diagrama está muy incompleto, ya que un Button puede sercomponente de un Panel, Dialog, … - Si se quisiera añadir un nuevo componente XXX, habría que cambiar laclase Frame y añadir el método addXXX (nada extensible)
**
*
*
A. Goñi. Dpto. LSI, UPV/EHU
43
Componentes principales de Swing
JComponent
JFrameJWindow
JPanelJDialog
JList JComboBox
JMenuBar
JTextField, JTextArea, JButton…
Applet
JApplet
A. Goñi. Dpto. LSI, UPV/EHU
44
Contenedores
• El contenedor más importante es el Frame/JFrame, pero también hay otros como Panel/JPanel y Dialog/JDialog.
• Clases Frame/JFrame– Ventana lisa a la que se le puede añadir título y ofrece los iconos
para maximizar, minimizar y destruir.– Es el único contenedor al que se le pueden insertar menús
• Clases Panel/JPanel– Son los contenedores genéricos que sirven para agrupar
componentes. Es la clase que se utiliza para insertar contenedores dentro de otros contenedores (subpaneles dentro de paneles)
– La clase JFrame de Swing incluye de manera automática un Panel. La clase Frame de AWT NO.
A. Goñi. Dpto. LSI, UPV/EHU
45
Para acceder al JPanelasociado al JFrame
A. Goñi. Dpto. LSI, UPV/EHU
46
jButton1
jPanel2
jTextArea1
jComboBox1jPanel4
jPanel1
jPanel3jRadioButton1
jRadioButton2
A. Goñi. Dpto. LSI, UPV/EHU
47
Componentes principales de AWT / Swing
• Clases TextField / JTextField– área de entrada de texto de una línea
• Clases TextArea / JTextArea– permite introducir varias líneas de texto– también puede usarse para mostrar texto– TextArea implementa un scroll vertical y
horizontal por cada área de texto– JTextArea no añade automáticamente un
scroll. Hay que añadir el JTextArea a un JScrollPane
A. Goñi. Dpto. LSI, UPV/EHU
48
JDeveloper genera elcódigo añadiendo el métodojbInit y capturando cualquierposible excepción. No lo pondremos así en los siguientesejemplos por ahorrar espacio.
A. Goñi. Dpto. LSI, UPV/EHU
49
Componentes principales de AWT / Swing
• Clases Button / JButton– Creación de botones. Un botón nos
permitirá realizar algún tipo de acción cuando sea pulsado.
• Clases Label / JLabel– Pueden mostrar información– Se suelen utilizar junto con los campos de
texto.
A. Goñi. Dpto. LSI, UPV/EHU
50
JFrame
A. Goñi. Dpto. LSI, UPV/EHU
51
Componentes principales de AWT / Swing
• Clases Checkbox/JCheckBox/JRadioButton– Las casillas de verificación permiten ofrecer al
usuario la posibilidad de activar/desactivar opciones.
– Los JRadioButton pueden añadirse a ButtonGroup si se debe ESCOGER SÓLO UNA OPCIÓN
– En AWT puede conseguirse el mismo resultado si los Checkbox se definen dentro de un mismo Checkboxgroup
A. Goñi. Dpto. LSI, UPV/EHU
52
A. Goñi. Dpto. LSI, UPV/EHU
53
Componentes principales de AWT / Swing
• Clases List / JList– Las listas desplazables permiten introducir
una serie de opciones que después el usuario puede elegir. En ocasiones son utilizadas para evitar la saturación de componentes en la pantalla.
– El List de AWT incluye un scroll que aparece cuando los elementos en la lista no caben en el espacio asignado al List.
– El JList no. Hay que añadirlo a un JScrollPane.
A. Goñi. Dpto. LSI, UPV/EHU
54
Pero sólo si se hace antes de que se muestre el JFrame
b.elementos.addElement(“C++”); aquí no funcionaría
Con vector no funciona si la lista es “dinámica”
A. Goñi. Dpto. LSI, UPV/EHU
55
Por ejemplo, javax.Swing ofrece la clase DefaultListModel, que proporciona los mismos métodos que Vector
Para listas “dinámicas” usar un ListModel
A. Goñi. Dpto. LSI, UPV/EHU
56
A. Goñi. Dpto. LSI, UPV/EHU
57
Componentes principales de AWT / Swing
• Clases Choice / JComboBox– Esta clase se utiliza para crear menús de
opciones.– Su ventaja es el poco espacio que ocupan
los menus desplegables en pantalla.
A. Goñi. Dpto. LSI, UPV/EHU
58
A. Goñi. Dpto. LSI, UPV/EHU
59
JTable
Modificar valores en celdas…
Se puede redimensionar…
JTable para mostrar y editar tablas de datos
A. Goñi. Dpto. LSI, UPV/EHU
60
Componentes principales de AWT / Swing
• Creación de menús en Swing– La clase JFrame es el único contenedor que
puede alojar a una barra de menús.– La clase JMenuBar permite crear la barra de
menús sobre la que se insertarán los menús.– La clase JMenu permite crear menús a los
que se les da un nombre y que muestran “elementos” en una ventana desplegable
– Los “elementos” del menú pueden ser objetos de JMenuItem o de JMenu (para menús en cascada).
• En AWT existen otras clases similares
A. Goñi. Dpto. LSI, UPV/EHU
61
Menús en Swing
JMenuBar
JMenuJMenu
JMenuItem JMenuItem
A. Goñi. Dpto. LSI, UPV/EHU
62
JDeveloper ayuda un poco…
A. Goñi. Dpto. LSI, UPV/EHU
63
Menús en AWT
Objeto de MenuBar
Objeto de Menu
Objeto de Menu
Objeto de MenuItem
Objeto de MenuShort
Objeto de CheckboxMenuItem
A. Goñi. Dpto. LSI, UPV/EHU
64
A. Goñi. Dpto. LSI, UPV/EHU
65
Administradores de diseño: Layout
• Sirven para decidir dónde se coloca un componente dentro del contenedor
contenedor.add(componente);• FlowLayout (administrador por defecto para Panel)
– va añadiendo los componentes en una línea hasta que se termina y pasa a la siguiente
• BorderLayout (administrador de Frame y Dialog)– añade los componentes en 5 áreas: norte, sur,
oeste, este y centro• El administrador por defecto se puede cambiar:contenedor.setLayout(new BorderLayout());
A. Goñi. Dpto. LSI, UPV/EHU
66
Administradores de diseño: Layout
• Si se desea colocar el componente en unas determinadas coordenadas, entonces hay que quitar el administrador de diseñocomponente.setLayout(null); // o setLayout(new XYLayout());
• Suponiendo que this es un contenedor y textField1 un componente suyosetLayout(null);textField1.setBounds(15,20,50,60);
lo coloca en: x y anchura altura
A. Goñi. Dpto. LSI, UPV/EHU
67
Panel con BorderLayout
Label en BorderLayout.NORTH
Panel con FlowLayout situado en BorderLayout.SOUTH
Panel con GridLayout(4,3) situado en BorderLayout.CENTER
A. Goñi. Dpto. LSI, UPV/EHU
68
jPanel1
jPanel2
jPanel4
A. Goñi. Dpto. LSI, UPV/EHU
69
Ventajas al definirlo conadministradores de diseño: se redibujan loscomponentesautomáticamente al cambiar el tamaño de la ventana.
A. Goñi. Dpto. LSI, UPV/EHU
70
Sin administrador de diseño. Se dan lascoordenadas de todos loscomponentes (usando una herramienta visual es fácil)
A. Goñi. Dpto. LSI, UPV/EHU
71
Como desventaja clara, es queal redimensionar el Frame, loscomponentes se quedan dondeestaban. Se podría programarel evento asociado a redimensionar la ventana y recalcular las coordenadas…
A. Goñi. Dpto. LSI, UPV/EHU
72
Otros contenedores
• Clases Dialog/JDialog– Ventana que permite leer datos del usuario– Puede asignársele la característica de ser MODAL, para
no permitir cambiar a otra ventana mientras esté activa.
• Clase FileDialog (AWT) / JFileChooser (Swing)– Ventana que permite abrir/guardar ficheros (modos
FileDialog.LOAD y FileDialog.SAVE)– En AWT, se utiliza la misma ventana de diálogo del
Sistema Operativo en el que se está ejecutando la máquina virtual Java
– Ofrece ya cierta funcionalidad. No hay que reprogramar el caso en el que se intenta sobreescribir un fichero (muestra ventana de alerta)
A. Goñi. Dpto. LSI, UPV/EHU
73
Ventana MODAL: hastaque no se cierre no puedecambiarse de ventana
modal a true
A. Goñi. Dpto. LSI, UPV/EHU
74
Necesario asociar el FileDialog a un Frame “padre”,pero no es necesario llamar a getDirectory/File desde él
A. Goñi. Dpto. LSI, UPV/EHU
75
Gestión de eventos
• Al diseñar una interfaz gráfica hay que tener en cuenta que se producirán ciertos EVENTOS como consecuencia de las acciones del usuario.
• Por lo tanto, el programador tendrá que preparar una serie de ACCIONES para procesar los eventos del usuario.
A. Goñi. Dpto. LSI, UPV/EHU
76
Eventos
• Evento es un suceso– generado por una acción del usuario– que afecta a algún componente de la
interfaz
• Ejemplos de eventos:– pulsar una tecla, mover el ratón, cambiar el
formato de una ventana, cerrar una venta, minimizar una ventana, pulsar un botón, se pierde (o gana) el foco en un componente, se cambia el valor de un área de texto, seleccionar un item en el menú, etc.
A. Goñi. Dpto. LSI, UPV/EHU
77
Tipos de eventos
• Eventos de bajo nivel– Relacionados con aspectos físicos de la interfaz
de usuario. Ejemplos: pulsación de teclas, movimientos de ratón, hacer click, ganar/perder el foco en un componente, abrir/cerrar ventana..
• Eventos de alto nivel o semánticos– Tienen que ver con la semántica de los
componentes. Ejemplos: pulsar un botón, cambiar el texto de un campo, seleccionar un item en un menú/lista/choice
– Generalmente son combinaciones de eventos de bajo nivel.
A. Goñi. Dpto. LSI, UPV/EHU
78
Los eventos son objetosLos eventos de bajo nivel son objetos de clases• ContainerEvent
– se producen cuando se añaden/eliminan componentes• FocusEvent
– se generan cuando el componente ha ganado o perdido el enfoque (foco) del teclado
• InputEvent (con subclases KeyEvent y MouseEvent)– se generan cuando el usuario pulsa una tecla, mueve
el ratón o hace click con él• WindowEvent
– se generan cuando se usa alguno de los controles de ventana (minimizar, cerrar, …)
Estas clases son subclases de java.awt.AWTEvent
A. Goñi. Dpto. LSI, UPV/EHU
79
Los eventos son objetos
Los eventos de alto nivel son objetos de clases• ActionEvent
– se producen cuando se realizan acciones específicas sobre componentes: ej: pulsaciones de botones
• AdjustmentEvent– se generan cuando una barra de desplazamiento cambia
• ItemEvent– se generan cuando el usuario cambia una elección, una lista
o casilla de verificación (Choice,List,CheckBox)• TextEvent
– se generan cuando cambia el texto en un componente TextArea o TextField
Estas clases son subclases de java.awt.AWTEvent
A. Goñi. Dpto. LSI, UPV/EHU
80
Interfaces Listener• Para gestionar eventos, Java proporciona
unas interfaces “oyentes” (Listeners), donde cada una de ellas contiene métodos que hay que implementar.
• La implementación proporcionada para cada método es la respuesta apropiada a cada evento.
• Si sobre un objeto gráfico queremos controlar cierto tipo de eventos, le asignaremos un “listener”
objGraf.addXXXListener(objListener)
A. Goñi. Dpto. LSI, UPV/EHU
81
obj1.addXXXListener(obj2);
obj1 contiene una referencia a un OBJETO GRÁFICO (botón, ventana, lista desplegable, checkbox, etc) sobre el que se quiere definir un comportamiento ante EVENTOS
obj2 contiene una referencia a un objeto de una clase que implementa el interface XXXListener. public interface XXXListener {....void accionYYY (AWTEvent e);
}
El objeto oyente ejecutará el método correspondiente a la acción (Ej.: accionYYY) usando el objeto Evento generado como parámetro
En tiempo de ejecución sucede un EVENTO que afecta al objeto de obj1
Se crea un objeto evento(AWTEvent)y se pasa el control al objeto oyente (el de obj2)
A. Goñi. Dpto. LSI, UPV/EHU
82
Tras pulsar el botón
OyenteBoton es INNER CLASS (clase definida dentro de otra). Por eso se puede acceder a los atributos jPanel1, jButton1,…
A. Goñi. Dpto. LSI, UPV/EHU
83
Asociar componentes gráficos con Listeners
• A cada componente gráfico tenemos que decirle qué interfaz Listener queremos implementar: addXXXListener()
• Por ejemplo:– addActionListener(ActionListener oyente)– addItemListener(ItemListener oyente)
• NO ES NECESARIO aprenderse losdistintos tipos de Listeners, si se usa una herramienta visual de desarrollo.
A. Goñi. Dpto. LSI, UPV/EHU
84
1) Hacer click en el componente
2) Seleccionar el Evento (actionPerformed)y hacer click
3) Escribir el código donde indica JDeveloper
A. Goñi. Dpto. LSI, UPV/EHU
85
Clases Adapter
• Algunos Listeners tienen varios métodos, pero tal vez no queramos implementarlos todos (porque no queremos responder a todos los tipos de eventos posibles).
• Sin embargo, Java obliga a implementar todos los métodos de una interfaz– Conclusión: muchas veces se proporcionarán
implementaciones vacías a los métodos.
• Por eso, Java ofrece al programador unas clases adaptadoras (Adapter) que implementan todos los métodos de las interfaces (dejándolos vacíos)
• Usando una herramienta visual NO es problema
A. Goñi. Dpto. LSI, UPV/EHU
86
Tras pulsar el botón
JDeveloper genera las clases Oyente comoINNER CLASS sin nombre
A. Goñi. Dpto. LSI, UPV/EHU
87
button1.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {
button1_actionPerformed(e);}
});
void button1_actionPerformed(ActionEvent e) {textArea1.setText("Opción: "+checkboxGroup1.getCurrent().getLabel());
}
ESTE CÓDIGO SE GENERA DE MANERA AUTOMÁTICA CON JDeveloper
LA ACCIÓN HAY QUE PROGRAMARLA, CLARO
Definición de una clase SIN NOMBRE que implementa el interfaceActionListener
A. Goñi. Dpto. LSI, UPV/EHU
88
A. Goñi. Dpto. LSI, UPV/EHU
89
Se puede usar un único método para tratar loseventos de los dos JRadioButton. El texto sepuede obtener del objeto EVENTO !!
A. Goñi. Dpto. LSI, UPV/EHU
90
Se puede usar un único método para tratar loseventos de los dos JRadioButton. El texto se puedeobtener del objeto EVENTO (ActionEvent e)
Para obtener información de contexto del evento (como la etiqueta del componentegráfico sobre el que se ha producido el evento)
A. Goñi. Dpto. LSI, UPV/EHU
91Inicialmente… Cuando entra el ratón en el botón
Al hacer “drag” dentro del botón Al salir el ratón del botón
Punto donde seencuentra el ratón
A. Goñi. Dpto. LSI, UPV/EHU
92
A. Goñi. Dpto. LSI, UPV/EHU
93
Cada vez que se escribe uncarácter en la caja de texto, seañade al área de texto y se borra de la caja de texto. Cada 25 caracteres se salta de línea en elárea de texto.
jTextField1
jTextArea1
A. Goñi. Dpto. LSI, UPV/EHU
94
Separación entre Nivel de Presentación y Lógica del Negocio
• Es conveniente separar el nivel de presentacióndel de la lógica del negocio
• El nivel de presentación está formado por lasclases de AWT/Swing
• La llamada al nivel lógica del negocio se realizaráen algún método de respuesta a un evento.
• Se puede incluir un atributo que contenga el objetocon la lógica del negocio (DE TIPO interfaceJAVA)– Podría conseguirse cambiar la lógica del negocio SIN NECESIDAD
DE cambiar el nivel de presentación. Incluso sin RECOMPILAR, e incluso haciéndolo EN TIEMPO DE EJECUCIÓN (sin relanzar elobjeto de presentación)
A. Goñi. Dpto. LSI, UPV/EHU
95
Clase Presentacion
logNe: LogicaNegocio
setLogicaNegocio(l: LogicaNegocio)
Interface LogicaNegocio
hacerX(… )hacerY(… )
usa
En alguno de los métodos de la clasePresentación (los que responden a eventos)se usará:
logNe.hacerX(…)o bien
logNe.hacerY(…)
A. Goñi. Dpto. LSI, UPV/EHU
96
Clase Presentacion
logNe: LogicaNegocio
setLogicaNegocio(l: LogicaNegocio)
Interface LogicaNegocio
hacerX(… )hacerY(… )
usa
clase LogicaNegocioConcreta
hacerX(… ) // ImplementadahacerY(… ) // Implementada
Presentacion p = new Presentacion();p.setLogicaNegocio(new LogicaNegocioConcreta());p.setVisible(true);
PARA CREAR LA INTERFAZ GRÁFICA CON SU LÓGICA DEL NEGOCIO:
A. Goñi. Dpto. LSI, UPV/EHU
97
Clase Presentacion
logNe: LogicaNegocio
setLogicaNegocio(l: LogicaNegocio)
Interface LogicaNegocio
hacerX(… )hacerY(… )
usa
clase LogicaNegocionNueva
hacerX(… ) // ImplementadahacerY(… ) // Implementada
Si ahora se quisiera cambiar la lógica del negocio, bastaría conhacer: p.setLogicaNegocio(new LogicaNegocioNueva());
NO HACE FALTA RECOMPILAR LA CLASE Presentacion, y, si se conoce la referencia del objeto, SE PUEDE CAMBIAR LA LÓGICA DEL NEGOCIO EN TIEMPO DE EJECUCIÓN
A. Goñi. Dpto. LSI, UPV/EHU
98
A. Goñi. Dpto. LSI, UPV/EHU
99
Sólo falta proporcionarla clase que implementeGestorBilletes…(con o sin nombre)
A. Goñi. Dpto. LSI, UPV/EHU
100
clase GestorBilletesImp
Clase PedirBillete
gestorBilletes: GestorBilletes
setGestorBilletes(GestorBilletes)
Interface GestorBilletes
getBillete(String):intusa
getBillete(String):int// Implementada
A. Goñi. Dpto. LSI, UPV/EHU
101
3. Conexión con BDs relacionales enJava
JDBC
A. Goñi. Dpto. LSI, UPV/EHU
102
Índice
• Introducción• Arquitectura para JDBC. Tipos de
drivers• Las clases e interfaces de JDBC• Ejemplo de uso de JDBC: un servidor
de billetes• Conexión con el nivel de presentación
A. Goñi. Dpto. LSI, UPV/EHU
103
Introducción
• JDBC (Java Database Connectivity) es un API; un conjunto de clases y métodos que se encuentran en el paquete java.sql y que sirven para– establecer conexiones con bases de datos– enviar sentencias SQL a dichas BDs– procesar los resultados
• Los vendedores de SGBD deben escribir “drivers”o controladores para JDBC, o al menos, permitir que programas que usan el API JDBC puedan conectarse con sus BDs.Hay muchos: http://industry.java.sun.com/products/jdbc/drivers
A. Goñi. Dpto. LSI, UPV/EHU
104
JDBC
• JDBC ofrece igual funcionalidad que ODBC (Open Database Connectivity) de Microsoft– El problema es que ODBC tiene interfaz C
• La gran mayoría de SGBD disponen ya de drivers para trabajar con ODBC
• En el JDK se suministra un puente JDBC-ODBC para convertir llamadas JDBC a ODBC y poder acceder así a BDs que ya tienen un driver ODBC mediante JDBC– En el caso de hacerlo así, hay que registrar la BD
correspondiente para ser usada con ODBC
A. Goñi. Dpto. LSI, UPV/EHU
105
Arquitectura para JDBC: 4 tipos de drivers
Aplicación JAVA
API de JDBC
JDBC Driver Manager
Driver JDBC
SGBD
API de JDBC Driver
SGBD
Driver puenteJDBC-ODBC
Driver ODBC
Distintos tipos de Driver JDBC:A) Traduce a APIs nativas del
SGBD. B) Se comunica con aplicación
intermedia en el servidorque traslada peticiones al SGBD que se trate
C) Se comunica directamentecon el SGBD
A. Goñi. Dpto. LSI, UPV/EHU
106
SGBD X
BD 1
BD 2
APLICACIÓN
Cargar Driver SGBD X
Abrir Conexión BD 1
Crear Statement
Enviar Sentencia SQL
ConnectionConnection c;c;
StatementStatement ss
Enviar/ Enviar/ Recibir Recibir SQLSQL
A. Goñi. Dpto. LSI, UPV/EHU
107
Cargar el Controlador/Driver
• Para cargar un controlador se puede usar el método forName() de la clase Class (carga clases Java)Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);– carga el puente JDBC-ODBCClass.forName(“org.gjt.mm.mysql.Driver”);– carga el Driver JDBC para trabajar con el SGBD
mySQL• La clase java.lang.Class permite crear
instancias de clases en tiempo de ejecución:Object o =
Class.forName(“org.gjt.mm.mysql.Driver”).newInstance();
– Crea una instancia de la clase org.gjt.mm.mm.mysql.Driver y la asigna al objeto o
A. Goñi. Dpto. LSI, UPV/EHU
108
La clase DriveManager• Sirve para registrar los controladores o drivers
DriverManager.registerDriver(new sun.jdbc.odbc.JdbcOdbcDriver());
• No es necesario hacerlo si se ha cargado el Drivercon Class.forName
• Además puede establecer conexiones con BDsConnection c = DriverManager.getConnection(
String dir,String usu,String clave)
– dir identifica a la BD. Dependiendo del SGBD usado tendrá una forma u otra jdbc:subprotocolo//servidor:puerto/base de datos
– usu y clave son nombre de usuario y clave, si hay
A. Goñi. Dpto. LSI, UPV/EHU
109
La interfaz Connection
• Una vez que tenemos una conexión abierta, se pueden lanzar sentencias SQL desde el programa Java.
• Para ello hay que crear objetos “Statement”Statement s = c.createStatement();
// c contiene un objeto de Connection
• Las conexiones hay que cerrarlas cuando no se necesitan (no queremos enviar más sentencias SQL a la BD) para liberar recursosc.close();
A. Goñi. Dpto. LSI, UPV/EHU
110
La interfaz Connection
• Por defecto, toda sentencia SQL enviada a un Statement termina con un commit si tiene éxito.
• Si se quiere que varias sentencias SQL formen una transacción, se puede hacer así:c.setAutoCommit(false);// Enviar las sentencias SQL que forman// la transacciónEjecutar c.commit();
o bien c.rollback();
A. Goñi. Dpto. LSI, UPV/EHU
111
Interfaz Statement• Sirve para enviar preguntas SQL a la BDint i = s.executeUpdate(String sql);
// s contiene un objeto de Statementejecuta una sentencia SQL INSERT, UPDATE o DELETE y devuelve el número de tuplas afectadas
ResultSet r = s.executeQuery(String sql);ejecuta una sentencia SQL SELECT y devuelve el resultado en un objeto ResultSet
NOTA: sólo puede haber un ResultSet “abierto” sobre un objeto “Statement”CONCLUSIÓN: si queremos trabajar con dos preguntasSQL a la vez se necesita definir dos statement diferentes
A. Goñi. Dpto. LSI, UPV/EHU
112
Interfaz Statement
• Se puede cerrar un statement, para liberar recursos:s.close();
// s contiene un objeto de Statement
• Se puede limitar el número máximo de tuplas que queremos que nos devuelva el SGBD:s.setMaxRows(maxTuplas);
• Se puede limitar el número máximo de segundos que queremos que espere el Driver:s.setQueryTimeout(maxSegundos);
A. Goñi. Dpto. LSI, UPV/EHU
113
Interfaz ResultSet• Sirve para trabajar con las respuestas a las
preguntas SQL realizadasboolean b = r.next();
// r es un objeto de tipo ResultSet
se posiciona en la siguiente tupla del resultado; devuelvetrue si hay o false si se ha llegado al final
• Existen métodos get que devuelven el valor de la tupla actual correspondiente a un atributo de la tabla respuesta. – El atributo se puede identificar por el nombre dado
en la parte SELECT de la pregunta o por su posición en la misma
– El tipo del atributo puede ser conocido o no
A. Goñi. Dpto. LSI, UPV/EHU
114
Interfaz ResultSet
String s = r.getString(numColumna);String s = r.getString(nombreColumna);int i = r.getInt(numColumna);int i = r.getInt(nombreColumna);boolean b = r.getBoolean(numColumna);boolean b = r.getBoolean(nombreColumna);
// si conocemos el tipo del atributo
Object o = r.getObject(numColumna);Object o = r.getObject(nombreColumna);
// si no conocemos el tipo del atributo
A. Goñi. Dpto. LSI, UPV/EHU
115
ResultSetResultSet rsrs = = s.executeQuerys.executeQuery(“SELECT * FROM BILLETES”);(“SELECT * FROM BILLETES”);
rs.nextrs.next()()truetrue
intint i = i = rs.getIntrs.getInt(1);(1);11
StringString estest = = rs.getStringrs.getString(2);(2);
OCUPADOOCUPADO
A. Goñi. Dpto. LSI, UPV/EHU
116
ResultSetResultSet rsrs = = s.executeQuerys.executeQuery(“SELECT * FROM BILLETES”);(“SELECT * FROM BILLETES”);
rs.nextrs.next()()truetrue
intint i = i = rs.getIntrs.getInt(“NUMERO”);(“NUMERO”);00
StringString estest = = rs.getStringrs.getString(“ESTADO”);(“ESTADO”);
OCUPADOOCUPADO
A. Goñi. Dpto. LSI, UPV/EHU
117
ResultSetResultSet rsrs = = s.executeQuerys.executeQuery(“SELECT * FROM BILLETES”);(“SELECT * FROM BILLETES”);
rs.nextrs.next()()truetrue
ObjectObject i = i = rs.getObjectrs.getObject(1);(1);i.toStringi.toString()()
StringString estest = = rs.getStringrs.getString(“ESTADO”);(“ESTADO”);
LIBRELIBRE
““2”2”
A. Goñi. Dpto. LSI, UPV/EHU
118
ResultSetResultSet rsrs = = s.executeQuerys.executeQuery(“SELECT * FROM BILLETES”);(“SELECT * FROM BILLETES”);
rs.nextrs.next()()falsefalse
A. Goñi. Dpto. LSI, UPV/EHU
119
Usando sentencias con parámetros
• Algunas sentencias SQL se repiten variasveces cambiando sólo algunos valores.– Se pueden parametrizar
Sea c un objeto de ConnectionPreparedStatement s = c.prepareStatement(“SELECT NOMBRE FROM PERSONAS WHERE CIUDAD=? AND EDAD>?”);
s.setString(1,“SS”); // Poner SS en 1er parámetros.setInt(2,25); // Poner 25 en 2º parámetroResultSet r = s.executeQuery(); // ...// Se puede reejecutar s.setString(1,“Bi”);..
A. Goñi. Dpto. LSI, UPV/EHU
120
A. Goñi. Dpto. LSI, UPV/EHU
121
A. Goñi. Dpto. LSI, UPV/EHU
122
A. Goñi. Dpto. LSI, UPV/EHU
123
A. Goñi. Dpto. LSI, UPV/EHU
124
1
2 3
4
Agregar y escoger “MAccess Driver”
Seleccionar una BD Access previamentecreada
A. Goñi. Dpto. LSI, UPV/EHU
125
A. Goñi. Dpto. LSI, UPV/EHU
126
A. Goñi. Dpto. LSI, UPV/EHU
127
EL CÓDIGO ANTERIOR PODRÍA SUSTITUIRSE POREL SIGUIENTE, DONDE SE USA UNA LLAMADA AUNA SENTENCIA SQL PARAMETRIZADA
A. Goñi. Dpto. LSI, UPV/EHU
128
A. Goñi. Dpto. LSI, UPV/EHU
129
Conexión con el nivel de presentación
• La clase ServidorGestorBilletes es una claseque contiene la LÓGICA DEL NEGOCIO– inicializarSala y getBillete
• Y que realiza llamadas al NIVEL DE DATOS – Son todas las sentencias JDBC
• Para realizar la conexión con el NIVEL DE PRESENTACIÓN, bastará con implementar la interfaz utilizada por el mismo y asignar unobjeto de la lógica del negocio al objeto de presentación
A. Goñi. Dpto. LSI, UPV/EHU
130
HAY QUE INDICAR EXPLÍCITAMENTE QUE SE IMPLEMENTA LA INTERFAZ
ASIGNAR ESALÓGICA DEL NEGOCIOAL OBJETO PRESENTACIÓN
CREAR OBJETO DE PRESENTACIÓN
CREAR OBJETO LÓGICA DEL NEGOCIO
A. Goñi. Dpto. LSI, UPV/EHU
131
clase ServidorGestorBilletesBD
Clase PedirBillete
gestorBilletes: GestorBilletes
setGestorBilletes(GestorBilletes)
Interface GestorBilletes
getBillete(String):intusa
getBillete(String):intinicializarSala(int)crearTablaBilletes()
A. Goñi. Dpto. LSI, UPV/EHU
132
4. Mecanismos de serialización en Java
A. Goñi. Dpto. LSI, UPV/EHU
133
Serialización de objetos
• Java ofrece unos servicios de serializaciónde objetos que CONVIERTEN OBJETOS EN SERIES DE BYTES
• Son útiles para:– proporcionar persistencia de objetos, ya que una
vez convertidos los objetos en bytes se pueden guardar en Streams de bytes (ficheros)
– enviar mensajes entre objetos de distintas máquinas (se serializan dichos mensajes)
• Usando sockets, RMI (Remote Method Invocation)
A. Goñi. Dpto. LSI, UPV/EHU
134
Personadni: intnombre: StringsuCoche: Coche
juan:Persona17832423“Juan Pérez”coche1
elena:Persona17114452“Elena Pérez”coche1
coche1:Coche3541 CGH“Citroen C4”<juan,elena>
Cochematricula: Stringmodelo: StringsusProp: Vector
CLASES OBJETOS
Se desea guardar el contenido de los objetos juan y elena en un fichero, o enviarlo por la red…
A. Goñi. Dpto. LSI, UPV/EHU
135
fichero.println(juan.toString());fichero.println(elena.toString());
public class Persona {…public String toString ()
{ return dni+ "/"+nombre+ + "/“+ suCoche.getMat() + "/"+ suCoche.getModelo();}
}
personas.txt17832423/Juan Pérez/3541 CGH/Citroen C417114452/Elena Pérez/3541 CGH/Citroen C4
Por ejemplo, si se quisiera almacenar los objetos en el fichero personas.txt…
… pero hay una pega al almacenar los valores. ¿Cómo se sabe “3541 CGH/Citroen C4” es el MISMO objeto?
PrintWriter fichero = new PrintWriter (new FileWriter("personas.txt"));
A. Goñi. Dpto. LSI, UPV/EHU
136
Serialización de objetos
• Si se quiere que los objetos de una clase se puedan serializar, en la definición de dicha clase hay que indicar que implementa el interfaz java.io.Serializable
• Entonces se pueden leer/escribir objetos en ObjectInputStream/ObjectOutputStreamcon los métodos readObject/writeObject
A. Goñi. Dpto. LSI, UPV/EHU
137
Serialización de objetos
• Para que un determinado atributo de una clase no se serialice hay que declararlo como transient– Por ejemplo un atributo que sea un Stream
• Los métodos writeObject y readObjectfuncionan bien con los tipos básicos, Strings, Arrays, Vector, etc. Pero también se pueden redefinir para una determinada clase
private void writeObject(java.io.ObjectOutputStream stream)
throws IOException;private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException;
A. Goñi. Dpto. LSI, UPV/EHU
138
Serialización de objetos
• Al hacer writeObject de un objeto se serializan todos los objetos contenidos en él, y así recursivamente.
• Hay que tener en cuenta que NO SE SERIALIZAN LOS ATRIBUTOS static
A. Goñi. Dpto. LSI, UPV/EHU
139
fichero.writeObject(juan);fichero.writeObject(elena);
public class Persona implements Serializable{…}
Por ejemplo, si se quisiera almacenar los objetos en el fichero personas.dat…
writeObject escribirá en personas.dat el objeto juan junto con su objeto incrustado coche1, y después escribirá el objeto elena con su objeto incrustado coche1 (¡¡el mismo!!)
ObjectOutputStream fichero = new ObjectOutputStream (new FileOutputStream("personas.dat"));
A. Goñi. Dpto. LSI, UPV/EHU
140
ObjectOutputStream socketComoStream = new ObjectOutputStream (socket.getOutputStream());
socketComoStream.writeObject(juan);socketComoStream.writeObject(elena);
public class Persona implements Serializable{…}
Por ejemplo, si se quisiera enviar los objetos por la red …
writeObject enviará por el socket el objeto juan junto con su objeto incrustado coche1, y después enviará el objeto elenacon su objeto incrustado coche1 (¡¡el mismo!!)
A. Goñi. Dpto. LSI, UPV/EHU
141
Ejemplo de serialización de un vector
• Dado un vector: Vector billetes;• Se puede escribir en el fichero
billetes.datObjectOutputStream sal = new ObjectOutputStream(newFileOutputStream(“billetes.dat”));
sal.writeObject(billetes);• Y se puede leer del fichero billetes.dat
ObjectInputStream ent =new ObjectInputStream(newFileInputStream(“billetes.dat”));
billetes=(Vector)ent.readObject();
A. Goñi. Dpto. LSI, UPV/EHU
142
Nueva lógica del negocio para el ejemplo de PEDIR BILLETES utilizandoMECANISMOS DE
SERIALIZACIÓN para la persistencia
A. Goñi. Dpto. LSI, UPV/EHU
143
clase ServidorGestorBilletesSerializado
Clase PedirBillete
gestorBilletes: GestorBilletes
setGestorBilletes(GestorBilletes)
Interface GestorBilletes
getBillete(String):intusa
getBillete(String):intinicializarSala(int)escribir()leer()
A. Goñi. Dpto. LSI, UPV/EHU
144Nueva lógica del negocio para elejemplo de PEDIR BILLETES. Se pide el billete a un servidor
(que se encuentra en la máquina“host”) por medio de un
SOCKET. Se usan mecanismosde SERIALIZACIÓN para elpaso de parámetros y recogida
de resultados.
A. Goñi. Dpto. LSI, UPV/EHU
145El servidor está a la espera de peticiones de clientes. Recoge los
parámetros y devuelve el resultado pormedio de SOCKETS. Utiliza la clase
ServidorGestorBilletesBD
A. Goñi. Dpto. LSI, UPV/EHU
146
clase GestorBilletesCliente
Clase PedirBillete
gestorBilletes: GestorBilletes
setGestorBilletes(GestorBilletes)
Interface GestorBilletes
getBillete(String):intusa
getBillete(String):int
clase Servidorusa
clase ServidorGestorBilletesBD
getBillete(String):intinicializarSala(int)crearTablaBilletes()
socket
En distintos ordenadores
A. Goñi. Dpto. LSI, UPV/EHU
147
5. Introducción a la computación distribuida conJava RMI
A. Goñi. Dpto. LSI, UPV/EHU
148
Índice• Introducción a RMI• Interfaz remota• Servidor remoto• Cliente• Arquitectura RMI: stubs, skeletons,
rmiregistry, serialización de parámetros/resultados, política de seguridad
• Ejemplo• Conexión entre nivel de presentación,
lógica del negocio y nivel de datos
A. Goñi. Dpto. LSI, UPV/EHU
149
Introducción a RMI
• RMI (Remote Method Invocation) es un API; un conjunto de clases y métodos que se encuentran en el paquete (java.rmi)y que sirven para
– desarrollar aplicaciones distribuidas en Java – que tengan la misma sintaxis y semántica que
aplicaciones no distribuidas• Equivalente a RPC (Remote Procedure Call)• Existen otros estándares como CORBA
– Más extenso ya que sirve para poder llamar a servicios construidos con distintos lenguajes de programación (y no sólo Java)
A. Goñi. Dpto. LSI, UPV/EHU
150
Introducción a RMI
Clase GestorBilletes- listaBilletes: Vector- maxBilletes: int
-- Clase con 1 sola instancia (Singleton)-- El método static getGestor() la devuelve
+ getGestor(): GestorBilletes+ getBillete(nom: String): int// Dev. nº billete asignado o -1 si no hay
Clase Cliente1....
Clase ClienteN....
No es posible realizar lo siguiente en una clase cliente:
GestorBilletes g = GestorBilletes.getGestor();return g.getBillete("Kepa Sola");
Es un objeto de una máquina virtual Java remota
EN EL NODO SERVIDOREN NODOS CLIENTE
A. Goñi. Dpto. LSI, UPV/EHU
151
Introducción a RMI
• Para construir una aplicación Cliente/Servidor donde un cliente acceda a un servicio remoto (clase remota) usando RMI hay que:
• 1.- Definir una interfaz remota• 2.- Implementar dicha interfaz remota
(construir el servidor RMI)• 3.- Implementar el cliente RMI que accede
al servicio remoto
A. Goñi. Dpto. LSI, UPV/EHU
152
Interfaz remota
Interfaz GestorBilletes
-- INTERFAZ REMOTA
+ getBillete(nom: String): int// Dev. nº billete asignado o -1 si no hay
Cliente1....
ClienteN....
RMI permite que se llamen a objetos remotos. Para ello, hay que definir una interfaz REMOTA. Así, en un cliente podría ejecutarse lo siguiente:
GestorBilletes g; // Código para obtener la dirección del objeto// remoto y dejarlo en greturn g.getBillete(“Kepa Sola”);
A. Goñi. Dpto. LSI, UPV/EHU
153
Interfaz Remota
HAY QUE TENER EN CUENTA QUE:• La interfaz remota debe extender java.rmi.Remote• Y todos los métodos definidos en él deben declararse como que pueden lanzar la excepción java.rmi.RemoteException
// GestorBilletes.javaimport java.rmi.*;public interface GestorBilletes
extends Remote{public int getBillete(String nom)
throws RemoteException;}
GestorBilletes.java Interfaz GestorBilletes
-- INTERFAZ REMOTA
+ getBillete(nom: String): intrealiza
Interfaz java.rmi.Remote
-- INTERFAZ REMOTA
A. Goñi. Dpto. LSI, UPV/EHU
154
Servidor Remoto
Interfaz GestorBilletes
-- INTERFAZ REMOTA
+ getBillete(nom: String): int
Interfaz java.rmi.Remote
-- INTERFAZ REMOTA
Clase ServidorGestorBilletes
-- CLASE REMOTA
+ getBillete(nom: String): int
Clase java.rmi.server.UnicastRemoteObject
-- CLASE REMOTA
implementa
extiende extiende
La clase servidor remoto:• implementa los métodos de la interfaz remota• extiende java.rmi.server.UnicastRemoteObject
La clase servidor remoto creará un objeto de sí misma y lo registrará con un nombre (para que objetos de clases clientes accedan a él y ejecuten sus métodos remotamente).
A. Goñi. Dpto. LSI, UPV/EHU
155
Servidor Remoto// ServidorGestorBilletes.javaimport java.rmi.*;import java.rmi.server.UnicastRemoteObject;import java.util.*;public class ServidorGestorBilletes
extends UnicastRemoteObjectimplements GestorBilletes
{ private Vector listaBilletes = new Vector();private static int maxBills = 50;public ServidorGestorBilletes()
throws RemoteException{}public int getBillete(String nom)
throws RemoteException {int num = listaBilletes.size()+1;if (num>maxBills) return -1;listaBilletes.addElement(nom);System.out.println("Asignado billete a: "+nom);return num; }public static void main(String[] args) {...} }
A. Goñi. Dpto. LSI, UPV/EHU
156
Servidor Remoto// Método main de ServidorGestorBilletes.javapublic static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try { ServidorGestorBilletes objetoServidor =
new ServidorGestorBilletes();
String servicio = "//localhost/gestorBilletes";// "//localhost:NumPuerto/NombreServicio"
// Registrar el servicio remotoNaming.rebind(servicio,objetoServidor);
} catch (Exception e) {System.out.println("Error al lanzar el servidor");}
}
A. Goñi. Dpto. LSI, UPV/EHU
157
Cliente
Interfaz GestorBilletes
-- INTERFAZ REMOTA
+ getBillete(nom: String): int
Interfaz java.rmi.Remote
-- INTERFAZ REMOTA
Clase ServidorGestorBilletes
-- CLASE REMOTA
+ getBillete(nom: String): int
Clase java.rmi.server.UnicastRemoteObject
-- CLASE REMOTA
implementa
extiende extiende
La clase cliente:• busca el objeto remoto que le proporciona el servicio que le interesa. Para ello debe conocer el nombre del servicio, pero no la clase remota (no hace new)• pide a dicho objeto que ejecute un método remoto (definido en la interfaz remota)
Clase Cliente
-- CLASE CLIENTE
usa
ges : GestorBilletes
A. Goñi. Dpto. LSI, UPV/EHU
158
Cliente// Cliente.javaimport java.rmi.*;
public class Cliente{ public static void main(String[] args) {System.setSecurityManager(new RMISecurityManager());GestorBilletes objRemoto;
String nomServ = "rmi://localhost/gestorBilletes";// "rmi://DireccionIP:NumPuerto/NombreServicio"
try {objRemoto = (GestorBilletes)Naming.lookup(nomServ);int b = objRemoto.getBillete(args[0]);if (b==-1) System.out.println("No hay billetes");else System.out.println("Obtenido : "+b);
} catch (Exception e) { System.out.println("Error... ");}}}
A. Goñi. Dpto. LSI, UPV/EHU
159
Los clientes RMI siguen un patrón de diseño INTERFACE
Interfaz InterfazRemotausa
Clase Cliente
Permite que la clase cliente ejecute métodos de instancias de otras clases, independientemente de las
mismas (sin siquiera saber cómo se llaman).Incluso pueden ser clases que todavía no estén
implementadas en el momento de escribir el código de la clase Cliente.
A. Goñi. Dpto. LSI, UPV/EHU
160
Arquitectura RMI
RETURN: 5
objRemoto.getBillete("Koldo")
Máquina virtual java CLIENTE
objRemoto @ObjLocalX
objServidor.getBillete("Koldo")
Máquina virtual java SERVIDOR
objServidor @ObjLocalY
1) Hay que conectar el objeto remoto (objRemoto) con el objeto servidor (objServidor) para que las llamadas a métodos del primero sean ejecutadas por el segundo2) Hay que pasar los valores de los parámetros de los métodos del cliente al servidor3) Hay que pasar los resultados de los métodos del servidor al cliente
A. Goñi. Dpto. LSI, UPV/EHU
161
Arquitectura RMI
Stub
Nivel de Referencia Remota
Nivel de Transporte
Skeleton
Nivel de Referencia Remota
Nivel de Transporte
Conexión TCP/IP
Programa Cliente Programa Servidorcall callreturn return
Los objetos Stub y Skeleton se encargan de realizar la conexión y del
paso de parámetros y resultados.
A. Goñi. Dpto. LSI, UPV/EHU
162
Arquitectura RMI
objRemoto.getBillete("Koldo");
Máquina virtual java CLIENTE
objServidor.getBillete("Koldo")
Máquina virtual java SERVIDOR
GestorBilletes objRemoto = (GestorBilletes)Naming.lookup("rmi://IPServidor/gestorBilletes");
@ObjSkelY Objeto SKELETON de la claseServidorGestorBilletes_Skeleton
getBillete
"Koldo"
objServidor @ObjServY Objeto de la claseServidorGestorBilletes
@ObjStubX Objeto STUB de la claseServidorGestorBilletes_Stub
RETURN: 5
lookup BUSCA y OBTIENE el objeto STUB
A. Goñi. Dpto. LSI, UPV/EHU
163
rmic: Generación de stubs y skeletons
rmic ServidorGestorClientes
rmic es una herramienta que genera de manera automática las clases STUB y
SKELETON a partir de la clase remota (ServidorGestorClientes.class)
SE OBTIENEN LAS CLASES:ServidorGestorClientes_Stub.classServidorGestorClientes_Skeleton.class
El ficheroServidorGestorClientes_Stub.classdebe quedar accesible a la máquina cliente. Una posibilidad es copiarlo en ella (ver otra posibilidad más adelante...)
A. Goñi. Dpto. LSI, UPV/EHU
164
Arquitectura RMI
Máquina virtual java situada en IPServidor
GestorBilletes objRemoto = (GestorBilletes)Naming.lookup("rmi://IPServidor/gestorBilletes");
¿Cómo se sabe cuál es la clase STUB de la cual hay que crear un objeto?
GestorBilletes es un interfaceLa clase en este caso es
ServidorGestorBilletes_Stub.class
RMIREGISTRY
....
....
gestorBilletes @ObjServidor ServidorGestorBilletes_Stub
puerto 1099
Naming.rebind("gestorBilletes",objetoServidor);
A. Goñi. Dpto. LSI, UPV/EHU
165
rmiregistry
• Es un servidor de nombres que relaciona objetos con nombres
• Hay que lanzarlo como proceso independiente en la máquina servidor– En la misma máquina que el servidor RMI
• En Unix– rmiregistry & (en Unix)– rmiregistry numPuerto &
• En Windows– rmiregistry [num. puerto]– start rmiregistry [num. puerto]
A. Goñi. Dpto. LSI, UPV/EHU
166
rmiregistry
• También se puede lanzar desde una aplicación Java (en el servidor RMI)java.rmi.registry.LocateRegistry.createRegistry(p)
Crea el proceso rmiregistry en el puerto p. El rmiregistry lanzado no acaba aunque acabe el servidor RMILanza una excepción si el puerto está ocupado
try { java.rmi.registry.LocateRegistry.createRegistry(1099); } catch (Exception e) {System.out.println(“Rmiregistry ya lanzado“+e.toString());}
Código que lanza el rmiregistry y controla la excepción quese puede levantar al reejecutar varias veces el servidor RMI
A. Goñi. Dpto. LSI, UPV/EHU
167
Serialización de parámetros/resultados
• En principio, los stubs y los servidores RMI se pasan los objetos enviados como parámetros y los resultados REALIZANDO UNA COPIA DE SUS VALORES (y de los objetos incluidos en ellos, recursivamente). – No se pasan referencias a un objeto remoto.
• Para ello, se usan los mecanismos de serialización de Java
las clases de dichos objetos deben implementar la interfaz Serializable
A. Goñi. Dpto. LSI, UPV/EHU
168
: PedirBillete
mainServidorGestorBilletesBD
objRemoto:ServidorGestorBilletesBD
new
Rmiregistry
Naming
rebind("localhost:1099/gestorBilletes",objRemoto)
SOCKET("localhost",1099,"gestorBilletes",stub)Naming
lookup("rmi://IpServidor:1099/gestorBilletes")
SOCKET("IPservidor",1099,"gestorBilletes")
SOCKET(stub)
stub: ServidorGestorBilletesBD_Stub
stub
getBillete("Pepe")
SOCKET("IPServidor",PuertoAnonimo,"gestorBilletes","getBillete","Pepe")
SOCKET(numBilleteParaPepe)numBilleteParaPepe
RMIREGISTRY y ServidorGestorBilletesBD en la mismamáquina (IPServidor), pero cada uno en DISTINTAS
MÁQUINAS VIRTUALES JAVA
PresentacionRemoto en otra máquina
RmiRegistry está escuchando en un puerto (1099)
Mirar métodos de LocateRegistry.createRegistry
stub: ServidorGestorBilletesBD_Stub
new(referenciaAObjRemoto)
Se pasa el objeto STUB serializado.El cliente cargará dinámicamente la claseServidorGestorBilletesBD_Stub
exportObject(PuertoAnonimo)
getRef()
referenciaAObjRemoto
A. Goñi. Dpto. LSI, UPV/EHU
169
java.security.policy• Un programa Java debe especificar un gestor
de seguridad que determine su política de seguridad.
• Algunas operaciones requieren que exista dicho gestor. En concreto, las de RMI.– RMI sólo cargará una clase serializable desde otra
máquina si hay un gestor de seguridad que lo permita
– Se puede establecer un gestor de seguridad por defecto para RMI de la siguiente manera:
System.setSecurityManager(new RMISecurityManager());
A. Goñi. Dpto. LSI, UPV/EHU
170
java.security.policy
• El gestor de seguridad por defecto de RMI utiliza una política muy restrictiva. – Sólo se pueden ejecutar STUBs del CLASSPATH local
• Se puede cambiar, indicando a la máquina virtual Java otro fichero de política de seguridad:
java -Djava.security.policy=java.policy Clase
Contenido del fichero java.policy:grant {
permission java.security.AllPermission;};
Nombre de fichero (por ejemplo)
NOTA: ESTO NO ES NECESARIO PARA VERSIONES ANTERIORES AL JDK1.2
A. Goñi. Dpto. LSI, UPV/EHU
171
Para no tener que copiar el STUB en el cliente...
• Al lanzar el CLIENTE hay que dar una URL para que el Naming.lookup acceda al stub allíjava -Djava.rmi.server.codebase=http://...
-Djava.security.policy=...cliente
NOTA: la URL debe acabar con /http://www.ehu.es INCORRECTO http://www.ehu.es/ CORRECTO
A. Goñi. Dpto. LSI, UPV/EHU
172
Servidor Remoto accede a BD// ServidorGestorBilletes.javaimport java.rmi.*;import java.sql.*;
import java.rmi.server.UnicastRemoteObject;import java.util.*;public class ServidorGestorBilletesBD
extends UnicastRemoteObjectimplements GestorBilletes
{private static Connection conexion;private static Statement sentencia;public ServidorGestorBilletesBD() throws RemoteException{try {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:Bill");sentencia=conexion.createStatement();conexion.setAutoCommit(false);// Habrá que hacer COMMITs} catch(Exception e){ System.out.println(”Error: "+e.toString());} }
A. Goñi. Dpto. LSI, UPV/EHU
173
Servidor Remoto accede a BDpublic int getBillete(String nom)
throws RemoteException {// Devuelve nº billete, -1 si no hay, -2 si hay problemasString pregSQL = "SELECT NUM FROM BILLETES”+
" WHERE ESTADO='LIBRE'";try{ ResultSet rs = sentencia.executeQuery(pregSQL);
if (rs.next()) {String num = rs.getString("NUM");int act = sentencia.executeUpdate("UPDATE BILLETES"+ " SET ESTADO='OCUPADO', NOMBRE = '"+nom+"' WHERE NUM="+num+" AND ESTADO='LIBRE'");conexion.commit();int n= Integer.parseInt(num);if (act>0) return n; // Núm. billete asignado return -2; } // Otro ya ha OCUPADO ese billeteelse return -1; } // No había ninguno librecatch (SQLException e)
{System.out.println("Error: "+e.toString());}return -2; // Que prueben otra vez a llamar
}
A. Goñi. Dpto. LSI, UPV/EHU
174
Servidor Remoto accede a BD// Método main de ServidorGestorBilletesBD.javapublic static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());try {ServidorGestorBilletesBD objetoServidor =
new ServidorGestorBilletesBD();
String maquina = "//localhost/";
String servicio = "gestorBilletes";String servicioRemoto = maquina+servicio;
// Registrar el servicio remotoNaming.rebind(servicioRemoto,objetoServidor);}catch (Exception e)
{System.out.println("Error: "+e.toString());}}}
A. Goñi. Dpto. LSI, UPV/EHU
175
Conexión entre nivel de presentación, lógica del negocio y datos
• Hasta ahora hemos considerado que en elnivel de presentación, el objeto con la lógicadel negocio se encuentra en un atributo (de tipo interface Java)
• Utilizando RMI se puede seguir con esa mismaidea, pero en este caso la interfaz es remota
• En vez de asignarle al objeto de presentación, el objeto con la lógica del negocio se puedehacer que sea el objeto de presentación quienlo busque (usando lookup).
• Cambiar la lógica del negocio consiste ensustituir un objeto por otro en el servidor.
A. Goñi. Dpto. LSI, UPV/EHU
176Interface LogicaNegocio
hacerX(… )hacerY(… )
usa
clase LogicaNegocioConcreta
hacerX(…) // ImplementacioneshacerY(…) // llaman al nivel de
// datos (usan JDBC)
Presentacion p = new Presentacion();p.setLogicaNegocio(new LogicaNegocioConcreta());p.setVisible(true);
CREAR LA INTERFAZ GRÁFICA Y ASIGNAR LÓGICA DEL NEGOCIO:
ARQUITECTURA FÍSICA EN 2 NIVELES: CLIENTE GORDO / SERVIDOR FLACO
Clase Presentacion
logNe: LogicaNegocio
setLogicaNegocio(l: LogicaNegocio)
// Permite cambiar lógica// negocio en tº ejecuc.
-- En esta clase se llama-- a la lógica del negocio:Por ej.: logNe.hacerX(…)
A. Goñi. Dpto. LSI, UPV/EHU
177Interface LogicaNegocio
hacerX(… )hacerY(… )
usa
clase LogicaNegocioConcreta
hacerX(…) // ImplementacioneshacerY(…) // llaman al nivel de
// datos (usan JDBC)
ARQUITECTURA FÍSICA EN 3 NIVELES usando RMI
Clase Presentacion
logNe: LogicaNegocio
setLogicaNegocio(String nombreServicio)
// Por ejemplo aquí se// puede asignar a logNe
-- En esta clase se llama-- a la lógica del negocio:Por ej.: logNe.hacerX(…)-- Para asignar la lógica-- del negocio se usa Naming.lookup y NomSer
interfaz Remota
-- La lógica del negocio se crea-- y se exporta usando:Naming.rebind y dando unnombre de servicio: NomSer
A. Goñi. Dpto. LSI, UPV/EHU
178
6. Tecnología Java para construcción de aplicaciones Web
Una introducción a Applets y Java Server Pages (JSP)
A. Goñi. Dpto. LSI, UPV/EHU
179
Índice
• Introducción • Applets
– Introducción y algunas características técnicas
– Nivel de presentación con Applets– Nivel de lógica del negocio con Applets
• Servlets• Java Server Pages (JSPs)
– Introducción y algunas características técnicas
– Nivel de presentación con JSPs– Nivel de lógica del negocio con JSPs
A. Goñi. Dpto. LSI, UPV/EHU
180
Introducción
• Aplicación Web: es una aplicación que se ejecuta en un navegador Web– Se pueden separar los 3 niveles: presentación,
lógica del negocio y datos– El nivel de presentación se ejecuta en el cliente
pero se “despliega” en el servidor– Que haya que cambiar el nivel de presentación no
implica reinstalar todos los clientes– Se puede añadir parte de la lógica del negocio a
la presentación por motivos de eficiencia:• Se reducirían llamadas a la lógica del negocio• Si hubiera que cambiar la lógica del negocio no
implicaría reinstalar todos los clientes
A. Goñi. Dpto. LSI, UPV/EHU
181
Introducción
• La tecnología Java incluye la posibilidad de crear aplicaciones Web utilizando Applets y Java Server Pages (JSPs)
• Son dos filosofías distintas:– Usando applets se descargan aplicaciones desde
el servidor a los clientes. • En los clientes se ejecutan dichas aplicaciones.
– Con JSPs, en el servidor se ejecutan aplicacionesque generan código HTML de manera dinámica, el cual se envía a los clientes
• En los clientes se visualiza el resultado HTML.
A. Goñi. Dpto. LSI, UPV/EHU
182
Applets
Programas Java que se ejecutan en un navegador Web.Son una herramienta poderosa que soporta la programación en el lado del cliente, muy importante en la Web.
ClienteNavegador
Applet
A. Goñi. Dpto. LSI, UPV/EHU
183
Applets: Restricciones y Ventajas
• (-) Un applet no puede acceder al disco local• Restringir lectura para que no pueda transmitirse información
local por internet• Restringir la escritura para que no se puedan escribir virus en
el disco local• (-) No se puede hacer una conexión de red a otro
nodo de Internet que no sea aquél de donde se ha descargado
• Existe la posibilidad de firmar digitalmente applets paraeliminar algunas restricciones
• (-) Ejecución más lenta ya que hay que descargarlosprimero
• Mejor comprimir todos los applets en ficheros JAR
• (+) No hay que instalarlos en el cliente. Los appletsson independientes de la plataforma.
• (+) No hay que preocuparse por problemas de seguridad
A. Goñi. Dpto. LSI, UPV/EHU
184
Métodos de los applets
• Para escribir un applet, hay que heredar de la claseApplet/JApplet e implementar unos métodos
• init( ): – Se ejecuta automáticamente cuando se inicializa el applet.
Hay que proporcionar una implementación obligatoriamente• start( ):
– Se ejecuta cada vez que el applet se hace visible, comoresultado de alguna acción en el navegador.Se llama siempre después de init()
• stop( ): – Se ejecuta cada vez que el applet deja de verse
• destroy( ): – Se ejecuta cuando el applet se descarga definitivamente
(implementarlo si hubiera que liberar recursos)• No hay por qué implementar el método main()
A. Goñi. Dpto. LSI, UPV/EHU
185
Ejecución de applets
• Para ejecutar un applet: – Se incrusta en una página Web usando una etiqueta (tag) – Se visualiza en un navegador que contenga la máquina
virtual java apropiada.
• Las etiquetas apropiadas son:– Para applets de AWT (Applet), se usa el tag “applet”
• <applet code=“applet” width=100 height=50> </applet>
– Para applets Swing (JApplet), depende del navegador• Con Internet Explorer se necesita cargar un
mecanismo de extensión que es un control ActiveX• Con Netscape hay que cargar el plug-in apropiado• Como el programador no sabe con qué navegador se
cargará la página, hay que proporcionar las etiquetas(tags) para ambos
• La herramienta Appletviewer visualiza applets (de AWT y Swing) incrustados con el tag Applet
A. Goñi. Dpto. LSI, UPV/EHU
186
Ejecución de applets<html><head><title>Applet1</title></head><hr>
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93“ width="100" height="50" align="baseline" codebase="http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0">
<PARAM NAME="code" VALUE="Applet1.class"><PARAM NAME="codebase" VALUE="."><PARAM NAME="type" VALUE="application/x-java-applet;version=1.2.2"><COMMENT><EMBED type="application/x-java-applet;version=1.2.2" width="200" height="200" align="baseline“ code="Applet1.class" codebase="."
pluginspage="http://java.sun.com/products/plugin/1.2/plugin-install.html"><NOEMBED>
</COMMENT>No hay soporte para los applets</NOEMBED>
</EMBED></OBJECT>
<hr></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
187
Nivel de presentación usando Applets
• En un Applet/JApplet se pueden incluir todos los elementos gráficos de los paquetes AWT y SWING de Java
• En un Applet se puede dibujar, cargar imágenes y escuchar sonidos
A. Goñi. Dpto. LSI, UPV/EHU
188
Nivel lógica del negocio con Applets
• Para obtener la lógica del negocio desde un applet, se puede usar RMI: la conexión sólo puede hacerse con el servidor Web
public void init() // Método inicialización del Applet{try {…
String maquina = this.getCodeBase().getHost();gestorBilletes = (GestorBilletes)Naming.lookup("rmi://"+maquina+":“
+numPuerto+servicio);}catch(Exception e){// Error al cargar la lógica del negocio
}
LA LÓGICA DEL NEGOCIO SE IMPLEMENTARÍA IGUAL
A. Goñi. Dpto. LSI, UPV/EHU
189
Nivel lógica del negocio con Applets
• Para llamar a la lógica del negocio, se usa el objeto de gestorBilletes
void jButton1_actionPerformed(ActionEvent e){try {String nombre = jTextField1.getText();int res = gestorBilletes.getBillete(nombre);if (res>0) jTextArea1.append("Asignado. \nReferencia: "+res+"\n");else if (res==-1) jTextArea1.append("No hay billetes libres\n");else if (res==-2) jTextArea1.append("Error: Inténtelo de nuevo.\n");
}catch (Exception ex) {jTextArea1.append("Error: "+ex.toString()+"\n");}
}
A. Goñi. Dpto. LSI, UPV/EHU
190
Se puede validar la entrada en el nivel de presentación
• Más eficiente: sólo se llama a la lógica del negocio con entradas correctas
void jButton1_actionPerformed(ActionEvent e){try { String nombre = jTextField1.getText();if ((nombre.length()<5) || (existeNoLetra(nombre)))
jTextArea1.append("Error: por lo menos 5 letras\n");else { int res = gestorBilletes.getBillete(nombre);
if (res>0) ...}} // CÓDIGO ANTERIOR QUE LLAMAcatch (Exception ex) {...} // A LA LÓGICA DEL NEGOCIO
static boolean existeNoLetra(String s) {for (int i=0;i<s.length();i++) {char c = s.charAt(i);if (!((c >= 'a') && (c <= 'z')
|| (c >= 'A') && (c <= 'Z'))) // Añadir á,é,..ñ,Ñ !!return true;}
return false;}
A. Goñi. Dpto. LSI, UPV/EHU
191
Ejemplo del applet PedirBilleteAp
Usando AppletviewerUsando un navegador
A. Goñi. Dpto. LSI, UPV/EHU
192
¿Validar la entrada es nivel de presentación o lógica del negocio?
• Validar la entrada tiene que ver con la presentación, con la interacción con el usuario, que ha escrito mal los datos: debe hacerse en el nivel de presentación
• Sin embargo, a veces no está tan clara la diferencia entre nivel de presentación y lógica del negocio
• En una aplicación Web no importa tanto, ya que el nivel de presentación “se instala” en el lado del servidor y se ejecuta en los clientes. Cambiar la lógica del negocio o presentación NO requiere reinstalar los clientes
• Regla a observar: intuir cambios futuros y hacer el software extensible ante esos cambios
A. Goñi. Dpto. LSI, UPV/EHU
193
Servlets
Aplicaciones Java, que devuelven como resultado HTML.Normalmente se utilizan para la generación de páginas dinámicas o control
Servidor
Servlet
Html
A. Goñi. Dpto. LSI, UPV/EHU
194
Plantilla de un Servlet Simple
import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class ServletTemplate extends HttpServlet {public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {// En "request" se leen las cabeceras HTTP y los// datos que se hayan escrito en formularios// Se usa "response" para especificar el código de// estado de la respuestas y las cabeceras HTTP (ej.// tipo del contenido, cookies, etc.)PrintWriter out = response.getWriter();// Se usa "out" para enviar el contenido al navegador}}
A. Goñi. Dpto. LSI, UPV/EHU
195
Ejemplo de Servletpublic class HolaWWW extends HttpServlet {public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();String docType ="<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +"Transitional//EN\">\n";out.println(docType +"<HTML>\n" +"<HEAD><TITLE>Hola WWW</TITLE></HEAD>\n" +"<BODY>\n" +"<H1>Hola WWW</H1>\n" +"</BODY></HTML>");}}
A. Goñi. Dpto. LSI, UPV/EHU
196
Java Server Pages (JSP)
Páginas HTML con código Java embebido.En la primera invocación a un JSP el sistema lo transforma en un Servlet
Servidor
JSP
Html <HTML>
%%Java
</HTML>
A. Goñi. Dpto. LSI, UPV/EHU
197
Scriptlet JSP
• <% código java %>– Código Java insertado en una página JSP. Se
procesa en el momento de solicitarla– Se pueden usar variables predefinidas: request,
response, out, session, application, config, y pageContext
<html><body><H1> Ejemplo de código Java incrustado </H1><P><%for (int i=0;i<3;i++)
out.println("<H2> Hola número "+i+"</H2><BR>");%><P><H1> Adiós </H1></body></html>
out: objeto con la salida HTML
A. Goñi. Dpto. LSI, UPV/EHU
198
Scriptlet JSP <html><body><H1> Ejemplo de código Java incrustado </H1><P><%for (int i=0;i<3;i++)
out.println("<H2> Hola número "+i+"</H2><BR>");%><P><H1> Adiós </H1></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
199
JSP Expression
• <%= expression %>– Expresión que se evalúa y se coloca en la salida– Se usan variables predefinidas: request,
response, out, session, application, config, y pageContext
<html><body><H1> Ejemplo de código Java incrustado </H1><P><%for (int i=0;i<3;i++){
%><H2> Hola número <%=i%></H2><BR><%}%><P><H1> Adiós </H1></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
200
Expresión JSP
<html><body><H1> Ejemplo de código Java incrustado </H1><P><%
for (int i=0;i<3;i++){%><H2> Hola número <%=i%></H2><BR><%}
%><P><H1> Adiós </H1></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
201
Declaración JSP
• <%! código %>– El código se ejecuta sólo la primera vez que se
carga la página.– Puede servir para definir e inicializar variables que
queremos “perduren”<html><body><H1> Ejemplo de código Java incrustado </H1><P><%! int i=0; %><%for (int j=i;j<i+3;j++){
%><H2> Hola número <%=j%></H2><BR><%}i=i+3;
%><P> <H1> Adiós </H1></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
202
Declaración JSP
<html><body><H1> Ejemplo de código Java incrustado </H1><P><%! int i=0; %><%for (int j=i;j<i+3;j++){
%><H2> Hola número <%=j%></H2><BR><%}i=i+3;
%><P> <H1> Adiós </H1></body></html>
Primera ejecución del JSP
Segunda ejecución del JSP
A. Goñi. Dpto. LSI, UPV/EHU
203
Directiva JSP page
• <%@ page atributo="valor" %>• Órdenes al motor de servlets sobre
configuración– import =“nombre de clase"
• Si se usan clases que hay que importar– contentType="MIME-Type"
• Por defecto text/html• Podría ser text/vnd.wap.wml (para WAP)
– errorPage=“URL" • Se establece una URL a mostrar si ocurre error en el JSP
– isErrorPage="true|false" • Si es una página que muestra un error (aparecerá como
URL en la directiva errorPage de alguna página JSP)• Puede usarse la variable “exception” (objeto con la excep.)
A. Goñi. Dpto. LSI, UPV/EHU
204
Comentarios JSP
• <%-- comentario JSP --%>• El comentario es ignorado por el traductor de la
página JSP al servlet– Es un comentario sólo visible en la página JSP
• Si se desea tener un comentario que sea visible en la página HTML entonces hay que usar
<!– comentario HTML -->– Visible sólo en el código fuente HTML, no en el
navegador que visualiza dicho código– NOTA: Los scriptlets JSP, directivas JSP y acciones
JSP dentro de un comentario HTML SÍ SE EJECUTAN• Se podría enviar un comentario generado de manera dinámica
A. Goñi. Dpto. LSI, UPV/EHU
205
Nivel de presentación con JSPs
• El nivel de presentación sirve parainteractuar con el usuario
• Obtener entrada del usuario– Utilización de formularios
• Mostrar una salida, resultados,… al usuario– Se puede utilizar toda la potencia del
HTML y mostrar: textos, gráficos, sonidos, vídeo, etc.
A. Goñi. Dpto. LSI, UPV/EHU
206
Entrada de datos: Formularios HTML
A. Goñi. Dpto. LSI, UPV/EHU
207
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE> Formulario </TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><H2 ALIGN="CENTER">Pantalla de introducción de datos </H2><FORM ACTION="http://localhost:8080/alfredo/verDatos.jsp"><CENTER>Nombre:<INPUT TYPE="TEXT" NAME="nombre" VALUE="Filemón"><BR>Apellido:<INPUT TYPE="TEXT" NAME="apellido" VALUE="Pi"><P><INPUT TYPE="CHECKBOX" NAME="publicidad" CHECKED>Estoyinteresado en recibir publicidad<BR><INPUT TYPE="CHECKBOX" NAME="futbol">Me gusta el fútbol<P>Sexo: <BR><INPUT TYPE="RADIO" NAME="sexo" VALUE="hombre"> Hombre <BR><INPUT TYPE="RADIO" NAME="sexo" VALUE="mujer"> Mujer <P>
A. Goñi. Dpto. LSI, UPV/EHU
208
Mi afición preferida:<SELECT NAME="aficion"><OPTION VALUE="monte"> Ir al monte<OPTION VALUE="bailar"> Bailar<OPTION VALUE="estudiar" SELECTED>Estudiar</SELECT><P>Cuéntame tu vida:<TEXTAREA NAME="vida"ROWS=15 COLS=60 WRAP="SOFT"></TEXTAREA><INPUT TYPE="SUBMIT" value="Enviar datos"> <!--Pulsar aquí para enviar los datos --></CENTER></FORM>
A. Goñi. Dpto. LSI, UPV/EHU
209
Entrada de datos: formularios
A. Goñi. Dpto. LSI, UPV/EHU
210<html><body><H1> Estos son los datos recogidos: </H1><% String nombre = request.getParameter("nombre");
String apellido = request.getParameter("apellido");out.println("Nombre es: "+nombre+" "+apellido);String sexo = request.getParameter("sexo");String futbol = request.getParameter("futbol");String publicidad = request.getParameter("publicidad");String vida = request.getParameter("vida");String aficion = request.getParameter("aficion");out.println("<BR>Sexo: "+sexo);out.println("<BR>Publicidad: "+publicidad);out.println(" Fútbol: "+futbol);out.println(" Afición preferida: "+aficion);out.println("<BR>Vida:<BR>"+vida); %>
</body></html>
Recoger datos de formularios
request. getParameter("PARAM")
A. Goñi. Dpto. LSI, UPV/EHU
211<%-- Comentario JSP: no aparece en el HTML, pero sí en el SERVLET --%><%-- Usamos JSP directive para importar paquetes Java: --%><%@ page import="java.util.*" %><%-- Declaraciones JSP: se ejecutan sólo cuando se carga el servlet: --%>
<%!long tiempoDeCarga= System.currentTimeMillis();Date fechaDeCarga = new Date();int numAccesos = 0;%>
<html><body><img SRC="imagenReloj.jpg" height=218 width=291></img><%-- A continuación se usan expresiones JSP --%><H1>Fecha de la primera carga de la página: <%= fechaDeCarga %> </H1><H1>Fecha actual: <%= new Date() %></H1><H2>Página activa <%= (System.currentTimeMillis()-tiempoDeCarga)/1000 %> segs</H2><H3>Página accedida <%= ++numAccesos %> veces desde <%= fechaDeCarga %></H3><%-- Un "scriptlet" que escribe en la salida estándar del servidory en la página visualizada por el cliente. Es código Java, y se usa la variable predefinida "out"--%><%
System.out.println("Adiós (no se verá en el navegador)");out.println("Agur (se verá en el navegador)");
%><P> <!-- Comentario HTML: aparece como comentario en el HTML, pero no se verá en el navegador del cliente. A continuación hay código HTML para que se cargue un sonidoen la página y que funcione en Netscape y en Internet Explorer --%><EMBED SRC="bong.wav" HIDDEN="true" AUTOSTART="true"><NOEMBED><BGSOUND SRC="bong.wav"></NOEMBED><P> <a href="bong.wav"> Haz click en este link y oirás el sonido también </a></body></html>
MOSTRAR LA SALIDA CON HTML
A. Goñi. Dpto. LSI, UPV/EHU
212<%-- Comentario JSP: no aparece en el HTML, pero sí en el SERVLET --%><%-- Usamos JSP directive para importar paquetes Java: --%><%@ page import="java.util.*" %><%-- Declaraciones JSP: se ejecutan sólo cuando se carga el servlet: --%>
<%!long tiempoDeCarga= System.currentTimeMillis();Date fechaDeCarga = new Date();int numAccesos = 0;%>
<html><body><img SRC="imagenReloj.jpg" height=218 width=291></img><%-- A continuación se usan expresiones JSP --%><H1>Fecha de la primera carga de la página: <%= fechaDeCarga %> </H1><H1>Fecha actual: <%= new Date() %></H1><H2>Página activa <%= (System.currentTimeMillis()-tiempoDeCarga)/1000 %> segs</H2><H3>Página accedida <%= ++numAccesos %> veces desde <%= fechaDeCarga %></H3><%-- Un "scriptlet" que escribe en la salida estándar del servidory en la página visualizada por el cliente. Es código Java, y se usa la variable predefinida "out"--%><%
System.out.println("Adiós (no se verá en el navegador)");out.println("Agur (se verá en el navegador)");
%><P> <!-- A continuación hay código HTML para que se cargue un sonido
en la página y que funcione en Netscape y en Internet Explorer.Este comentario se verá en el navegador del cliente --%>
<EMBED SRC="bong.wav" HIDDEN="true" AUTOSTART="true"><NOEMBED><BGSOUND SRC="bong.wav"></NOEMBED><P> <a href="bong.wav"> Haz click en este link y oirás el sonido también </a></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
213<%-- Comentario JSP: no aparece en el HTML, pero sí en el SERVLET --%><%-- Usamos JSP directive para importar paquetes Java: --%><%@ page import="java.util.*" %><%-- Declaraciones JSP: se ejecutan sólo cuando se carga el servlet: --%>
<%!long tiempoDeCarga= System.currentTimeMillis();Date fechaDeCarga = new Date();int numAccesos = 0;%>
<html><body><img SRC="imagenReloj.jpg" height=218 width=291></img><%-- A continuación se usan expresiones JSP --%><H1>Fecha de la primera carga de la página: <%= fechaDeCarga %> </H1><H1>Fecha actual: <%= new Date() %></H1><H2>Página activa <%= (System.currentTimeMillis()-tiempoDeCarga)/1000 %> segs</H2><H3>Página accedida <%= ++numAccesos %> veces desde <%= fechaDeCarga %></H3><%-- Un "scriptlet" que escribe en la salida estándar del servidory en la página visualizada por el cliente. Es código Java, y se usa la variable predefinida "out"--%><%
System.out.println("Adiós (no se verá en el navegador)");out.println("Agur (se verá en el navegador)");
%><P> <!-- A continuación hay código HTML para que se cargue un sonido
en la página y que funcione en Netscape y en Internet Explorer.Este comentario se verá en el navegador del cliente --%>
<EMBED SRC="bong.wav" HIDDEN="true" AUTOSTART="true"><NOEMBED><BGSOUND SRC="bong.wav"></NOEMBED><P> <a href="bong.wav"> Haz click en este link y oirás el sonido también </a></body></html>
A. Goñi. Dpto. LSI, UPV/EHU
214También se puede validar la entrada en el nivel de presentación con JSPs y JavaScript
• Más eficiente: sólo se llama a la lógica del negocio con entradas correctas
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"><TITLE>PEDIR BILLETE</TITLE></HEAD><BODY><H1> PEDIR BILLETE </H1><FORM NAME="LE" METHOD="post" ACTION="PedirBillete.jsp">Nombre: <INPUT TYPE="text" NAME="nombre" onChange=validar();><P><INPUT TYPE="submit" value="Pedir Billete" ><INPUT type="reset" VALUE="Borrar Datos"></FORM><SCRIPT LANGUAGE="JavaScript">
function validar(){var nombre = document.LE.nombre.value;if (nombre.length<5) alert("Error, menos de 5 letras:" +
document.LE.nombre.value);document.LE.nombre.value = ""; }
</SCRIPT></BODY></HTML>
A. Goñi. Dpto. LSI, UPV/EHU
215
Validar la entrada en la presentación
JavaScript es un lenguaje de programación interpretado que puede ser ejecutado en un navegador
è PERMITE EJECUCIÓN DE CÓDIGO EN EL CLIENTE
A. Goñi. Dpto. LSI, UPV/EHU
216
Nivel Lógica del Negocio con JSPs
• El nivel de presentación debe limitarse a obtener la entrada del usuario y a devolver resultados– Cómo se obtienen los resultados a partir de la entrada lo
deciden/calculan las operaciones propias de la lógica del negocio.
• Es mejor que el nivel de presentación lo diseñen “expertos” (diseñadores gráficos) – Ofrecerles la posibilidad de llamar a la lógica del negocio, a ser
posible sin que conozcan detalles del lenguaje de programación
• Es interesante una arquitectura en varios niveles• Utilizando la tecnología de JSPs, se puede
llamar a JavaBeans, que implementen la lógica del negocio
A. Goñi. Dpto. LSI, UPV/EHU
217
Java Beans
• Un Java Bean es una clase Java que:– Proporciona un constructor sin parámetros
• Explícitamente u omitiendo todos los constructores
– Define todos sus atributos como “private”– Proporciona métodos accesores “get” y
modificadores “set” a los atributos• Si el atributo se llama “nomAtributo”• Entonces el método get será “getNomAtributo()”• Y el set: “setNomAtributo(TipoAtributo t)”• Si el atributo es una propiedad booleana se usará
“isNomAtributo()” en vez de “getNomAtributo()”
A. Goñi. Dpto. LSI, UPV/EHU
218
Instanciar JavaBeans
• Acción JSP: <jsp:useBean atributo=valor * /> • Para encontrar (o crear si no existe) una
instancia de una clase Java Bean• Posibles atributos:
– id="nombre de la instancia“– scope="page|request|session|application“– class=“nombre de la clase Java Bean“
<jsp:useBean id="gestorBilletes" class="beans.GestorBilletesBean" scope="request" />
Crea o encuentra la instancia de la clase beans.GestorBilletesBean, accesible durante la petición actual, y la que podrá referirse con el identificador gestorBilletes
A. Goñi. Dpto. LSI, UPV/EHU
219
Instanciar JavaBeans
<jsp:useBean id="gestorBilletes" class="beans.GestorBilletesBean" scope="application" />
Crea o encuentra la instancia de la clase beans.GestorBilletesBean, accesible durante “toda la aplicación”, y la que podrá referirse con el identificador gestorBilletes
<%! gestorBilletes =new beans.GestorBilletesBean(); }
CUIDADO, NO ES EXACTAMENTE EQUIVALENTE…
CON scope=“request” cada vez se crea una instancia nueva
A. Goñi. Dpto. LSI, UPV/EHU
220
Llamar a JavaBeans
• A partir de ese momento se puede usar el bean, directamente en Java:
<% ...int res = gestorBilletes.getBillete(nombre);...%>
<jsp:useBean id="gestorBilletes" class="beans.GestorBilletesBean" scope="request" />
A. Goñi. Dpto. LSI, UPV/EHU
221
Llamar a Java Beans: setProperty
• <jsp:setProperty att=val*/>– Para poner valores en atributos del Java Bean.
• name=“identificador del bean" • property=“nombre del atributo|*"• param=“nombre del parámetro de formulario"• value=“valor a asignar"
<jsp:setProperty name="gestorBilletes" property="nombre" value="Pepe" />Equivalente a:<% gestorBilletes.setNombre(“Pepe”);%>
<jsp:setProperty name="gestorBilletes" property="nombre" param="nom" />Equivalente a:<% String s1 = request.getParameter("nom");
gestorBilletes.setNombre(s1);%>
A. Goñi. Dpto. LSI, UPV/EHU
222
Llamar a Java Beans: getProperty
<jsp:getProperty name=“identificador del bean“ property=“nombre del atributo"/>– Para obtener valores de atributos del bean
<jsp:getProperty name="gestorBilletes" property="nombre" />Equivalente a:<%= gestorBilletes.getNombre();%>
NOTA: jsp:setProperty y jsp:getProperty posibilitan llamar a la lógica del negocio sin usar java: sólo lenguaje de etiquetas
A. Goñi. Dpto. LSI, UPV/EHU
223
<%@ page contentType="text/html;charset=windows-1252"%><HTML> <HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"><TITLE> PEDIR BILLETE </TITLE></HEAD><BODY><H1> PEDIR BILLETE </H1><FORM NAME="LE" METHOD="post" ACTION="PedirBillete.jsp">Nombre: <INPUT TYPE="text" NAME="nombre"><P><INPUT TYPE="submit" value="Pedir Billete"><INPUT type="reset" VALUE="Borrar Datos"></FORM></BODY></HTML>
A. Goñi. Dpto. LSI, UPV/EHU
224
<%@ page contentType="text/html;charset=windows-1252" import="java.util.*"%><jsp:useBean id="gestorBilletes" class="beans.GestorBilletesBean" scope="request" /><HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"><TITLE></TITLE></HEAD><BODY><H2>PEDIR BILLETE</H2><P><% String nombre = request.getParameter("nombre");int res = gestorBilletes.getBillete(nombre);if (res>0) out.println("<H1> Asignado. </H1> <P> </H2> Referencia: "+res+"</H2>");else if (res==-1) out.println("<H1> No hay billetes libres</H1>");else if (res==-2) out.println("<H1> Error: Inténtelo de nuevo.</H1>");%></P></BODY></HTML>
A. Goñi. Dpto. LSI, UPV/EHU
225
A. Goñi. Dpto. LSI, UPV/EHU
226
package beans;import java.sql.*;public class GestorBilletesBean{public GestorBilletesBean() {try{Class.forName("org.gjt.mm.mysql.Driver");conexion=DriverManager.getConnection
("jdbc:mysql://localhost/Billetes");… }
public int getBillete(String nom) {String pregSQL = "SELECT NUMERO FROM BILLETES"+
" WHERE ESTADO='LIBRE'";try{ResultSet rs = sentencia.executeQuery(pregSQL);
..}}
A. Goñi. Dpto. LSI, UPV/EHU
227
Otra posibilidad: añadir otro nivel en la propia lógica del negocio
Permite separar el servidor Web del servidor de aplicaciones. Así podría ser compartido por varios servidores Web.
También se puede ver como una manera de reutilizar lógica del negocio (suponiendo que ya estaba el ServidorGestorBilletesBD)
A. Goñi. Dpto. LSI, UPV/EHU
228
Más información…
• Sobre Servlets y JSPs hay mucho más– Más directivas y acciones– Librerías de etiquetas existentes– Posibilidad de crear etiquetas propias– Trabajo con Servlets (definir sesiones,
usar cookies, etc.), Applets, XML,…• Bibliografía:
– Core Servlets and Java Server Pages• Libro en PDF gratuito en:
http://www.coreservlets.com
A. Goñi. Dpto. LSI, UPV/EHU
229
7. Introducción a los Servicios Web
A. Goñi. Dpto. LSI, UPV/EHU
230
Índice
• Introducción• HTTP en 5 minutos• XML en 5 minutos• SOAP• WSDL • Usar Servicios Web en JDeveloper• Otros temas
A. Goñi. Dpto. LSI, UPV/EHU
231
Introducción: qué es un Servicio Web
• Definición dada por el W3C– A Web service is a software system designed to support
interoperable machine-to-machine interaction over a network. It has an interface described in a machine-processable format (specifically WSDL). Other systems interact with the Web service in a manner prescribed by its description using SOAP-messages, typically conveyed using HTTP with an XML serialization in conjunction with other Web-related standards
• Un Servicio Web es – (Parte de) Lógica de negocio
• La interfaz se define en un estándar basado en XML (WSDL)
– Accesible mediante protocolos de Internet• Habitualmente HTTP y SOAP (XML)
A. Goñi. Dpto. LSI, UPV/EHU
232
Introducción: Ventajas de los SW
CLIENTESERVIDOR
HTTP
XML
SERVIDORCLIENTE
JRMP / IIOP
TCP/IP
RMI
CLIENTESERVIDOR
IIOP
TCP/IP
CORBA
Lenguaje JAVA
Interfaces definidas en JAVA
Varias máquinas y S.O.
Varios lenguajes: Java, C++…
Interfaces definidas en IDL
Varias máquinas y S.O.
NO HAY RESTRICCIÓN SOBRE LENGUAJES, PLATAFORMAS, ETC.
CLIENTE
. NET Remoting
SERVIDOR
Varios lenguajes .NET: C++, C#, VB.NET …
Interfaces definidas en .NET
Máquinas Windows (?)
(-) Sin embargo, tipos de datos en las llamadas son más simples…
(Sustituye a DCOM)
(+) Favorecen la interoperabilidad
(+) Paso a través de firewalls
A. Goñi. Dpto. LSI, UPV/EHU
233
HTTP en 5 minutos
• HTTP es un protocolo Cliente/Servidor de Internet (TCP/IP) del nivel de aplicación, que proporciona servicios de transmisión de datos entre aplicaciones.
CLIENTE HTTP SERVIDOR HTTP
Petición
Respuesta
Ejemplos de comandos en peticiones:
GET Para leer una página Web
POST: Para enviar datos a una página Web
Ejemplos de respuestas:
Estados
Datos
Códigos de error
A. Goñi. Dpto. LSI, UPV/EHU
234
HTTP en 5 minutos
A. Goñi. Dpto. LSI, UPV/EHU
235
HTTP en 5 minutos[85] sisf00 > telnet sipx55.si.ehu.es 8080Trying 158.227.112.155...Connected to sipx55.si.ehu.es.Escape character is '^]'.GET /iso/jsp/public_html/pagina.jsp HTTP/1.0
HTTP/1.0 200 OKContent-Type: text/html;charset=windows-1252Set-Cookie2: JSESSIONID=pjqb72fy21;Version=1;Discard;Path="/iso"Set-Cookie: JSESSIONID=pjqb72fy21;Path=/isoServlet-Engine: Tomcat Web Server/3.2.3 (JSP 1.1; Servlet 2.2; Java 1.3.1_02; Windows 2000 5.0 x86; java.vendor=Sun Microsystems Inc.)
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Prueba</title></head><body><h2> Hola null<br>Estamos a: Tue May 03 13:28:53 CEST 2005</h2></body></html>Connection closed by foreign host.[65] sisf00 >
Con telnet se puede abrir un socketinteractivo con un servidor HTTP
Con GET se solicita una página web(en este caso es un JSP)
Y el contenido de la página HTML
// Añadir línea en blanco
El servidor HTTP envía datos (protocolo, código respuesta, información sobre el servidor,…)
A. Goñi. Dpto. LSI, UPV/EHU
236
HTTP en 5 minutos
A. Goñi. Dpto. LSI, UPV/EHU
237
HTTP en 5 minutos[107] sisf00 > telnet sipx55.si.ehu.es 8080Trying 158.227.112.155...Connected to sipx55.si.ehu.es.Escape character is '^]'.POST /iso/jsp/public_html/pagina.jsp HTTP/1.0Content-type: application/x-www-form-urlencodedContent-length: 14
Nombre=AlfredoHTTP/1.0 200 OKContent-Type: text/html;charset=windows-1252Set-Cookie2: JSESSIONID=crb244gx61;Version=1;Discard;Path="/iso"Set-Cookie: JSESSIONID=crb244gx61;Path=/isoServlet-Engine: Tomcat Web Server/3.2.3 (JSP 1.1; Servlet 2.2; Java 1.3.1_02; Windows 2000 5.0 x86; java.vendor=Sun Microsystems Inc.)
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"><title>Prueba</title></head><body><h2> Hola Alfredo<br>Estamos a: Tue May 03 14:11:01 CEST 2005</h2></body></html>Connection closed by foreign host.[108] sisf00 >
Con el comando POST, se pueden enviar datos al servidor HTTP.
En este caso es el contenido de un parámetro, pero en general, puede ser cualquier fichero.
A. Goñi. Dpto. LSI, UPV/EHU
238
XML en 5 minutos
• XML (eXtensible Markup Language) es un lenguaje de marcas o etiquetas que sirve para describir datos– Definido por el W3C en 1996, a partir de
otro lenguaje: SGML, del cual deriva también HTML
– HTML es otro lenguaje de marcas diseñado para mostrar datos
• XML para almacenar, comunicar, no mostrar datos
– Es extensible: se pueden definir nuevas marcas o etiquetas (tags)
A. Goñi. Dpto. LSI, UPV/EHU
239
XML en 5 minutos
ENCABEZAMIENTO XML: VERSIÓN Y CONJUNTO DE CARACTERES
ETIQUETAS: se deben abrir y cerrar <nombreSala> …</nombreSala>
ATRIBUTOS (siempre entre comillas, simples o dobles):
<sala imagen=“principe1.gif”>
ETIQUETAS SIN DATOS ASOCIADOS: <nombreSala/> Equivalente a: <nombreSala></nombreSala>
OBLIGATORIO UN ÚNICO ELEMENTO RAÍZ: <entradasTodasSalas>
ANIDACIÓN DE MARCAS: toda marca que se cierra debe corresponder a la última marca abierta y no cerrada
En las etiquetas: MAYÚSCULAS ? minúsculas
A. Goñi. Dpto. LSI, UPV/EHU
240
XML en 5 minutos
En un navegador se puede ver el fichero XML; abrir y cerrar “etiquetas”
A. Goñi. Dpto. LSI, UPV/EHU
241
Documentos XML bien formados vs. Documentos XML válidos
• Un documento XML está bien formado si cumple las restricciones anteriores– No hay nodo raíz, atributos no entre comillas,
mal anidamiento, etc…• Pero es posible que no sea un documento XML
válido– Nombres de etiquetas, atributos erróneos– No aparición de alguna etiqueta obligatoria– …
• Se puede definir la estructura de un documento XML usando DTD o XML-Schema
• Qué etiquetas deben/pueden venir, qué atributos, en qué orden, etc.
A. Goñi. Dpto. LSI, UPV/EHU
242
Llamadas a servicios remotos usando XML y HTTP
CLIENTE
SERVIDOR
HTTPXML
Se usa HTTP para la transmisión de datos XML entre las aplicaciones CLIENTE y SERVIDOR
Se puede definir una estructura de documento XML que describa una llamada a un procedimiento remoto
POST /gestorBilletes HTTP/1.0Content-type: text/xmlContent-length: XX
<?xml version='1.0' encoding='windows-1252'?><llamadaRemota>
<getBillete><nombre>Pepe</nombre>
</getBillete></llamadaRemota>
Por ejemplo, para llamar al método getBillete(nombre), podríamos hacerlo así:
A. Goñi. Dpto. LSI, UPV/EHU
243
Se necesita un estándar para enviar el mensaje con la llamada remota
CLIENTESERVIDOR
HTTP
XML
Se usa HTTP para la transmisión de datos XML entre las aplicaciones CLIENTE y SERVIDOR
Se puede definir una estructura de documento XML que describa una llamada a un procedimiento remoto
SIN EMBARGO: el documento XML que describe llamadas a procedimientos remotos debe seguir un estándar si no se quiere construir un servidor distinto cada vez, para que extraiga los métodos y parámetros
SOAP: Simple Object Access Protocol
A. Goñi. Dpto. LSI, UPV/EHU
244
SOAP: Simple Object Access Protocol
• SOAP 1.2 es recomendación W3C desde 24/3/2004 (http://www.w3.org/TR/soap/)
• Define:– Formato de mensajes de comunicación en XML– Cómo debería ser transportado un mensaje vía
Web (HTTP) o e-mail (SMTP)– Reglas que se siguen cuando se procesa un
mensaje SOAP– Cómo se convierte una llamada RPC de un cliente
en un mensaje SOAP, cómo se envía al servidor, cómo se convierte en una llamada RPC en el servidor, cómo se convierte la respuesta en un mensaje SOAP y se devuelve al cliente
A. Goñi. Dpto. LSI, UPV/EHU
245
Formato de un mensaje SOAP
SOAP Envelope
SOAP header
Bloque Header
SOAP BodyBloque Body
Bloque Header
Bloque Body
El mensaje se mete en un sobre (envelope)
El mensaje se compone de una cabecera (header) OPCIONAL y de un cuerpo (Body) OBLIGATORIO
La cabecera (header) se utiliza para enviar información sobre identificadores de transacciones, certificados de seguridad, información sobre coordinación, etc.
El cuerpo (body) contiene las llamadas a los procedimientos remotos (junto con los parámetros), o bien las respuestas de dichos procedimientos remotos, o bien información sobre el error que se haya producido.
A. Goñi. Dpto. LSI, UPV/EHU
246
Ejemplo de llamada SOAP
getNumBillete(“Pepe”)
nom
A. Goñi. Dpto. LSI, UPV/EHU
247
Ejemplo de resultado en SOAP
Resultado de la llamada a getNumBillete(“Pepe”)
==> 2 (como int)
A. Goñi. Dpto. LSI, UPV/EHU
248
Se necesita un estándar que describa el Servicio Web
• ¿Cómo saber qué etiquetas XML podemos poner en el mensaje SOAP?<getNumBillete…><nom …>
• Es necesario conocer la definición del servicio Web (esto es, su interfaz)
• Los SW se describen en WSDL
WSDL: Web Services DescriptionLanguage
A. Goñi. Dpto. LSI, UPV/EHU
249
WSDL: Web Services DescriptionLanguage
• WSDL 1.1 es una Nota W3C desde 15/3/2001 (http://www.w3.org/TR/wsdl/)
• Define:– Una descripción abstracta de un servicio Web
• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación• Operaciones individuales compuestas de distintos patrones de
intercambio de mensajes• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web• El enlace (binding) de la interfaz a un protocolo de transporte• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los
enlaces (bindings) de la misma interfaz
A. Goñi. Dpto. LSI, UPV/EHU
250
WSDL: Web Services DescriptionLanguage
Documento WSDL
DE
SCR
IPC
IÓN
A
BST
RA
CT
AD
EL
SE
RV
ICIO
Types
Message (REQUEST)
Message (RESPONSE)
Message (REQUEST)
Message (RESPONSE)
Operation 1 Operation 2
Interface
binding 1
endpoint 1
binding 2
endpoint 2
binding 3
endpoint 3
Service
DE
SCR
IPC
IÓN
CO
NC
RE
TA
D
EL
SE
RV
ICIO
TIPOS DE DATOS USADOS (los de XML Schema)
PARA CADA OPERACIÓN
MENSAJES DE PETICIÓN Y RESPUESTA
SERVICIO ABSTRACTO (CONJUNTO DE OPERACIONES)
TODAS LAS IMPLEMENTACIONES DEL
SERVICIO
ENLACES A PROTOCOLOS DE TRANSPORTE
DIRECCIONES DE LOS ENLACES
A. Goñi. Dpto. LSI, UPV/EHU
251WSDL
Types
Message (REQUEST)
Message (RESPONSE)
Message (REQUEST)
Message (RESPONSE)
Operation 1 Operation 2
Interface
binding 1
endpoint 1
binding 2
endpoint 2
binding 3
endpoint 3
Service
A. Goñi. Dpto. LSI, UPV/EHU
252
WSDL: Web Services DescriptionLanguage
types
– Una descripción abstracta de un servicio Web
• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación• Operaciones individuales compuestas de distintos patrones de intercambio de mensajes• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web• El enlace (binding) de la interfaz a un protocolo de transporte• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los enlaces (bindings) de la misma interfaz
A. Goñi. Dpto. LSI, UPV/EHU
253
WSDL: Web Services DescriptionLanguage
message
– Una descripción abstracta de un servicio Web• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación
• Operaciones individuales compuestas de distintos patrones de intercambio de mensajes• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web• El enlace (binding) de la interfaz a un protocolo de transporte• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los enlaces (bindings) de la misma interfaz
A. Goñi. Dpto. LSI, UPV/EHU
254
WSDL: Web Services DescriptionLanguage
– Una descripción abstracta de un servicio Web• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación
• Operaciones individuales compuestas de distintos patrones de intercambio de mensajes
• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web• El enlace (binding) de la interfaz a un protocolo de transporte• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los enlaces (bindings) de la misma interfaz
portType
operation
A. Goñi. Dpto. LSI, UPV/EHU
255
WSDL: Web Services DescriptionLanguage
– Una descripción abstracta de un servicio Web• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación• Operaciones individuales compuestas de distintos patrones de intercambio de mensajes• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web
• El enlace (binding) de la interfaz a un protocolo de transporte
• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los enlaces (bindings) de la misma
interfaz
binding
A. Goñi. Dpto. LSI, UPV/EHU
256
WSDL: Web Services DescriptionLanguage
– Una descripción abstracta de un servicio Web• El sistema de tipos usados para describir los mensajes (basado en XML Schema)
• Mensajes implicados en invocar una operación• Operaciones individuales compuestas de distintos patrones de intercambio de mensajes• Una interfaz que agrupa las operaciones que forman el servicio
– Una descripción concreta del servicio Web• El enlace (binding) de la interfaz a un protocolo de transporte
• Dirección o punto de acceso (endpoint) del enlace (binding)• Descripción de un servicio como una colección de todos los
enlaces (bindings) de la misma interfaz
port
service
A. Goñi. Dpto. LSI, UPV/EHU
257
Punto de acceso (endpoint) al SW
A. Goñi. Dpto. LSI, UPV/EHU
258
A. Goñi. Dpto. LSI, UPV/EHU
259
RESULTADO
Mensaje SOAP con la
respuesta
A. Goñi. Dpto. LSI, UPV/EHU
260
Usar SW en JDeveloper
• Afortunadamente, los distintos entornos ofrecen herramientas y asistentes que generan los WSDL y SOAP de manera automática, a partir de clases implementadas en distintos Leng. Prog.
• Los programadores pueden seguir trabajando con sus lenguajes y plataformas habituales
• JDeveloper, en concreto, lo permite
A. Goñi. Dpto. LSI, UPV/EHU
261
Crear un SW en Java
A. Goñi. Dpto. LSI, UPV/EHU
262
Se selecciona la clase Java para la que se quiere crear el SW
A. Goñi. Dpto. LSI, UPV/EHU
263Seleccionar los métodos que se quieren publicar en el SW
¡Cuidado! No se pueden crear SW para métodos cuyos tipos no sean los básicos, String,
Date, Calendar,… o Array[] de ellos
A. Goñi. Dpto. LSI, UPV/EHU
264
Se indica la dirección del punto de acceso
A. Goñi. Dpto. LSI, UPV/EHU
265
El WSDL se genera automáticamente
A. Goñi. Dpto. LSI, UPV/EHU
266
Punto acceso
A. Goñi. Dpto. LSI, UPV/EHU
267Creamos una clase Java cliente del SW
A. Goñi. Dpto. LSI, UPV/EHU
268
A. Goñi. Dpto. LSI, UPV/EHU
269
Añadimos el código con la llamada al SW (en Java)
A. Goñi. Dpto. LSI, UPV/EHU
270
Ejecutamos el SW
A. Goñi. Dpto. LSI, UPV/EHU
271
Ejecutamos el cliente del SW
A. Goñi. Dpto. LSI, UPV/EHU
272
Y activamos el Monitor TCP para ver los mensajes SOAPTools => TCP Packet Monitor
A. Goñi. Dpto. LSI, UPV/EHU
273
Mensaje SOAP con la petición
Mensaje SOAP con la respuesta
A. Goñi. Dpto. LSI, UPV/EHU
274
Otros temas
• UDDI (Universal Description, Discovery and Integration)– Es un directorio distribuido donde las empresas pueden registrar,
eliminar y buscar servicios web.– Empresas como IBM, Microsoft, etc. mantienen nodos con esa
información.• Se pretende construir una infraestructura para construir
aplicaciones integrando servicios web entre empresas (B2B)• Herramientas para traducir de WSDL a un lenguaje (Java,
lenguaje .NET, …)– Apache AXIS proporciona compiladores Java a WSDL y de WSDL
a Java• Definición de otros estándares como WS-Coordination, WS-
Transaction, WS-Routing– ¿Qué pasa si se quiere reservar un viaje completo?
• Reservar vuelo => Usando SW• Reservar hotel => Usando SW• ¿Y si quisiéramos que fuera una transacción?
A. Goñi. Dpto. LSI, UPV/EHU
275
Ejercicio de ArquitecturasSoftware
A. Goñi. Dpto. LSI, UPV/EHU
276import java.awt.*;import java.awt.event.*;public class ConsPrecioIU extends Frame {
Label label1 = new Label();Panel panel1 = new Panel();Button button1 = new Button();Button button2 = new Button();Panel panel2 = new Panel();GridLayout gridLayout1 = new GridLayout(3,2);Label label2 = new Label();TextField textField1 = new TextField();Label label3 = new Label();TextField textField2 = new TextField();Label label4 = new Label();TextField textField3 = new TextField();public ConsPrecioIU() {
super();try {jbInit();
}catch (Exception e) {e.printStackTrace(); } }
// Continúa…
La interfaz de usuarioasociada a un caso de uso llamadoCONSULTAR PRECIO aparece a continuación, junto con la clase Java correspondiente:
A. Goñi. Dpto. LSI, UPV/EHU
277private void jbInit() throws Exception {this.setTitle("Frame Title");label1.setText("CONSULTAR PRECIO");label1.setAlignment(Label.CENTER);button1.setLabel("Consultar Precio");button1.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {button1_actionPerformed(e); } });
button2.setLabel("Cancelar");button2.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {button2_actionPerformed(e); } });
label2.setText("MANZANAS (Kg.)");label3.setText("PERAS (Kg.)");label4.setText("NARANJAS (Kg.)");panel2.setLayout(gridLayout1);this.add(label1, BorderLayout.NORTH);this.add(panel1, BorderLayout.SOUTH);panel1.add(button1, null);panel1.add(button2, null);this.add(panel2, BorderLayout.CENTER);panel2.add(label2, null);panel2.add(textField1, null);panel2.add(label3, null);panel2.add(textField2, null);panel2.add(label4, null);panel2.add(textField3, null);this.pack();this.setVisible(true);}
void button1_actionPerformed(ActionEvent e) {...}void button2_actionPerformed(ActionEvent e) {...}
}
A. Goñi. Dpto. LSI, UPV/EHU
278Se dispone también de una clase llamada Aviso quesirve para crear Dialog modales asociados al objetoFrame actual. La llamada new Aviso(this,"PulsaAceptar y me voy"); crearía lo siguiente:
Además, nos han proporcionado los siguientes métodos, loscuales no sabemos ni a qué clase pertenecen ni qué es lo quehacen exactamente, pero nos han dicho que son útiles para acceder a los datos almacenados en la siguiente tabla de una BD Access. Además nos dicen que dicha BD es accesible pormedio de una fuente de datos ODBC llamada PRODS
A. Goñi. Dpto. LSI, UPV/EHU
279
public void inicializarBD () {try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");conexion=DriverManager.getConnection("jdbc:odbc:PRODS");
sentencia=conexion.createStatement(); }catch(Exception e){System.out.println("Error"+e.toString());} }
public float getPrecio(String nombre) {try{ rs=sentencia.executeQuery("SELECT PRECIO FROM PRODUCTOS "+
"WHERE NOMBRE='"+nombre+"'");if (rs.next()) return rs.getFloat("PRECIO");
} catch (Exception e) {System.out.println("Error: "+e.toString());}return 0; }
A. Goñi. Dpto. LSI, UPV/EHU
280Se pide: Rellenar la clase ConsPrecioIU con el códigonecesario para que al pulsar el botón CONSULTAR PRECIO aparezca como resultado el precio de losproductos escogidos. Por ejemplo, el resultado sería elsiguiente:
si los precios actuales fueran los que aparecen en la tablaACCESS anterior y se hubiera pulsado el botón CONSULTAR PRECIO con los siguientes datos de entrada:
La solución debe basarse en una arquitectura lógica en 3 niveles y ser extensible ante un futuro cambio en la lógica del negocio, ya que se está pensando en “aplicar porcentajes de descuento a cada producto dependiendo de la cantidad de Kg. que se compre”.
A. Goñi. Dpto. LSI, UPV/EHU
281
Solución
ConsPrecioIU
p: PreciosLN
“interface” PreciosLNusa calcularPrecio(c1,c2,c3: String): float
Precios
inicializarBD(): voidgetPrecio(nombre:String): floatcalcularPrecio(kgMan,kgPer,kgNar: String) : float
A. Goñi. Dpto. LSI, UPV/EHU
282EN LA PRESENTACIÓN AÑADIMOS UN ATRIBUTO CON LA LÓGICA DEL NEGOCIO Y MÉTODO PARA ASIGNARLA:
public class ConsPrecioIU extends Frame {…PreciosLN pr;
void setLogicaNegocio(PreciosLN p) {pr=n;}… }
public interface PreciosLN {
public float calcularPrecio(String kgManz, String kgPer, String kgNar);
}
LA LÓGICA DEL NEGOCIO SE DEFINE CON UNA INTERFAZ:
A. Goñi. Dpto. LSI, UPV/EHU
283
void button1_actionPerformed(ActionEvent e) {// En p tenemos el objeto con la lógica del negociofloat precio = p.calcularPrecio(textField1.getText(),
textField2.getText(),textField3.getText());
Aviso a = new Aviso(this,"Precio es: "+precio);}
LA LÓGICA DEL NEGOCIO SE USA DESDE ELMÉTODO DE ATENCIÓN AL EVENTO
A. Goñi. Dpto. LSI, UPV/EHU
284
public class Precios implements PreciosLN {
public float calcularPrecio(String kgManz, String kgPer, String kgNar) {
float m,p,n;try{m=Float.parseFloat(kgManz);} catch (Exception ex) {m=0;}try{p=Float.parseFloat(kgPer);} catch (Exception ex) {p=0;}try{n=Float.parseFloat(kgNar);} catch (Exception ex) {n=0;}return m*getPrecio("MANZANAS (Kg.)")+
p*getPrecio("PERAS (Kg.)")+ n*getPrecio("NARANJAS (Kg.)");}
// y los métodos inicializarBD y getPrecio…}
LA LÓGICA DEL NEGOCIO SE OBTIENEIMPLEMENTANDO LA INTERFAZ. PARA ELLO SE REALIZAN LLAMADAS AL NIVEL DE DATOS
A. Goñi. Dpto. LSI, UPV/EHU
285
Es una solución correcta…
• La solución sigue una arquitectura lógica entres niveles (están separadas el nivel de presentación del nivel lógica del negocio enclases y el nivel de datos en la BD)– Presentación: ConsPrecioIU y Aviso– Lógica del negocio: interfaz PreciosLN y clase Precios
• Es extensible– Cuando se quiera añadir la regla del negocio para aplicar
descuentos según la cantidad comprada habrá quereprogramar la clase calcularPrecios de la lógica del negocio y la BD (para almacenar descuentos, etc.). PeroNO CAMBIARÁ la clase de presentación
A. Goñi. Dpto. LSI, UPV/EHU
286
Precios
inicializarBD(): voidgetPrecio(nombre:String): floatgetPrecioMan(): floatgetPrecioPer(): float,getPrecioNar(): float
ConsPrecioIU
p: PreciosLN
“interface” PreciosLN
usa getPrecioMan(): floatgetPrecioPer(): float,getPrecioNar(): float
La siguiente solución no escorrecta…
A. Goñi. Dpto. LSI, UPV/EHU
287
void button1_actionPerformed(ActionEvent e) {// En pr tenemos el objeto con la lógica del negocioString kgManz = textField1.getText(); // idem. kgPer y KgNartry{m=Float.parseFloat(kgManz);} catch (Exception ex) {m=0;}try{p=Float.parseFloat(kgPer);} catch (Exception ex) {p=0;}try{n=Float.parseFloat(kgNar);} catch (Exception ex) {n=0;}float precio = m*pr.getPrecioMan()+ p*pr.getPrecioPer() +
n*pr.getPrecioNar();Aviso a = new Aviso(this,"Precio es: "+precio);}
LA LÓGICA DEL NEGOCIO SE USA DESDE ELMÉTODO DE ATENCIÓN AL EVENTO
NO ES EXTENSIBLE. EL PRECIO DE LOSPRODUCTOS NO DEPENDE DE LA CANTIDAD.HABRÍA QUE CAMBIAR LA PRESENTACIÓN:if (m>10) precioMan = pr.getPrecioMan()*0.9;// idem. con resto de productos y descuentos
A. Goñi. Dpto. LSI, UPV/EHU
288
La solución propuesta, sin embargo, no es extensible si se desea cambiar elnúmero y el nombre de productos
(lo cual no se pedía en elenunciado…)
A. Goñi. Dpto. LSI, UPV/EHU
289
• Una solución extensible ante elposible cambio “se puedenconsultar los precios de variosproductos” aparece a continuación.
• Para ver si una solución esextensible hay que saber conrespecto a qué posible cambio esextensible
A. Goñi. Dpto. LSI, UPV/EHU
290void button1_actionPerformed(ActionEvent e) {// En p tenemos el objeto con la lógica del negocioVector datos= new Vector();datos.addElement(label1.getText());datos.addElement(textField1.getText()); datos.addElement(label2.getText()); // …float precio = p.calcularPrecio(datos.elements());
Aviso a = new Aviso(this,"Precio es: "+precio);}
ConsPrecioIU
p: PreciosLN
“interface” PreciosLN
usa calcularPrecio(datos: Enumeration): floatobtenerProductos(): Enumeration
Precios
inicializarBD(): voidgetPrecio(nombre:String): floatcalcularPrecio(PrecCant:Enumeration ) : floatobtenerProductos(): Enumeration