Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ Parte I: Examen de teoría Duración: 2 horas, 30 minutos No se permite el uso de libros ni apuntes. Conteste cada pregunta en una hoja separada. Ejercicio 1. (1,5 puntos) Se desea desarrollar un sistema informático que gestione la organización de una universidad. Una universidad se caracteriza mediante su nombre y la ciudad donde se sitúa. A una universidad están vinculados dos tipos de personas: trabajadores y estudiantes. Cada persona tiene un DNI y un nombre. Los trabajadores pertenecen a dos grupos principales: personal docente e investigador (PDI) y personal administrativo y de servicios (PAS). Cada trabajador tiene asociados la categoría (caso del PDI) o el puesto que ocupa (caso del PAS), y una fecha de inicio de contrato. Los miembros del PDI pueden o no ser doctores. Las actividades que desarrolla el PDI son investigar y enseñar, mientras que la actividad que desarrolla el PAS es administrar. Un trabajador de una universidad puede cursar estudios en la universidad que lo contrata o en otra universidad (pista: recuerde el concepto de overlapping), pero sólo puede ser contratado por una única universidad. Cada universidad se compone de un conjunto de departamentos, cada uno de los cuales tiene un nombre y un conjunto de trabajadores adscrito. Un trabajador no puede estar adscrito a más de un departamento. Un PDI está adscrito obligatoriamente a un departamento mientras que un PAS, no. Cada departamento está dirigido por un doctor. Para simplificar el modelo, los alumnos estudian en una sola universidad y pueden ser o bien alumnos de grado, de una determinada titulación, o bien alumnos de doctorado, de un determinado programa de doctorado, pero no ambas cosas. Un alumno de grado puede también simultanear con sus estudios la colaboración en un departamento y puede realizar un PFC dirigido por un miembro del PDI. Un alumno de doctorado realiza una tesis dirigida por un doctor. Proporcione un modelo de esta descripción en forma de un diagrama de clases UML. Ejercicio 2. (1,5 puntos) (a) (0,5 puntos) Defina los conceptos siguientes tal y como se usan en el entorno de computación distribuida Jini: ● Proxy. Su descripción debe incluir el papel que desempeñan los proxies y los distintos tipos de proxy que pueden utilizarse en el entono Jini. ● Lookup service (o Servicio de Consulta). Su descripción debe incluir el papel que desempeña este servicio en el entorno Jini. (b) (1 punto) Describa cómo el entorno de computación distribuida Jini logra network plug and play (“enchufar y usar en red”), refiriéndose a las descripciones que ha proporcionado como respuesta al apartado previo. Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ Ejercicio 3 (2 puntos) (a) (0,5 puntos) Describa brevemente cada uno de los tres elementos estructurales (pista: fachada, funcionalidad e información no funcional) que componen un Enterprise Java Bean según las especificaciones EJB1 y EJB2 (pista: recuerde que en EJB2 se duplicó el número de partes constituyentes de uno de estos elementos estructurales con respecto a EJB1). (b) (1,5 puntos) Mire el código siguiente (conforme a la especificación EJB2) para una clase bean, y luego responda a las preguntas que aparecen a continuación. Note que ciertas partes del código se han reemplazado por XXXX package examples.XXX; import import import import java.sql.*; javax.naming.*; javax.ejb.*; java.util.*; public class AccountBean implements XXXXBean { protected XXXXContext ctx; private String accountID; // PK private String ownerName; private double balance; public AccountBean() { System.out.println("New Bank Account XXXX Bean Java Object created."); } public void deposit(double amt) throws AccountException { System.out.println("deposit(" + amt + ") called."); balance += amt; } public void withdraw(double amt) throws AccountException { System.out.println("withdraw(" + amt + ") called."); if (amt > balance) { throw new AccountException("Your balance is " + balance + "! You cannot withdraw " + amt + "!"); } balance -= amt; } public double getBalance() { System.out.println("getBalance() called."); return balance; } public void setOwnerName(String name) { System.out.println("setOwnerName() called."); ownerName = name; } public String getOwnerName() { System.out.println("getOwnerName() called."); return ownerName; } public String getAccountID() { System.out.println("getAccountID() called."); return accountID; } public void setAccountID(String id) { System.out.println("setAccountID() called."); this.accountID = id; } Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ public void ejbActivate() { System.out.println("ejbActivate() called."); } public void ejbRemove() throws RemoveException { System.out.println("ejbRemove() called."); AccountPK pk = (AccountPK) ctx.getPrimaryKey(); String id = pk.accountID; PreparedStatement pstmt = null; Connection conn = null; try { conn = getConnection(); pstmt = conn.prepareStatement("delete from accounts where id = ?"); pstmt.setString(1, id); if (pstmt.executeUpdate() == 0) { throw new RemoveException("Account " + pk + ": remove failed"); } } catch (Exception ex) { throw new EJBException(ex.toString()); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public void ejbPassivate() { System.out.println("ejbPassivate () called."); } public void ejbLoad() { System.out.println("ejbLoad() called."); AccountPK pk = (AccountPK) ctx.getPrimaryKey(); String id = pk.accountID; PreparedStatement pstmt = null; Connection conn = null; try { conn = getConnection(); pstmt = conn.prepareStatement("select ownerName, balance from accounts where id = ?"); pstmt.setString(1, id); ResultSet rs = pstmt.executeQuery(); rs.next(); ownerName = rs.getString("ownerName"); balance = rs.getDouble("balance"); } catch (Exception ex) { throw new EJBException("Account " + pk + ": load failed", ex); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public void ejbStore() { System.out.println("ejbStore() called."); Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ PreparedStatement pstmt = null; Connection conn = null; try { conn = getConnection(); pstmt = conn.prepareStatement("update accounts set ownerName = ?, balance = ? where id = ?"); pstmt.setString(1, ownerName); pstmt.setDouble(2, balance); pstmt.setString(3, accountID); pstmt.executeUpdate(); } catch (Exception ex) { throw new EJBException("Account " + accountID + ": save failed", ex); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public void setXXXXContext(XXXXContext ctx) { System.out.println("setXXXXContext called"); this.ctx = ctx; } public void unsetXXXXContext() { System.out.println("unsetXXXXContext called"); this.ctx = null; } public void ejbPostCreate(String accountID, String ownerName) { } public AccountPK ejbCreate(String accountID,String ownerName)throws CreateException { PreparedStatement pstmt = null; Connection conn = null; try { System.out.println("ejbCreate() called."); this.accountID = accountID; this.ownerName = ownerName; this.balance = 0; conn = getConnection(); pstmt = conn.prepareStatement("insert into accounts (id, ownerName, balance) values (?, ?, ?)"); pstmt.setString(1, accountID); pstmt.setString(2, ownerName); pstmt.setDouble(3, balance); pstmt.executeUpdate(); return new AccountPK(accountID); } catch (Exception e) { throw new CreateException(e.toString()); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public AccountPK ejbFindByPrimaryKey(AccountPK key) throws FinderException { Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ PreparedStatement pstmt = null; Connection conn = null; try { System.out.println("ejbFindByPrimaryKey(" + key + ") called"); conn = getConnection(); pstmt = conn.prepareStatement("select id from accounts where id = ?"); pstmt.setString(1, key.toString()); ResultSet rs = pstmt.executeQuery(); rs.next(); return key; } catch (Exception e) { throw new FinderException(e.toString()); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public Collection ejbFindByOwnerName(String name) throws FinderException { PreparedStatement pstmt = null; Connection conn = null; Vector v = new Vector(); try { System.out.println("ejbFindByOwnerName(" + name + ") called"); conn = getConnection(); pstmt = conn.prepareStatement("select id from accounts where ownerName = ?"); pstmt.setString(1, name); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { String id = rs.getString("id"); v.addElement(new AccountPK(id)); } return v; } catch (Exception e) { throw new FinderException(e.toString()); } finally { try { if (pstmt != null) pstmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } } public Connection getConnection() throws Exception { try { Context ctx = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("java:comp/env/jdbc/XXX-account"); return ds.getConnection(); } catch (Exception e) { System.err.println("Could not locate datasource! Reason:"); e.printStackTrace(); throw e; } } } Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ (i) (0,5 puntos) ¿Qué tipo de EJB se está codificando aquí? Proporcione toda la información que pueda, justificando su respuesta. (ii) (1 punto) Suponiendo que el EJB no tiene interfaces locales y que el cliente podrá acceder al saldo (balance), y podrá tanto acceder como modificar el nombre del propietario (ownerName) y el id de la cuenta (accountID), ¿qué forma tendrán las interfaces de este EJB? Ejercicio 4 (1,5 puntos) (a) La base de datos de un Centro de Soporte a Usuarios contiene las siguientes tablas: USUARIOS Código_Usuario Nombre_Usuario Departamento Nombre_Técnico Especialidad Cargo TECNICOS Código_Técnico INCIDENCIAS Código_Incidencia Descripción Código_Usuario Fecha_Recepción Código_Técnico Fecha_Resolución Al recibir una incidencia se registran la referencia a ella asignada, el código del usuario que lo comunicó, la descripción que de ella proporcionó este usuario, la fecha en la que se recibió, y el código del técnico asignado para su resolución. La fecha de resolución no se registrará hasta que el técnico comunique que la incidencia ha sido resuelta. Proporcione las sentencias SQL que implementan las siguientes instrucciones: (i) Borre de la base de datos las incidencias resueltas antes del 01-01-2005 (ii) Liste las incidencias reportadas por el departamento de ‘Marketing’ que hayan sido resueltas, reflejando la descripción de éstas, y las fechas de recepción y resolución, en orden decreciente respecto a su fecha de recepción. (iii) Liste el número de incidencias resueltas por cada técnico durante el año 2006 (iv) Cambie la especialidad de los técnicos que se especializan en ‘Comunicaciones’ y de los que se especializan en ‘Sistemas Distribuidos’ por ‘Infraestructuras’ Puede suponer que las fechas pueden compararse directamente y que, en el formato de fechas utilizado, el 1 de mayo de 2007, por ejemplo, se escribe 20070501. Como ayuda con el apartado (iii), considere el ejemplo siguiente: para calcular el número de incidencias que se hayan resuelto el mismo día en que se reportaron, utilizamos la función de conjuntos COUNT(*) para contar las filas de la tabla INCIDENCIAS en las que el valor de Fecha_Recepción es igual al valor de Fecha_Resolución. Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ Ejercicio 5. (3,5 puntos) (a) (0,5 puntos) Describa los distintos mecanismos de J2EE para mantener una sesión entre un usuario y una aplicación web. Se desea implementar una Mini-Tienda-Online con los siguientes componentes: • Un formulario de entrada (OrderItem.html) que tiene el siguiente aspecto: cuyo código es: <HTML> <HEAD> <TITLE>Order Item</TITLE> </HEAD> <BODY> <H1>Order Item</H1> <FORM action="/servlet/OrderItem" method="POST"> <P> Item: <INPUT type="TEXT" name="item" size="25" value=""><BR> Quantity: <INPUT type="TEXT" name="quantity" size="6" value=""> <P> <INPUT type="SUBMIT" name="Order Item" value="Order Item"> <INPUT type="RESET" name="Reset" value="Reset"> </FORM> <FORM action="/servlet/Checkout" method="POST"> <P> <INPUT type="SUBMIT" name="Checkout" value="Checkout"> </FORM> </BODY> </HTML> • El servlet OrderItemServlet, al que se envía la solicitud del formulario, y que anota el artículo y la cantidad solicitada en el Carro de Compra. • el servlet CheckOutServlet, con el que se hacen los pedidos de los artículos que se encuentran en el Carro de la Compra. El carro de la compra se almacena como una instancia de la clase ShoppingCartBean, cuyo código es: Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ import java.util.HashMap; import java.io.Serializable; public class ShoppingCartBean implements Serializable { HashMap items = new HashMap(); public ShoppingCartBean(){} public void addItem(String item, Integer quantity) { items.put(item, quantity); } public HashMap getItems() { return items; } } (b) (0.75 puntos) Complete el código del OrderItemServlet que se muestra a continuación, escribiendo donde indican los comentarios en negrita (puede escribir en el propio enunciado si quiere): import import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*; CompanyBean; public class OrderItemServlet extends HttpServlet { String[] params; PrintWriter out; public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { // obtener o crear una sesión res.setContentType("text/html"); out = res.getWriter(); // obtener o crear el shoppingCartBean String item=""; Integer quantity = null; params = req.getParameterValues("item"); if (params != null && params[0] != null) { item = params[0]; params = req.getParameterValues("quantity"); if (params != null && params[0] != null) { quantity = new Integer(params[0]); shoppingCartBean.addItem(item, quantity); // almacenar el shoppingCartBean en la sesión Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ out.println("Thank you for your order:<p>" + item + ", quantity: " + quantity); } } else { out.println("Error processing order."); } out.println("<hr>"); out.println("<a href=\"/index.html\">Back to index</a> " + "or <a href=\"/servlet/Checkout\">checkout</a>"); out.close(); } } (c) (1 punto) Modifique el código anterior para que redirija la ejecución directamente a la página de inicio si ha habido algún error. Puede utilizar pseudocódigo detallado si no recuerda la sintaxis exacta de alguna sentencia. (d) (1.25 puntos) El código del CheckoutServlet que se muestra a continuación (algunas sentencias han sido sustituidas por comentarios): import import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*; CompanyBean; public class CheckoutServlet extends HttpServlet { PrintWriter out; public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { // obtener la sesión out = res.getWriter(); if (session == null) { out.println("No items ordered!"); return; } // obtener el shoppingCartBean if (shoppingCartBean == null) { out.println("No items ordered!"); return; } HashMap items = shoppingCartBean.getItems(); Set itemSet = items.keySet(); Iterator iterator = itemSet.iterator(); String key; out.println("You ordered the following items:<p>"); out.println("<table>"); while (iterator.hasNext()) { key = (String)iterator.next(); out.println("<tr><td>" + key + "</td><td>" Examen de Software de Comunicaciones 5º Ingeniero de Telecomunicación 16 de febrero de 2007 Departamento de Ingeniería Telemática Universidad Carlos III de Madrid Nombre y apellidos:_____________________________________________ + items.get(key) + "</td></tr>"); } out.println("</table><p>"); out.println("Thank you for your order."); out.println("<hr>"); out.println("<a href=\"/index.html\">Back to index</a>"); out.close(); //cerrar la sesión } } Esta misma funcionalidad se puede realizar con una JSP en lugar de con un servlet. Indique en código o pseudocódigo cómo sería la JSP equivalente.