A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU 1
Ejercicio de Arquitecturas
Software
Caso de Uso
CONSULTAR PRECIOS
2 import 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 usuario asociada a un caso de uso llamado CONSULTAR PRECIO aparece a continuación, junto con la clase Java correspondiente :
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
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) {...} } 4
Se dispone también de una clase llamada Aviso que sirve para crear Dialog modales asociados al objeto Frame actual. La llamada new Aviso(this,"Pulsa Aceptar y me voy"); crearía lo siguiente :
Además, nos han proporcionado los siguientes métodos, los cuales no sabemos ni a qué clase pertenecen ni qué es lo que hacen exactamente , pero nos han dicho que son útiles para acceder a los datos almacenados e n la siguiente tabla de una BD Access. Además nos dicen que dicha BD es accesible por medio de una fuente de datos ODBC llamada PRODS
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
5
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; }
6
Se pide : Rellenar la clase ConsPrecioIU con el código necesario para que al pulsar el botón CONSULTAR PRECIO aparezca como resultado el precio de los productos escogidos. Por ejemplo, el resultado sería el siguiente :
si los precios actuales fueran los que aparecen en la tabla ACCESS 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 e n 3 niveles y ser extensible ante un futuro cambio e n la lógica del negocio, ya que se está pensando e n “aplicar porcentajes de
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
Precios
inicializarBD(): void
getPrecio(nombre:String): float
getPrecioMan(): float
getPrecioPer(): float,
getPrecioNar(): float
ConsPrecioIU
p: PreciosLN
“interface” PreciosLN
usa
getPrecioMan(): float
getPrecioPer(): float,
getPrecioNar(): float
8
void button1_actionPerformed(ActionEvent e) {
// En p tenemos el objeto con la lógica del negocio
String kgManz = textField1.getText(); // idem. kgPer y KgNar
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;}
float precio = m*p.getPrecioMan()+ p*p.getPrecioPer() +
n*p.getPrecioNar();
Aviso a = new Aviso(this,"Precio es: "+precio);}
LA LÓGICA DEL NEGOCIO SE USA DESDE EL
MÉTODO DE ATENCIÓN AL EVENTO
NO ES EXTENSIBLE. EL PRECIO DE LOS
PRODUCTOS 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, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU 9
Segunda Solución
ConsPrecioIU
p: PreciosLN
“interface” PreciosLN
usa
calcularPrecio(c1,c2,c3: String ): float
Precios
inicializarBD(): void
getPrecio(nombre:String): float
calcularPrecio(kgMan,kgPer,kgNar: String ) : float
10
EN LA PRESENTACIÓN AÑADIMOS UN ATRIBUTO
CON LA LÓGICA DEL NEGOCIO Y MÉTODO PARA
ASIGNARLA:
public class ConsPrecioIU extends Frame {
…
PreciosLN p;
void setLogicaNegocio(PreciosLN p) {pr=n;}
… }
public interface PreciosLN {
public float calcularPrecio(String kgManz,
String kgPer,
String kgNar);
}
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
void button1_actionPerformed(ActionEvent e) {
// En p tenemos el objeto con la lógica del negocio
float 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 EL
MÉTODO DE ATENCIÓN AL EVENTO
12
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 OBTIENE
IMPLEMENTANDO LA INTERFAZ. PARA ELLO
SE REALIZAN LLAMADAS AL NIVEL DE DATOS
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
13
Es una solución correcta…
• La solución sigue una arquitectura lógica en
tres niveles (están separadas el nivel de
presentación del nivel lógica del negocio en
clases 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á que
reprogramar la clase calcularPrecios de la lógica del
negocio y la BD (para almacenar descuentos, etc.). Pero
NO CAMBIARÁ la clase de presentación
14
La solución propuesta, sin embargo,
no es extensible si se desea cambiar el
número y el nombre de productos
(lo cual no se pedía en el
enunciado…)
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
• Una solución extensible ante el
posible cambio “se pueden
consultar los precios de varios
productos” aparece a continuación.
• Para ver si una solución es
extensible hay que saber con
respecto a qué posible cambio es
extensible
16
ConsPrecioIU p: PreciosLN
“interface” PreciosLN
usa calcularPrecio(datos : Vector): float obtenerProductos (): Vector
Precios inicializarBD(): void
getPrecio(nombre:String): float calcularPrecio(PrecCant: Vector) : float obtenerProductos (): Vector
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
17
void button1_actionPerformed(ActionEvent e) {
// En p tenemos el objeto con la lógica del negocio
Vector datos= new Vector();
datos.addElement(label1.getText());
datos.addElement(textField1.getText());
datos.addElement(label2.getText()); // …
float precio = p.calcularPrecio(datos);
Aviso a = new Aviso(this,"Precio es: "+precio);
}
ConsPrecioIU p: PreciosLN
“interface” PreciosLN
usa calcularPrecio(datos : Vector): float obtenerProductos (): Vector
Precios inicializarBD(): void
getPrecio(nombre:String): float calcularPrecio(PrecCant: Vector) : float obtenerProductos (): Vector
18
• El método obtenerProductos() se
necesitará para colocar dichos
productos en la interfaz de usuario…
• Implementad dicho código…
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
El resto de transparencias no las
he utilizado…
20
Nivel de Presentación
Nivel Lógica del Negocio
Nivel de Datos
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
21
Restricciones de los Applets
• An applet can’t touch the local disk.
– No reading: you wouldn’t want an applet to read and transmit private information over the Internet without your permission. – No writing: Writing is prevented, of course, since that would be an
open invitation to a virus.
– Java offers digital signing for applets. Many applet restrictions are relaxed when you choose to allow trusted applets (those signed by a trusted source) to have access to your machine.
• Applets can take longer to display, since you must download the whole thing every time, including a separate server hit for each different class. Your browser can cache the applet, but there are no guarantees. Because of this, you should always package your applets in a JAR (Java ARchive) file that
combines all the applet components (including other .class files as well as images and sounds) together into a single
compressed file that can be downloaded in a single server transaction. “Digital signing” is available for each individual entry in the JAR file.
• No puede hacer una conexión de red a otro nodo de Internet que no sea aquél de donde se ha descargado
22
Ventajas de los Applets
• There is no installation issue. An applet has true platform independence (including the ability to easily play audio files, etc.) so you don’t need to make any changes in your code for different platforms nor does anyone have to perform any “tweaking” on installation. In fact, installation is automatic every time the user loads the Web page that contains applets, so updates happen silently and automatically. In traditional client/server systems, building and installing a new version of the client software is often a nightmare.
• 2.You don’t have to worry about bad code causing damage to someone’s system, because of the security built into the core Java language and applet structure. This, along with the previous point, makes Java popular for so-called intranet client/server applications that live only within a company or restricted arena of operation where the user environment (Web browser and add-ins) can be specified and/or controlled.
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
• Applets are built using an application framework. You inherit from class JApplet and override the appropriate methods. There are a few methods that control the creation and execution of an applet on a Web page
• init( ): Automatically called to perform first-time initialization of the applet, including component layout. You’ll always override this method. • start( ): Called every time the applet moves into sight on the Web
browser to allow the applet to start up its normal operations (especially those that are shut off by stop( )). Also called after init( ).
• stop( ): Called every time the applet moves out of sight on the Web browser to allow the applet to shut off expensive operations. Also called right before destroy( ).
• destroy( ): Called when the applet is being unloaded from the page to perform final release of resources when the applet is no longer used • Note that applets are not required to have a main( ). That’s all wired
into the application framework; you put any startup code in init( ).
24
Ejecución de applets
• To run this program you must place it inside a Web
page and view that page inside your Java-enabled
Web browser. To place an applet inside a Web page
you put a special tag inside the HTML source for that
Web page to tell the page how to load and run the
applet.
• Al principio (applets de AWT)
• <applet code=Applet1 width=100 height=50>
</applet>
• Después (Applet de Swing)
• With Internet Explorer, the extension mechanism is
the ActiveX control, and with Netscape it is the
plug-in. In your HTML code, you must provide tags to
support both.
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
25
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 Java 2 support for APPLET!! </NOEMBED> </EMBED> </OBJECT> <hr></body></html> 26
Con appletviewer
• Sun’s JDK (freely downloadable from java.sun.com)
contains a tool called the Appletviewer that picks the
<applet> tags out of the HTML file and runs the
applets without displaying the surrounding HTML
text.
• Because the Appletviewer ignores everything but
APPLET tags, you can put those tags in the Java
source file as comments:
•
// <applet code=MyApplet width=200 height=100>
•
// </applet>
• This way, you can run “appletviewer MyApplet.java”
and you don’t need to create tiny HTML files to run
tests.
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
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
– Si uno solicita sacar -500 € de un cajero no podrá hacerlo porque no tiene sentido según la “lógica del negocio” de los cajeros automáticos
– Si uno solicita sacar 998 € de un cajero, no podrá hacerlo porque la “lógica del negocio” dice que no se sacan monedas de cajeros
– Si uno solicita sacar a débito 1500 € de un cajero (y no tiene s aldo) no podrá hacerlo porque así lo indica la “lógica del negocio”
– ¿Los datos -500, 998 y 1500 son erróneos? Algunos podrán comprobarse en la presentación y otros en la lógica del negocio.
• En el ejemplo anterior del gestor de billetes…
– ¿La restricción de que los nombres deben tener al menos 5 caracteres y deben ser todos alfabéticos es una regla del negocio? ¿O es un problema de presentación?
– ¿Qué sucedería si después se decidiera no dar billetes si no se proporciona el nombre y el apellido? El código anterior NO VALDRÍA y tendríamos que cambiar el nivel de presentación. ¿Pero no es en realidad un cambio en una regla del negocio?
• Usando Applets (o JSPs ) no importaría 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
28
¿Validar la entrada es nivel de
presentación o lógica del negocio?
• Prever los cambios y colocarlo donde
mejor convenga
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
29
The jsp:setProperty Action
• <jsp:setProperty att=val*/>
• Set bean properties, either explicitly or
by designating that value comes from a
request parameter.
• Legal attributes are
– name="beanName"
– property="propertyName|*"
– param="parameterName"
– value="val"
30
The jsp:getProperty Action
• <jsp:getProperty name="propertyName "
•
value="val"/>
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
• <jsp:plugin attribute="value"*>...
•
</jsp:plugin>
• Generates OBJECT or EMBED tags, as
appropriate to the browser type, asking
that an applet be run using the Java
Plugin.
32
The jsp:forward Action
• <jsp:forward page="relative URL"/>
• Forwards request to another page.
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
33
JSP Introduction
• JSP makes it easier to create and maintain HTML, while still
providing full access to servlet code
• JSP pages get translated into servlets
– It is the servlets that run at request time
– Client does not see anything JSP-related
• You still need to understand servlets
– Understanding how JSP really works
– Servlet code called from JSP
– Knowing when servlets are better than JSP
– Mixing servlets and JSP
• Other technologies use similar approach,
but aren't as portable and don't let you use
Java for the "real code"
34
Uses of JSP Constructs
• Scripting elements
calling servlet code
directly
• Scripting elements
calling servlet code
indirectly (by means
of utility classes)
• Beans
• Custom tags
• Servlet/JSP combo
(MVC), with beans
and possibly custom
tags
Simple
Application
Complex
Application
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
JSP Scripting Elements
• JSP Expressions
• – Format: <%= expression %>
• – Evaluated and inserted into the servlet’s output. • • JSP Scriptlets
• – Format: <% code %>
• – Inserted verbatim into the servlet’s _jspService method • • JSP Declarations
• – Format: <%! code %>
• – Inserted verbatim into the body of the servlet class • • Predefined variables
• – request, response, out, session, application • • Limit the Java code that is directly in page
• – Use helper classes, beans, custom tags, servlet/JSP combo
36
JSP include Directive
• <%@ include file="url" %>
• A file on the local system to be included
when the JSP page is translated into a
servlet
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
37
Arquitectura 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 DE DATOS + 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
NO LO
HE DADO
38
Arquitectura física en 2 niveles:
cliente flaco/servidor gordo
• El despliegue de la aplicación es alto: instalar drivers y configurar todos los clientes (Idem.)
• Cambiar de SGBD requiere reinstalar todos los clientes
– Aún peor: El lenguaje para definir procedimientos almacenados
suele ser propietario (propio de cada SGBD)
• Cambiar el esquema de la BD puede afectar a los clientes (Idem.)
• Cambiar la lógica del negocio implica recompilar y desplegar en todos los clientes
– TAL VEZ NO, si afecta sólo a procedimientos almacenados
• Costos de conexión con la BD son altos. Cada cliente una conexión. (Idem.) • La red se puede sobrecargar. Cada sentencia SQL usa la red.
– ESTE PROBLEMA SE SUAVIZA.
A. Goñi, J.R. Zubizarreta, J. Iturrioz. Dpto. LSI, UPV/EHU
Presentación
Datos