3.4: Arquitecturas Software de 3.4: Arquitecturas 3.4: Software de Varios Niveles A. Goñi, J. Ibáñez, J. Iturrioz, J.A. Vadillo OCW 2013 Índice Introducción Arquitectura lógica del software en capas: presentación, lógica del negocio y datos. A i Arquitectura fí física i en 2 niveles: i l cliente li gordo/servidor flaco Arquitectura física en 2 niveles: cliente flaco/servidor gordo Arquitectura física en 3 (o más) niveles Introducción Hay aplicaciones que deben ejecutar operaciones de manera CONCURRENTE, SEGURA, FIABLE y EFICIENTE CLIENTE (INTERFAZ GRÁFICA) BASE DE DATOS Introducción Ejemplos: j p Terminales donde se pueden comprar entradas p para espectáculos p Cajeros automáticos conectados a una central Oficinas de reservas y compra de vuelos y viajes. SOLUCIÓN: usar una Arquitectura Arq it t r con n despliegue d pli d de componentes mp n nt software en el lado del servidor Componente: código que implementa un conjunto conocido de interfaces Ejemplo: comprar billetes para espectáculos BASE DE DATOS RELACIONAL public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel( JLabel(“Nombre:”); Nombre: ); JButton jButton1 = new JButton(“Pedir Billete”); public PedirBilleteNO3NIVELES() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); i D i M tC ti ("jdb db Bill t ") } void jButton1_actionPerformed(ActionEvent e) { ResultSet rs = sentencia.executeQuery( sentencia.executeQuery("SELECT SELECT NUMERO FROM"+ " BILLETES WHERE ESTADO=\'LIBRE\'"); if (rs.next()) { int act = sentencia.executeUpdate( sentencia executeUpdate("UPDATE UPDATE BILLETES BILLETES"+ + " SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+ " WHERE NUMERO="+rs.getString("NUMERO")+ " AND ESTADO ESTADO='LIBRE'"); '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);}} Ejemplo: comprar billetes para espectáculos Billete Espectáculo num =0 0 estado=Comprado nombre=Kepa Sola +num +estado +nombre num=1 estado=libre nombre num=2 estado=libre nombre BASE DE DATOS ORIENTADA A OBJETOS 75 public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel(“Nombre:”); JButton jButton1 = new JButton(“Pedir Billete”); public bli static t ti String St i ESPECTACULO = “Oscar “O 2011”; 2011” ObjectContainer db; public PedirBilleteNO3NIVELES() { db=DB4oManager.getContainer(); } void jButton1_actionPerformed(ActionEvent e) { Espectaculo esp= Espectaculo.getEspectaculo(ESPECTACULO); Billete b b= esp.getBilleteLibre(); int num=b.comprar(jTextField1.getText()); jTextArea1.append("Asignado. \nReferencia: "+n+"\n"); db store(b); db.store(b); } public bli static t ti void id main i (St (String i []arg) [] ) { PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES(); b.setVisible(true);}} Problema… Problema • E En las l iimplementaciones l t i anteriores t i NO SE SEPARA el código correspondiente a los siguientes aspectos: – Presentación – Lógica del negocio – Datos • O lo que es lo mismo: – NO SE APLICA UNA ARQUITECTURA SOFTWARE DE VARIOS NIVELES public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel(“Nombre:”); JButton jButton1 = new JButton(“Pedir Billete”); public bli static t ti String St i ESPECTACULO = “Oscar “O 2011”; 2011” ObjectContainer db; PRESENTACIÓN public PedirBilleteNO3NIVELES() { db=DB4oManager.getContainer(); } void jButton1_actionPerformed(ActionEvent e) { Espectaculo esp= db.getEspectaculo(ESPECTACULO); Billete b b= esp.getBilleteLibre(); int num=b.comprar(jTextField1.getText()); jTextArea1.append("Asignado. \nReferencia: "+n+"\n"); db store(b); db.store(b); } public bli static t ti void id main i (St (String i []arg) [] ) { PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES(); b.setVisible(true);}} public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel(“Nombre:”); JButton jButton1 = new JButton(“Pedir Billete”); public bli static t ti String St i ESPECTACULO = “Oscar “O 2011”; 2011” ObjectContainer db; ACCESO A DATOS public PedirBilleteNO3NIVELES() { db=DB4oManager.getContainer(); } void jButton1_actionPerformed(ActionEvent e) { Espectaculo esp= db.getEspectaculo(ESPECTACULO); Billete b b= esp.getBilleteLibre(); int num=b.comprar(jTextField1.getText()); jTextArea1.append("Asignado. \nReferencia: "+n+"\n"); db store(b); db.store(b); } public bli static t ti void id main i (St (String i []arg) [] ) { PedirBilleteNO3NIVELES b = new PedirBilleteNO3NIVELES(); b.setVisible(true);}} public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel(“Nombre:”); JButton jButton1 = new JButton(“Pedir Billete”); public bli static t ti String St i ESPECTACULO = “Oscar “O 2011”; 2011” ObjectContainer db; public PedirBilleteNO3NIVELES() { db=DB4oManager.getContainer(); } void jjButton1_actionPerformed(ActionEvent _ e) { Espectaculo esp= db.getEspectaculo(ESPECTACULO); Billete b= esp.getBilleteLibre(); int num=b.comprar(jTextField1.getText()); num b.comprar(jTextField1.getText()); jTextArea1.append("Asignado. \nReferencia: "+n+"\n"); db.store(b); } LÓGICA DEL NEGOCIO public static void main (String []arg) { P di Bill t NO3NIVELES b = new PedirBilleteNO3NIVELES(); PedirBilleteNO3NIVELES P di Bill t NO3NIVELES() b.setVisible(true);}} public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel( JLabel(“Nombre:”); Nombre: ); JButton jButton1 = new JButton(“Pedir Billete”); PRESENTACIÓN public PedirBilleteNO3NIVELES() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); i D i M tC ti ("jdb db Bill t ") } void jButton1_actionPerformed(ActionEvent e) { ResultSet rs = sentencia.executeQuery( sentencia.executeQuery("SELECT SELECT NUMERO FROM"+ " BILLETES WHERE ESTADO=\'LIBRE\'"); if (rs.next()) { int act = sentencia.executeUpdate( sentencia executeUpdate("UPDATE UPDATE BILLETES BILLETES"+ + " SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+ " WHERE NUMERO="+rs.getString("NUMERO")+ " AND ESTADO ESTADO='LIBRE'"); '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);}} public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel( JLabel(“Nombre:”); Nombre: ); JButton jButton1 = new JButton(“Pedir Billete”); ACCESO A DATOS public PedirBilleteNO3NIVELES() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); i D i M tC ti ("jdb db Bill t ") } void jButton1_actionPerformed(ActionEvent e) { ResultSet rs = sentencia.executeQuery( sentencia.executeQuery("SELECT SELECT NUMERO FROM"+ " BILLETES WHERE ESTADO=\'LIBRE\'"); if (rs.next()) { int act = sentencia.executeUpdate( sentencia executeUpdate("UPDATE UPDATE BILLETES BILLETES"+ + " SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+ " WHERE NUMERO="+rs.getString("NUMERO")+ " AND ESTADO ESTADO='LIBRE'"); '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);}} public class PedirBilleteNO3NIVELES extends JFrame { // Nota: NO ESTÁ COMPLETA !! JLabel jLabel1 = new JLabel( JLabel(“Nombre:”); Nombre: ); JButton jButton1 = new JButton(“Pedir Billete”); LÓGICA DEL NEGOCIO public PedirBilleteNO3NIVELES() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager.getConnection("jdbc:odbc:Billetes"); i D i M tC ti ("jdb db Bill t ") } void jButton1_actionPerformed(ActionEvent e) { ResultSet rs = sentencia.executeQuery( sentencia.executeQuery("SELECT SELECT NUMERO FROM"+ " BILLETES WHERE ESTADO=\'LIBRE\'"); if (rs.next()) { int act = sentencia.executeUpdate( sentencia executeUpdate("UPDATE UPDATE BILLETES BILLETES"+ + " SET ESTADO='OCUPADO', NOMBRE = "+jTextField1.getText()+ " WHERE NUMERO="+rs.getString("NUMERO")+ " AND ESTADO ESTADO='LIBRE'"); '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);}} Arquitectura lógica del software en niveles (capas) NIVEL (CAPA) DE PRESENTACIÓN Ó interfaces de usuario y la interacción con el mismo NIVEL (CAPA) DE LÓGICA DEL NEGOCIO resolver los p problemas del negocio g implementar las reglas propias del negocio. NIVEL (CAPA) DE DATOS BD donde se proporciona la persistencia SE APLICA UNA ARQUITECTURA LÓGICA Ó EN VARIAS CAPAS SI ESTAS ESTÁN SEPARADAS EN CLASES O COMPONENTES DISTINTOS Arquitectura lógica del software en niveles MÁS EXTENSIBILIDAD 1. NIVEL DE 1.PRESENTACIÓN Nombre: Pedir Billete INTERFAZ GRÁFICO DE USUARIO 2.- NIVEL DE LÓGICA DEL NEGOCIO public class GB implements GestorBilletes { ... public int getBillete (String nom) { {...} } CLASES CON OPERACIONES PROPIAS DEL NEGOCIO 3.- NIVEL DE DATOS SELECT ... INSERT ... ObjectContainer db db.store() - inicializarSala - getBillete,... Aquíí se pueden A d aplicar li reglas l d dell negocio: por cada 10 billetes comprados se regala uno, etc... BASE DE DATOS Arquitectura lógica del software en niveles Ventaja: Se puede cambiar cada uno de d llos niveles l minimizando d l cambios los bi en llos otros t niveles i l UNA ARQUITECTURA LÓGICA DEL SOFTWARE EN VARIOS NIVELES FAVORECE LA EXTENSIBILIDAD Y REUTILIZACIÓN DEL SOFTWARE El diseño de los casos de uso que hemos realizado es compatible con una arquitectura software en varios niveles Diagrama de secuencia (BD OO) Lógica del Negocio : Usuario : PedirBillete : GestorBilletes : BD Dar nombre nom y espectáculo esp Datos getBillete(nom,esp) e:=getEspectaculo(esp) g p ( p) e: Espectaculo b:=getBlleteLibre() Presentación b : Billete comprar(b,nom) setNombre(nom) ( ) store(b) b 88 Diagrama de secuencia (BD Rel.) Ló i del Lógica d l Negocio N i : Usuario : PedirBillete : GestorBilletes : GestorBD Proporcionar nombre y solicitar billete Datos getBillete(nombre) executeQuery:=executeQuery( P1) : ResultSet new() Presentación next() next() [hay libres] : get( get("NUMERO") NUMERO ) num executeUpdate:=executeUpdate(P2) P1: SELECT NUMERO FROM BILLETES WHERE ESTADO='LIBRE' b : Billete P2: UPDATE BILLETES SET ESTADO='OCUPADO' WHERE NUMERO = %num% new(num, nom) [no hay libres]: new(-1, "") b Arquitectura física del software f en niveles i l L CAPAS LÓGICAS se pueden Las d d desplegar l en distintos NODOS/NIVELES FÍSICOS Arquitectura en 2 niveles Capa de presentación en NODO CLIENTE Capa de datos en NODO SERVIDOR (de BD) ¿Y la capa de lógica del negocio? En el CLIENTE: junto con el nivel de presentación PARTE podría juntarse con el nivel de datos Arquitectura q en 3 niveles (o ( más)) Cada nivel, al menos, en un nodo distinto Arquitectura física en 2 niveles: cliente gordo/servidor flaco El nivel de presentación y el de la lógica del negocio g se unen en un nodo. En el otro queda q el nivel de datos. CLIENTE NIVEL DE PRESENTACIÓN NIVEL DE LÓGICA DEL NEGOCIO SERVIDOR NIVEL DE DATOS • Comunicación entre Cliente y Servidor en SQL Q / db4o • Se necesitan APIs como por ejemplo JDBC y/o ODBC, db4o • Deben instalarse DRIVERS de la BD en todos los clientes CLIENTE public class PedirBillete2NivCliGordo extends JFrame { GestorBilletes2NivCliGordo gestorBilletes; Presentación 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");} } Lógica ó i del Negocio i public class GestorBilletesBD implements GestorBilletes2NivCliGordo {p 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 asignado else return new Billete(-1,"");; } // No había ninguno libre}}} DEFINIR FUENTE DATOS ODBC “Billetes” E INSTALAR LA CLASE sun.jdbc.odbc.JdbcOdbcDriver BD Datos SERVIDOR CLIENTE public class PedirBillete2NivCliGordo extends JFrame { GestorBilletes2NivCliGordo gestorBilletes; Presentación 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");} } Lógica ó i del Negocio i public class GestorBilletesBD implements GestorBilletes2NivCliGordo {p public GestorBilletesBD () { db=DB4oManager.getContainer(); } public Billete getBillete(String nom) {Espectaculo esp= db.get Espectaculo (nom); Billete b=esp.getBilleteLibre(); int num=b.comprar(nom); db.store(b); return b;} BD Datos SERVIDOR INSTALAR LA CLASE com.db4o.DB4oManager 93 CLIENTE Sentencia SQL CLIENTE Respuesta CLIENTE CLIENTE BD Driver CLIENTE CLIENTE dbcDriver CLIENTE OdbcDriver CLIENTE CLIENTE c.JdbcOdbcDriver CLIENTE CLIENTE bc.JdbcOdbcDriver SERVIDOR CLIENTE bc.odbc.JdbcOdbcDriver CLIENTE CLIENTE n.jdbc.odbc.JdbcOdbcDriver CLIENTE ¡¡ CADA CLIENTE CLIENTE sun.jdbc.odbc.JdbcOdbcDriver sun.jdbc.odbc.JdbcOdbcDriver CLIENTE sun.jdbc.odbc.JdbcOdbcDriver sun.jdbc.odbc.JdbcOdbcDriver UNA CONEXIÓN ABIERTA CON LA BD!! CLIENTE Petición Db4o CLIENTE Resultado CLIENTE CLIENTE BD ager CLIENTE CLIENTE Manager g CLIENTE oManager CLIENTE CLIENTE o.DB4oManager CLIENTE CLIENTE 4o.DB4oManager SERVIDOR CLIENTE m.db4o.DB4oManager CLIENTE CLIENTE com.db4o.DB4oManager CLIENTE ¡¡ CADA CLIENTE CLIENTE com.db4o.DB4oManager com.db4o.DB4oManager CLIENTE com.db4o.DB4oManager com.db4o.DB4oManager UNA CONEXIÓN ABIERTA CON LA BD!! 95 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 altos. Cada cliente una conexión. La red se puede sobrecargar. sobrecargar Cada sentencia SQL usa la red. red Arquitectura física en 3 niveles CLIENTE CLIENTE SERVIDOR CLIENTE SERVIDOR Nivel de Presentación Nivell de Ni d Lógica Ló i del d l Negocio N i (en APPLICATION SERVERS) Ni l de Nivel d Datos D BASE DE DATOS CLIENTE public class PedirBillete extends JFrame { GestorBilletes gestorBilletes; Presentación 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");} } BD Datos SERVIDOR DATOS SERVIDOR APLICACIONES INSTALAR LA CLASE sun.jdbc.odbc. JdbcOdbcDriver Y DEFINIR FUENTE DATOS ODBC “Billetes” public class ServidorGestorBilletesBD Lógica del Negocio implements GestorBilletes { public ServidorGestorBilletesBD() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager conexion DriverManager.getConnection( getConnection("jdbc:odbc:Billetes");} jdbc:odbc:Billetes );} public Billete getBillete(String nom) {ResultSet rs = sent.executeQuery("SELECT NUMERO…";); int act = sent.executeUpdate( sent.executeUpdate("UPDATE UPDATE BILLETES … …“); ); if (act>0) return new Billete(n,nom); // Núm. billete asignado else return new Billete(-1,"");; } // No había ninguno libre}}} BD sun.jdbc.odbc.JdbcOdbcDriver SERVIDOR CLIENTE APLICACIONES CLIENTE CLIENTE sun.jdbc.odbc.JdbcOdbcDriver SERVIDOR SERVIDOR CLIENTE DATOS APLICACIONES CLIENTE CLIENTE CLIENTE CLIENTE SERVIDOR APLICACIONES C CLIENTE CLIENTE sun.jdbc.odbc.JdbcOdbcDriver CLIENTE CLIENTE CLIENTE ¡¡ SÓLO LOS SERVIDORES CLIENTE CLIENTE DE APLICACIONES TIENEN CLIENTE CONEXIONES ABIERTAS CLIENTE CON LA BD!! BD com.db4o.DB4oManager SERVIDOR CLIENTE APLICACIONES CLIENTE CLIENTE com.db4o.DB4oManager SERVIDOR SERVIDOR CLIENTE DATOS APLICACIONES CLIENTE CLIENTE CLIENTE CLIENTE SERVIDOR APLICACIONES C CLIENTE CLIENTE com.db4o.DB4oManager CLIENTE CLIENTE CLIENTE ¡¡ SÓLO LOS SERVIDORES CLIENTE CLIENTE DE APLICACIONES TIENEN CLIENTE CONEXIONES ABIERTAS CLIENTE CON LA BD!! Las aplicaciones Web permiten más niveles CLIENTE (N W (Nav. Web) b) CLIENTE (Nav Web) (Nav. SERVIDOR WEB SERVIDOR WEB SERVIDOR APLICACIONES CLIENTE (N W (Nav. Web) b) CLIENTE (N W (Nav. Web) b) SERVIDOR WEB SERVIDOR APLICACIONES Nivell de Ni d Presentación P t ió (instalación) Nivel de Lógica del Negocio Nivel de Datos BASE DE DATOS Nivel de P Presentación t ió (ejecución) CLIENTE Navegador Web Ejecutar Presentación SERVIDOR WEB BD Datos HTML + JSP + Bean Instalar Presentación SERVIDOR DATOS SERVIDOR APLICACIONES INSTALAR LA CLASE sun.jdbc.odbc. JdbcOdbcDriver Y DEFINIR FUENTE DATOS ODBC “Billetes” public class ServidorGestorBilletesBD Lógica del Negocio implements GestorBilletes { public ServidorGestorBilletesBD() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conexion=DriverManager conexion DriverManager.getConnection( getConnection("jdbc:odbc:Billetes");} jdbc:odbc:Billetes );} public Billete getBillete(String nom) {ResultSet rs = sent.executeQuery("SELECT NUMERO…";); int act = sent.executeUpdate( sent.executeUpdate("UPDATE UPDATE BILLETES … …“); ); if (act>0) return new Billete(n,nom); // Núm. billete asignado else return new Billete(-1,"");; } // No había ninguno libre}}} BD sun.jdbc.odbc.JdbcOdbcDriver SERVIDOR APLICACIONES sun.jdbc.odbc.JdbcOdbcDriver jdb db Jdb Odb D i SERVIDOR APLICACIONES SERVIDOR WEB CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE SERVIDOR WEB CLIENTE CLIENTE CLIENTE C CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE CLIENTE SERVIDOR DATOS SERVIDOR APLICACIONES sun jdbc odbc JdbcOdbcDriver sun.jdbc.odbc.JdbcOdbcDriver EN LOS CLIENTES NO HAY QUE INSTALAR NADA (EXCEPTO NAVEGADOR WEB+ INTERNET) 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 g del negocio g NO implica p recompilar p y desplegar en todos los clientes. Costos de conexión con la BD NO son tan altos. Los clientes no realizan li conexiones i con lla BD BD. Sólo Sól los l servidores id con lla lógica del negocio lo hacen. En general, general se MEJORA en EFICIENCIA EFICIENCIA, MANTENIMIENTO y EXTENSIBILIDAD Arquitectura q física en 3 niveles Existe tecnología que permite construir aplicaciones siguiendo esta filosofía de componentes y objetos distribuidos (server (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 p presentación se p puede dividir más usando JJava Applets, Servlets y/o JSPs CORBA es una arquitectura para comunicación entre objetos bj t distribuidos di t ib id a través t é de d ORBs ORB (Object (Obj t Request R t Brokers). Es un estándar definido por OMG. DCOM/COM+ y la plataforma .NET NET es la tecnología equivalente desarrollada por Microsoft Arquitectura q 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 j del NIVEL DE PRESENTACIÓN EN UN navegador WEB (Págs. con Applets o Págs. JSPs) JSPs) Computación con objetos distribuidos (RMI) para definir el NIVEL LÓGICA DEL NEGOCIO e iinvocarlo l ddesde d ell NIVEL DE PRESENTACIÓN Llamadas a JSPs y de ellos a JavaBeans Conexión con BDs relacionales (JDBC) o con BDOOs (db4o) para conseguir la comunicación entre NIVEL LÓGICA DEL NEGOCIO y DATOS