Wiki

Clone wiki

Publianuncios - TecSysWeb / Features

Características de la Aplicación

publianuncios2.png

Soporte a usuarios

En la esquina superior derecha un menú de dropdown muestra la opciones disponibles para usuario.

Registro

Los datos que se requieren son:

  • Email
  • Nombre
  • Contraseña(incluida confirmación)
  • Apellidos
  • Teléfono
  • Municipio(con tres select al estilo de la página principal)

Cabe señalar que la password nunca se almacena en ninguna tabla, sino que con ella se genera un usuario de la base de datos mediante un procedimiento almacenado, de forma que no es accesible mediante ninguna consulta SQL.

Registro OAuth

OAuth es un sistema de acceso a recursos de terceros, requiere que un cliente de OAuth esté verificado con anterioridad y se le asigne un id de cliente, las ventajas son que no requiere completar extensos formularios y que no hay un intercambio de credenciales del usuario a la aplicación, sino un intercambio de tokens, la autenticación se realiza utilizando una redirección al servidor de recursos, en nuestro caso Google+, y cuando acaba se llama a una url de callback verificada o bien alguna función javascript.

En nuestro caso cuando un usuario utiliza este tipo de registro se genera uno en nuestra base de datos, un usuario funcional que puede publicar anuncios y actuar como uno convencional.

Autenticación

Un sencillo formulario user/password permite acceder a usuarios previamente registrados, recuerde que sólo aquellos usuarios que optaron por el registro ordinario pueden hacerlo, el resto deben elegir la opción de login con Google+. Esta autenticación utiliza el sessionStorage de HTML5 y por tanto es persistente mientras el dominio sea el mismo. Un breve ejemplo de como se utiliza la API de este tipo de almacenamiento utilizando Coffeescript sería:

#!Coffeescript
sessionStorage.setItem 'email', 'pepe@pepe.com'
console.log sessionStorage.getItem 'email'
Aparece lo siguiente en la barra superior:

login.png

Logout

Equivale a lo siquiente:

#!Coffeescript
sessionStorage.removeItem 'email'
Se borra de la sesión, se redirige y desaparece el texto de la barra superior.

Filtrado de anuncios

Para visualizar anuncios no se requiere tener un usuario, el sitio posee un potente sistema de filtrado. La estructura de un anuncio es:

estructura.png

Categoría

En la zona superior izquierda de la página principal están las categorías, pinchando sobre cualquiera de ellas acotamos la búsqueda y el filtro.

Ubicación

Existen tres pestañas en el panel principal que muestran u ocultan una serie de select's para restringir la búsqueda:

  • Por comunidad autónoma.
  • Por provincia.
  • Por localidad.

Cabe señalar que cualquier anuncio está asociado a un usuario, sin embargo la localización de un usuario es siempre un municipio, por tanto una búsqueda por comunidad autónoma sería en realidad una búsqueda por todos los municipios que contiene, esto se logra gracias a las virtudes del lenguaje SQL y su sentencia INNER JOIN, de forma que un join de la tabla consigo misma una vez puede extraer municipios para una provincia y aplicada dos veces puede extraerlos para la comunidad gracias a su id de autoreferencia (idPadre). Las localizaciones se actualizan al cambiar el valor de los select's para provincia o comunidad utilizando AJAX.

Tags

Existe un campo de texto que toma en cuenta palabras clave que se encuentren separadas por comas, no importa cuantos espacios separen los tokens ya que la expresión regular de separación /\s*,+\s*/ los elimina:

#!Coffeescript
keys = $('input[name=keys]').val().split /\s*,+\s*/
El script tomará en cuenta estos tokens en la descripción del anuncio y mostrará resultados que muestren todas y cada una de la palabras clave (un and lógico).

Generación de anuncios

Además de mostrar permite generar anuncios para usuarios verificados, aparece un botón antes desconocido, en la barra superior y pinchando un formulario con tres campos:

  • Precio.
  • Descripción.
  • Categoría(un select con opciones añadidas mediante AJAX, al estilo de la página principal)
  • Foto.
  • Vídeo (opcional).

Cabe señalar que la subida se realiza por partes, primero el formulario requiere que todos sus campos estén completos tras lo cual se inicia la subida de la foto y/o el vídeo, hemos preferido guardar los archivos multimedia en el sistema de ficheros del servidor frente a añadir la foto en un campo 'Blob' a la base de datos por comodidad y eficiencia. Utilizamos un UUID (universal id) junto con la extensión del archivo original mediante el siguiente fragmento de código.

#!Java
String rnd = UUID.randomUUID().toString();
String extension = "";
int i = filename.lastIndexOf('.');
if (i > 0) {
    extension = filename.substring(i);
}
String path = Params.PHOTOS_PATH + rnd + extension;
File fileToCreate = new File(path);
FileUtils.copyFile(this.file, fileToCreate);
Las constantes Params.PHOTOS_PATH y Params.VIDEOS_PATH indican los directorios photos y videos ubicados en WebContent y por tanto son persistentes.

La segunda parte consiste en almacenar los datos simples del anuncio, la petición AJAX anterior devuelve los ids universales que ya pueden utilizarse en los campos pathFoto y pathVideo y se dispone a llamar a una de las acciones de struts.

