Conceptos básicos de servlets

 

1. Seguimos con nuestra aplicación de subastas de la sesión anterior. Nos queda definir el servlet central ServletMain. Hay algunos elementos que se dejan ya implementados, para facilitar la tarea y para no perder tiempo con aspectos de la aplicación que son secundarios en cuanto a manejo de servlets se refiere. Veremos primero qué es lo que ya hay hecho, y después lo que se pide hacer.

Elementos ya implementados:

Vector usuarios = new Vector();

que mantiene un listado de los usuarios que hay actualmente registrados en el servidor de subastas.

boolean validaUsuario(String login, 
                      String password)

boolean registraUsuario(String login, 
                        String password,
                        String email)

Usuario buscaUsuario(String login)

Con validaUsuario() podremos hacer que un usuario registrado entre al servidor con el login login y password password.  Devuelve true si se ha validado bien, false si no.

Con registraUsuario() podremos registrar un nuevo usuario, dando su login, password y e-mail. Devuelve true si se ha registrado bien, false si no (porque el login esté repetido, por ejemplo).

El método buscaUsuario() lo utilizan internamente los otros dos, para buscar el usuario de login login en la lista de usuarios. Devuelve el objeto Usuario con los datos del usuario, si se ha encontrado, o null si no se encontró.

Los elementos de esta tabla hash son objetos de la clase interna ObjetoSubasta, que contendrá los datos de cada producto que se tiene en la subasta:

Se tienen métodos para acceder a todos los campos, y un método:

void setPuja(String usuario, double valor)

que asigna un nuevo valor para el producto, ofrecido por el usuario usuario. Se empleará para ir incrementando el valor de la puja a medida que los usuarios vayan incrementando el valor ofrecido.

 

Elementos por implementar:

Lo que se pide en este ejercicio que hagamos sobre ServletMain es:

a) Al principio del método doGet(...) se deben tomar los parámetros de entrada del servlet, que serán:

String login = request.getParameter("login);
String password = request.getParameter("password");
String accion = request.getParameter("accion");

Si alguno de los parámetros de entrada es null, se redirige al servlet ServletLogin:

response.sendRedirect("/subasta/login");

 

b) Si están todos los parámetros, vamos comprobando qué acción hay que realizar.

registrar: si la acción es registrar, obtenemos el email del usuario (el login y password ya los hemos tomado antes), e intentamos llamar al método registraUsuario(...) de ServletMain. Si funciona bien redirigimos a ServletLogin para que entre, y si no, redirigimos a ServletRegistro para que vuelva a introducir los datos:

String email = request.getParameter("email");
if (registraUsuario(login, password, email))
	response.sendRedirect("/subasta/login");
else
	response.sendRedirect("/subasta/registro");

 

validar: si la acción es validar, intentamos llamar al método validaUsuario(...) de la clase ServletMain. Si no funciona, redirigimos a ServletLogin para que se vuelva a validar (si funciona no hace falta que hagamos nada).

if (!validaUsuario(login, password))
	response.sendRedirect("/subasta/login");

 

comprar: si la acción es comprar, se toman primero dos parámetros de entrada más: el producto que se compra y el valor que se ofrece:

String producto = request.getParameter("producto");
double valor = Double.parseDouble(request.getParameter("valor"));

Luego, tomamos el artículo, vemos si el valor ofertado es mayor que el actual, y si es así modificamos la puja. Luego redirigimos a este mismo servlet, con accion=validar, para que vuelva a validar al usuario:

ObjetoSubasta obj = (ObjetoSubasta)articulos.get(producto);

if (obj.getValor() < valor)
{
   obj.setPuja(login, valor);
   articulos.put(producto, obj);
}

response.sendRedirect("/subasta/main?accion=validar");

 

vender: si la acción es vender, se toman primero dos parámetros de entrada más: el producto que se pone en venta y el valor inicial:

String producto = request.getParameter("producto");
double valor = Double.parseDouble(request.getParameter("valor"));

Luego añadimos el artículo a la lista, y redirigimos a este mismo servlet, con accion=validar, para que vuelva a validar al usuario:

articulos.put(producto, new ObjetoSubasta(login, producto, valor));
response.sendRedirect("/subasta/main?accion=validar");

 

Adicionalmente, tenemos otras dos acciones, generadas desde el propio servlet ServletMain:

adjudicar: se utiliza para otorgar un artículo a un usuario. Toma primero un parámetro de entrada, el producto que se adjudica:

String producto = request.getParameter("producto");

Luego eliminamos el producto de la lista de artículos de la subasta, y redirigimos a este mismo servlet, con accion=validar:

articulos.remove(producto);
response.sendRedirect("/subasta/main?accion=validar");

cancelar: se utiliza para eliminar un artículo de la subasta, sin otorgarlo a ningún usuario. Toma primero un parámetro de entrada, el producto que se elimina:

String producto = request.getParameter("producto");

Luego eliminamos el producto de la lista de artículos de la subasta, y redirigimos a este mismo servlet, con accion=validar:

articulos.remove(producto);
response.sendRedirect("/subasta/main?accion=validar");

Aunque en apariencia estas dos acciones hacen lo mismo, en adjudicar se podrían tomar los datos del usuario al que se le adjudica el producto, o el valor por el que se vende, y sacar esa información por pantalla. Esto se deja como opcional.

 

c) Finalmente, se muestra una página con el estado actual de la subasta.

out.println ("<a href=\"/subasta/vender\">" + 
             "Vender un articulo</a>");
out.println ("<a href=\"/subasta/login\">" + 
             "Salir</a>");
Enumeration elem = articulos.elements();
while (elem.hasMoreElements())
{
   ObjetoSubasta os = (ObjetoSubasta)
                      (elem.nextElement());
   if (os.getPropietario().equals(login))
   {
	out.println("<br><a href=\"/subasta/main?" + 
                    "accion=adjudicar&producto=" + 
                    os.getProducto() + "\">Adjudicar</a> " + 

                    "<a href=\"/subasta/main?" + 
                    "accion=cancelar&producto=" + 
                    os.getProducto() + "\">Cancelar</a> " + 

                    os.getProducto() + " (" + os.getValor() + 
                    ") [" + os.getUsuario() + "] ");
   } 
}
Enumeration elem = articulos.elements();
while (elem.hasMoreElements())
{
   ObjetoSubasta os = (ObjetoSubasta)
                      (elem.nextElement());
   if (!os.getPropietario().equals(login))
   {
        out.println("<br><a href=\"/subasta/comprar?" + 
                    "producto=" + os.getProducto() + 
                    "\">Comprar</a> " + 

                    os.getProducto() + " (" + os.getValor() + 
                    ") [" + os.getUsuario() + "] ");
   }
}

 

d) IMPORTANTE: Notar que, con la estructura que le estamos dando a la aplicación, los datos del usuario validado (login y password) se pierden en las redirecciones. Para poderlos ir manteniendo a lo largo de las peticiones del usuario, tendremos que irlos pasando entre los servlets como parámetros de los formularios o enlaces:

<a href="/subasta/main?login=login&password=password...">
<input type="hidden" name="login" value="login">
<input type="hidden" name="password" value="password">

donde login y password son las variables donde se encuentren el login y password tomados, que ya habíamos asignado previamente:

String login = request.getParameter("login");
String password = request.getParameter("password");

 

NOTA: observad que para las acciones comprar, vender, adjudicar y cancelar se vuelve a llamar al servlet ServletMain con accion=validar. Esto es porque si se recarga la página y no cambiamos estas acciones, se volverá a comprar, vender, adjudicar o cancelar el artículo repetidamente. Necesitamos redirigir con otra acción para que estas no se repitan. Aseguraos que cualquier llamada a ServletMain desde los servlets periféricos que no implique una acción concreta tenga añadida la acción validar.

 

2.(OPTATIVO) Añadir una tabla en la página (a continuación de las listas de enlaces mostradas en el apartado c del ejercicio anterior) donde se muestren las últimas N acciones realizadas por los usuarios. Para ello podemos tener en la clase los campos:

final int MAXOPERACIONES = 10;
Vector ultimasOperaciones = new Vector();

Se trataría de mantener MAXOPERACIONES cadenas de texto en el vector ultimasOperaciones, insertando las últimas operaciones que se vayan produciendo, y eliminando las antiguas. Luego, para las operaciones actuales, se colocarían en una tabla, una en cada fila:

ultimasOperaciones.addElement("Venta de...");
ultimasOperaciones.removeElementAt(0);
<table border="0">
<th>ULTIMAS OPERACIONES</th>
<tr><td>Operacion 1</td></tr>
<tr><td>Operacion 2</td></tr>
...
<tr><td>Operacion MAXOPERACIONES</td></tr>

 

3.(OPTATIVO) Notar que algunas redirecciones de un servlet a otro indican un funcionamiento correcto (por ejemplo, si registramos a un usuario correctamente desde ServletRegistro, el servlet central redirige a continuación a ServletLogin para que entre en la subasta.

Sin embargo, otras redirecciones indican un error: si validamos incorrectamente a un usuario en ServletLogin, el servlet central vuelve a redirigir a ServletLogin. Esto puede confundir al usuario, que no sabe por qué se le está redirigiendo a una página u otra, y si ha hecho algo bien o mal.

Podemos añadir un parámetro más que pasar entre servlets, llamado error, que indique si ha habido algún error por el cual se ha redirigido a ese servlet. Por ejemplo, si validamos mal a un usuario, haremos:

if (!validaUsuario(login, password))
	response.sendRedirect("/subasta/login?error=Error+al+validar+usuario");

Se trataría de tomar dicho parámetro al principio de cada servlet que lo pueda recibir, y si no es nulo o vacío, mostrar su contenido en la página:

String error = request.getParameter("error");
...
if (error != null && error.length() > 0)
	out.println ("<b>Error:</b> " + error);