Publicidad

Se han colocado una serie de iframe's con fondo amarillo a lo largo de toda la web, estos cuadros representan la publicidad existente en un sitio cualquiera. Se ha utilizado un segundo servidor Apache Tomcat (escuchando en el puerto 8085) como servidor de publicidad, este servidor tiene dos recursos .jsp accesibles:

  • enviarAnuncio.jsp
  • recibirPreferencia.jsp

Cada uno de los iframe's apunta su atributo src (source) al recurso enviarAnuncio.jsp, por tanto habrá que resolver un conflicto del tipo CORS (Cross-Origin Resource Sharing), nuestro browser bloqueará peticiones AJAX a otros dominios, por ello incluiremos la siguiente línea de código a la hora de enviar la petición:

#!Coffeescript
request.withCredentials = yes

Cabe decir que la funcion $.ajax del core de jQuery permite incluir esta característica pero tan solo desde la versión 1.5 en adelante. En el servidor por su parte colocaremos las dos cabeceras siguientes:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Hemos implementado una curiosa estrategia de marketing, utilizando la web lorempixel.com, esta web aporta imágenes gratuitamente que son utilizadas en maquetas web, incluye diferentes temáticas como animales, gatos, monumentos, ciudades, moda, etc. En concreto cuando nuestro usuario llega por primera vez no hay cookie de publicidad y la temática existente es 'abstract', cuando se pulsa sobre filtrar se accede al recurso recibirPreferencia.jsp y se establece una cookie, con una temática de forma aleatoria, esta temática podría establecerse en base a unos criterios determinados incluso utilizando complejos algoritmos y bases de datos con información del usuario.

En definitiva cuando en usuario accede a otra parte de la web o recarga, se puede ver que todas las imágenes pertenecen a una temática concreta, son 9 imágenes diferentes por temática, elegidas a su vez de forma aleatoria. La cookie dura 20 segundos tras lo cual la temática vuelve a ser de imágenes abstractas. A continuación se muestran dos ejemplos de publicidad:

adv-abstract.png adv-sidney.png

Métodos de pago

Se han colocados dos tipos de métodos de pago:

  • Si se quiere pagar mediante Paypal bastará con pulsar en el botón propio de esta plataforma. Su implementación ha sido sencilla, aunque no es trivial, ya que hay que acceder al sitio web de Paypal y crear un botón único por cada tipo de producto con un precio predeterminado, lo cual en nuestra aplicación no tiene sentido ya que son los propios usuarios los que crean cada anuncio. Por tanto, para probar este método se ha hecho un botón único para todos los anuncios, por un importe de 1 euro.

  • Para implementar el pago por tarjeta de crédito se ha recurrido a Paymill. un sistema real pero que nos permite crear una cuenta y utilizarla en modo prueba con números de tarjeta falsos. Se ha creado un formulario con los datos necesarios y que al momento de pagar se conectará con Paymill para comprobar que éstos son correctos.

Chat

Se ha implementado un Chat, mediante WebSockets, que permiten a las aplicaciones web mantener una comunicación bidireccional. Cuando se accede al chat se crea un nuevo WebSocket con la url para conectarlo al servidor. Si el usuario pulsa el botón Enviar en el cliente, el texto viaja al servidor en formato JSON, y éste lo procesa.

En el servidor debe haber un objeto capaz de aceptar peticiones ws para poder servirlas. Hemos utilizado la librería de Tomcat para WebSockets. Se ha creado una clase Chat.java que es un ServerEndPoint. Esta clase dispondrá de los métodos necesarios para gestionar conexiones de entrada, recepción de mensajes, cierre de conexiones y envío de mensajes.

Se podrá acceder al chat siempre que el usuario esté identificado, ya que cada mensaje irá precedido del usuario que lo envía. Se podrá escribir un mensaje y mantener una conversación con otros usuarios. Cada usuario dispondrá de un color en una paleta de colores de hasta 15 colores (que pueden repetirse si existen mas de 15 usuarios), gracias a un plugin cortesía de google.

chat.png

Handicaps de la aplicación

Refresco de la imagen

Después de la publicación del anuncio su imagen es ubicada en el directorio photos sin embargo el cliente redirecciona al índice y su imagen no aparece, esto se debe a un mal refresco por parte del servidor Tomcat, la imagen está pero el directorio no ha sido refrescado por Tomcat hasta los 5-10 segundos donde el refresco automático ya tiene en cuenta la imagen, esto podría solucionarse retrasando la publicación del anuncio hasta pasado ese tiempo.

Fichero de parámetros

Un fichero Params.java está ubicado bajo el paquete DAO, este archivo es ignorado explícitamente por git y por lo tanto no se encuentra en este repositorio, contiene usuarios y contraseñas que son utilizadas por el pool de conexiones así como rutas absolutas (i.e. directorio de fotos), esto es así para permitir la máxima flexibilidad y que cada componente del grupo tenga su configuración personalizada.

Funcionalidades sin implementar

Existen funcionalidades que aparecían en la maqueta original pero que no han sido desarrolladas como la búsqueda superior o la lista de deseos, no obstante no se ha eliminado por si hubiera futuros cambios.

Volver al índice

Updated