Você está na página 1de 34

MEMORIA PRCTICA:

Sistemas de Gestin de Comercio Remoto


Asignatura: Sistemas Distribuidos

CURSO 2012-2013
Grado Ingeniera Informtica

Alumno: Vctor Colomo Gmez


DNI:
E-Mail: victor.colomo@gmail.com
Telfono:
Centro Asociado: Las Tablas (Madrid)
-1-

NDICE

1 Memoria Descriptiva......3

2 - Diagrama de clases ....8

3 - Ejemplos de ejecucin.......9

4 Conclusiones..18

5 - Cdigo fuente....19

-2-

1.- MEMORIA DESCRIPTIVA

Para la realizacin de esta prctica se ha utilizado el ID Eclipse SDK con la versin 4.2.1 y
y jdk1.7.0_09 de Java. Para disearla se han tenido en cuenta los siguientes aspectos:
- Un cliente slo puede tener registrada una demanda en el servicio Mercancas, si ya
tiene una demanda en el sistema e intenta introducir una nueva, no se incluir esta ltima,
se le devolver un boolean=false y se le indicar por pantalla que no ha sido registrada.
Para que el cliente pueda cambiar la demanda se ha incluido la opcin Eliminar
demanda en su men principal.
- Un distribuidor slo puede tener registrada una oferta en el servicio Mercancas, si ya
tiene una oferta en el sistema e intenta introducir una nueva, no se incluir esta ltima, se
le devolver un boolean=false y se le indicar por pantalla que no ha sido registrada.
Para que el distribuidor pueda cambiar su oferta se ha incluido la opcin Eliminar
demanda en su men principal.
Tambin se ha supuesto que el precio indicado cuando introducimos una ofertas es el
precio por kilogramo, con lo que no se lleva una contabilidad de los ingresos de los
distribuidores ni los gastos de los cliente
- Cuando un cliente elige la opcin Listar ofertas, se ha decidido simplemente listar las
ofertas y uno utilizar una devolucin de Llamada (callback)
- Cuando un cliente desea comprar una mercanca tiene que indicar el ID (nmero de
usuario) del distribuidor al que se va a conectar para comprar un determinado producto.
Para realizar la compra tendr que especificar la cantidad deseada, que puede ser la
totalidad de la oferta slo una parte.
Si el ID o la cantidad introducida es incorrecta, no se produce ninguna comprar y se indica
por pantalla.
Como slo es posible una oferta por distribuidor, no es necesario que el cliente
especifique el tipo de mercancia. Si el cliente ha introducido una demanda, est no tiene
que ser igual a la que oferta el distribuidor para que se realice la compra
- El nombre con que se hace referencia al objeto remoto de un distribuidor ser la
concatenacin de Distribuidor con su nmero de usuario (ID). La asignacin del puerto
se realiza desde el servicio autenticar del Regulador.

-3-

Se han diseado tres paquete y la estructura es la siguiente:

COMERCIO.COMMON: contiene el cdigo comn de


las tres entidades:
- Gui: clase creada para evitar la redundancia de
cdigo. Se utilizar cuando se muestra por pantalla el
men principal, para introducir texto, entero, float o
un tipo de mercanca por tecla y para limpiar la
pantalla
-Interfaces remotas de los servicios Autenticacin,
Mercancas y ventas
- TipoMercancia: clase que se utiliza para almacenar
una oferta o demanda. Sus atributos son:
Tipo (Sting), Precio (Float), Cantidad (int),
nombreServidor (Sting).
Contiene los mtodos necesarios para operar con
ellos.
- Utilis: contiene CODEBASE que nos evitar tener
que escribir la ruta del class path. Al pasarle una
clase, se obtiene la ruta donde esta cargada

COMERCIO.CLIENTE: cdigo utilizado por la entidad Cliente. Contiene su main.


COMERCIO.DISTRIBUIDOR: cdigo utilizado por la entidad Distribuidor. Incluye su main
y la clase que implementa la interfaz remota del servicio ventas
COMERCIO.REGUALADOR: cdigo utilizado por la entidad Regulador. Contiene su main
y las clases que implementan las interfaces remotas del servicio Autenticacin y
Mercancas.
La interaccin entre las tres entidades queda representada por el siguiente esquema:

-4-

A continuacin se explica la funcionabilidad de los tres servicios utilizados y como se ha


realizado su implementacin en Java:

SERVICIO AUTENTIFICACIN:
Su funcin es dar de alta a las entidades cliente y distribuidor, depende de la entidad
regulador. Este servicio consta de estas clase/intefaces:
ServicioAutenticacionInterface: contiene la interfaz remota del servicio.
ServicioAutenticacionImpl: clase que implementa la interfaz remota.
Incluye estos mtodos:
- public int Autenticar (String nombre, int tipo)
Cuando un cliente (tipo=1) un distribuidor (tipo=2) se dan da alta en el Regulador,
llaman a este mtodo pasndole su nombre (que previamente han introducido por
teclado) y su tipo, el servicio devuelve a la entidad demandante un identificador nico con
el que se podr registrar cualquier operacin en el sistema.
Anlogamente, se aaden en la lista de cliente (listaClientes) o distribuidores conectados
(listaDistribuidores y listaServicioVentas).
Cuando un Distribuidor se autentica, se aade en la listaServiciosVentas el nombre del
objeto remoto de su servicio de ventas para que un cliente conectarse a el.

- public void QuitarConectado(int id, int tipo)


Cuando una entidad demandante solicita salir se procede a darlo de baja en las listas
del regulador. Cuando se desconecta una entidad distribuidor, tambin se elimina de la
lista listaServiciosVentas.

- public void MostarLista(int tipo)


Con este mtodo el Regulador puede listar a todos los clientes (tipo=1) o distribuidores
(tipo=2) que se estn conectados actualmente

- public String MostrarServidorVentas (int id)


Cuando un Cliente desea comprar una determinada mercanca, realiza una llamada a
este mtodo pasndole como argumente el ID del Distribuidor al que va a realizar la
compra, y se le devuelve el nombre del objeto remoto al que va a conectarse.

- public int NumeroPuerto ()


Para asignar un nmero de puerto libre a cada Distribuidor para que pueda levantar
correctamente su servicio de Ventas, as evitamos que dos servicios tengan asignado el
mismo puerto

private static int getSesion(): mtodo privado que se utiliza para asignar un nmero de
ID distinto a cada entidad que se conecto. Se asignan nmeros correlativos empezando
en 100.

-5-

SERVICIO MERCANCIAS:
Se encargar de registrar las mercancas demandas por los clientes y las ofertas que
realizan los distribuidores, su finalidad es listar las ofertas de mercancas a los clientes
que lo soliciten, depende de la entidad regulador. Este servicio consta de estas
clase/intefaces
ServicioMercanciasInterface: contiene la interfaz remota del servicio.
ServicioMercanciasImpl: clase que implementa la interfaz remota.
Los mtodos utilizados son:
public void Listar (int tipo)
Con este mtodo el Regulador puede listar todas los ofertas realizadas por los
distribuidores (tipo=1) y las demandas de los clientes (tipo=2).

public void QuitarLista (int id, int tipo)


Para dar de baja una oferta o demanda de la lista correspondiente (listademandas o
listaofertas) cuando se realiza una venta, cuando un cliente o distribuidor lo solicita a
travs de su men principal o cuando cierra su sesin

public boolean IntroducirDemanda (int id, String tipo)


Para que los clientes puedan introducir sus demandas, para ello es necesario que pasa si
identificador y el tipo de mercanca demandada (Arroz, Lentejas, Garbanzos, Judas o
Soja).
El Regulador slo permite una demanda por cliente. Devuelve un boolean que indicar si
la demanda se ha introducido correctamente en el sistema o no (si ya existe una).

public Map<Integer, TipoMercancia> RecibirOfertas(String tipo)


Mtodo usuado por los clientes para recibir las ofertas existentes de un determinado tipo
de mercanca que es pasado como argumentp. Se devuelve un map con todas las ofertas
que cumplan la condicin, que posteriomente sern impresas en la pantalla en el cliente.

public boolean IntroducirOfertas (int id, TipoMercancia oferta)


Mtodo usuado por los distribuidores para introducir ofertas en el sistema.
El Regulador slo permite una oferta por Distribuidor. Devuelve un boolean que indicar si
la oferta se ha introducido correctamente en el sistema o no (si ya existe una, o si los
datos introducidos son incorrectos).

-6-

SERVICIO VENTAS:
Este servicio se encarga de completar las compradas solicitadas por los clientes. Ese
servicio consta de estas clase/intefaces:
ServicioVentaInterface: contiene la interfaz remota del servicio.
ServicioVentaImpl: clase que implementa la interfaz remota
Incluye los siguientes mtodos:
public void ListarVentas () :
Cuando el distribuidor llama a este mtodo, se listan todas sus ventas.
public boolean ComprarMercancia (int cantidad, String nombre):
Mtodo usado por el cliente para realizar la compra de un determinado producto. El
cliente pasa como argumentos la cantidad deseada y el nombre del objeto remoto del
ServicioVentas a travs del cual se va a realizar la compara. Devuelve un booleano que le
indicar al cliente si la compra se ha efectuado o no.
Si la venta se realiza correctamente, esta se aade en listaVentas para que el distribuidor
pueda realizar un seguimiento de sus ventas, se modifica la oferta actual con la cantidad
que hay disponible (o se elimina la oferta si se ha comprado su totalidad) y se realizan las
llamadas necesaras al servicio Mercancias para actualizar la mercanca disponible en el
servidor.
public void IncluirOferta (TipoMercancia oferta) :
Cuando un Distribuidor aade una oferta en el Servicio mercancas, a travs de este
mtodo tambin se aade en su servicio ventas, para posteriormente poder realizar
comprobaciones cuando se solicita una comprar por parte de un cliente.
public void setID (int miSesion) :
Mtodo que guardar el ID del Distribuidor que es pasado como argumento, que
posteriormente ser utilizado para identificarlo dentro del servio mercancas que depende
del Regulador

-7-

2.- DIAGRAMA DE CLASES


A continuacin se muestra el diagramas de clases del proyecto. Para facilitar la claridad
del mismos se han eliminado las operaciones con las clases Gui y TipoMercancia. En la
carpeta Diagramas se incluye este y otro con todos los enlaces.

-8-

3.- EJEMPLOS DE EJECUCIN


Para este ejemplo de ejecucin se ha arrancado primero el regulador (que tambin
levanta rmiregistry) y posteriormente 4 clientes y 3 distribuidores:
Los ID (identificador nico) asignado a los cliente son: 101 (Carrefour), 102 (Simply), 105
(Alcampo) y 106 (Mercadona), y a los distribuidores: 103 (Arroces SA), 104 (La paellera)
y 107 (Legumbres SL)

Posteriormente se ha aadido una demanda en cada cliente y una oferta en cada


distribuidor, se muestra un ejemplo:

-9-

Desde Regulador listamos los clientes y los distribuidores conectados, sus ofertas y
demandas respectivamente para comprobar que todo se ha registrado correctamente:

- 10 -

Desde el cliente 101-Carrefour listamos las ofertas de Arroz Disponibles:

Realizamos la compra introduciendo un ID incorrecto, por pantalla se muestra el error y se


vuelve a mostar el men del cliente:

- 11 -

Desde el mismo cliente, realizamos la compra al distribuidor 104 - La paellera, por una
cantidad inferior a disponible:

Desde el regulador vemos que la mercanca disponible del distribuidor 104 ha disminuido:

Verificamos que el distribuidor ha reflejado la venta:

- 12 -

Desde otro cliente (105 - Alcampo) revisamos las oferta de una mercanca no ofertada:

Desde el mismo cliente realizamos la comprar total de garbanzos disponibles en el


servidor 107 Legumbres SL:

- 13 -

Comprobamos la venta en el servidor con id 107:

Tambin comprobamos en el regulador que la oferta se ha eliminado:

En el Cliente 101 eliminamos su demanda, para comprobar despus en el regualdor que


se ha eliminado correctamente:

- 14 -

Por ltimo se procede a cerras el distribuidor con ID 104 y verificamos en el regulador que
se ha dado de baja en su lista de ofertas y distribuidores conectados:

- 15 -

Tambin se han controlado los posibles errores a la hora de realizara una compra. Tanto
en el servidor (si el tipo es incorrecto, si el precio o la cantidad es cero):

Como en el cliente, si el ID no tiene ninguna oferta en el sistema

- 16 -

O si las datos introducidos son incorrectos (si la cantidad es cero):

- 17 -

4.- CONCLUSIONES

Con el ejemplo mostrado anteriormente, se ha comprobado que se cumplen todas las


funcionalidades planteados en la prctico y que se controlan los posibles fallos que pudan
ocurrir, aunque si esta aplicacin se quisiera distribuir se podran realizar una sera de
mejoras para incremetar su funcionabilidad y sacar mayor provecho de ella:
- La ms destacable sera realizar un mayor control cuando un cliente realiza una compra:
cuando se introduce el ID del distribuidor se podra mostrar su oferta disponible y una
confirmacin por teclado para asegurar que la mercanca comprada es la deseada.
Adems se podra controlar la cantidad gastada por un cliente, llevar una cuenta de los
beneficios de un distribuidor
- Por otra parte, con el diseo actual tiene muy poco utilidad que un cliente introduzca en
el regulador su demanda, se podra mostar por la pantalla del cliente en las oferta que se
van introduciendo en el servicio mercancas que coincidad con el tipo demandado as
como la modificacin o la anulacin de las ofertas existentes. Con estos cambios, no
tendra casi utilidad la opcin Recibir ofertas de los clientes
A la hora de afrontar la prctica, se han contrado con una sere de dificultadas que se
han resuelto de la siguiente forma:
- En el Main del Distribuidor cuando se intentaba levantar el servicio de Mercancias al
utilizar el mtedo CODEBASE (para evitar tener que escribir el PATH), daba un error del
tipo java.lang.ClassCastException, se solvento aadiendo antes de conectarse al servicio
mercancas y autentificar.
Utilis.SetCodeBase(ServicioVentaInterface.class);
ServicioVentaImpl distribuidorVenta = new ServicioVentaImpl();
- Tambin ha provocado errores la utilizacin de tipos remote en los mtodos, una vez
incluidos dentro del main se han evitado estos errores, quizas no es la solucin ms
estticas pero s prctica ya que definiendolo como una variable global tampoco se
solucionaba.

- 18 -

5.- CDIGO FUENTE


A continuacin se muestra el cdigo fuente de la prctica:

PACKAGE COMERCIO.COMMON
/*******************************************************************************
* CLASE Gui
*******************************************************************************/
public class Gui {
// MTODO PARA MOSTRAR MEN DE LAS ENTIDADES
public static int MostrarMenu(String name, String[] entradas) {
int opcion=0;
System.out.println(" MENU " + name );
System.out.println("******************************");
for (int i = 0; i < entradas.length; i++) {
System.out.println((i + 1) + ".- " + entradas[i]);
}
try{
do{
Scanner entrada = new Scanner(System.in);
System.out.print("Selecciones una opcion [1-" + entradas.length+"]: ");
opcion = entrada.nextInt();
System.out.println();
System.out.println();
}while(opcion<0 && opcion>entradas.length);
}
catch (Exception e){
System.out.println();
System.out.println("ERROR EN LA OPCION ELEGIDA!!!");
}
return opcion;
}
// MTODO PARA LIMPIAR LA PANTALLA
public static void LimpiarPantalla() throws IOException {
System.out.println("Presione una tecla para continuar . . . ");
System.in.read();
for (int i = 0; i <30 ; i ++)
System.out.println();
}
// MTODO PARA INTRODUCIR EL TIPO DE MERCANCIA
public static String IntroducirMercancia() {
String tipo=null;
int mercancia=0;
String [] tipoMercancia = {"Arroz","Lentejas","Garbanzos","Judias","Soja"};
System.out.println("Mercancias disponibles");
System.out.println("1-Arroz, 2-Lentejas, 3-Garbanzos,4 -Judias, 5-Soja");
System.out.println();
try{
do{
System.out.print("Elija el tipo de Mercancia [1-5]: ");
Scanner entrada = new Scanner(System.in);
mercancia = entrada.nextInt();
tipo = tipoMercancia[mercancia-1];
System.out.println();
}while(mercancia<0 || mercancia>5);
}

- 19 -

catch (Exception e){


System.out.println("EROR EN LA MERCANCIA ELEGIDA!!!");
}
return tipo;
}
//MTODO PARA INTRODUCIR UN TIPO ENTERO
public static int IntroducirEntero(String texto){
int entero=0;
System.out.print(texto+": ");
try{
Scanner entrada = new Scanner(System.in);
entero = entrada.nextInt();
System.out.println();
}
catch (Exception e){
System.out.println();
System.out.println("ERROR AL INTRODUCIR DATO!!!");
}
return entero;
}
//MTODO PARA INTRODUCIR UN TIPO STRING
public static String IntroducirString(String texto) throws IOException{
String cadena=null;
System.out.print(texto+": ");
try{
BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
cadena = entrada.readLine();
}
catch (Exception e){
System.out.println("ERROR EN LA ENTRADA DE DATOS!!!!");
}
return cadena;
}
//MTODO PARA INTRODUCIR UN TIPO DOUBLE
public static float IntroducirDouble(String texto) throws IOException{
float decimal=(float) 0.00;
System.out.print(texto+": ");
try{
Scanner entrada = new Scanner(System.in);
decimal = entrada.nextFloat();
System.out.println();
}
catch (Exception e){
System.out.println("ERROR EN LA ENTRADA DE DATOS!!!!");
}
return decimal;
}
}

- 20 -

/*******************************************************************************
* CLASE ServicioAutenticacionInterface
*******************************************************************************/
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ServicioAutenticacionInterface extends Remote {
public int Autenticar (String nombre, int tipo) throws RemoteException;
public void QuitarConectado(int id, int tipo) throws RemoteException;
public void MostarLista(int tipo)throws RemoteException;
public int NumeroPuerto () throws RemoteException;
public String MostrarServidorVentas (int id) throws RemoteException;
}
/*******************************************************************************
* CLASE ServicioMercanciasInterface
*******************************************************************************/
import java.util.Map;
import java.rmi.Remote;
import java.rmi.RemoteException;
import comercio.common.TipoMercancia;
public interface ServicioMercanciasInterface extends Remote {
public void Listar (int tipo) throws RemoteException;
public boolean IntroducirDemanda (int id, String tipo) throws RemoteException;
public Map<Integer, TipoMercancia> RecibirOfertas(String tipo) throws RemoteException;
public boolean IntroducirOfertas (int id, TipoMercancia oferta) throws RemoteException;
public void QuitarLista (int id, int tipo) throws RemoteException;
}
/*******************************************************************************
* CLASE ServicioVentaInterface
*******************************************************************************/
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import comercio.common.TipoMercancia;
public interface ServicioVentaInterface extends Remote {
public void ListarVentas () throws RemoteException;
public boolean ComprarMercancia (int cantidad, String nombre) throws RemoteException,
NotBoundException;
public void IncluirOferta (TipoMercancia oferta) throws RemoteException;
public void setID (int miSesion, String nombreDistribuidor) throws RemoteException;
}

- 21 -

/*******************************************************************************
* CLASE TipoMercancia, definimos tipo de dato TipoMercancia para registrar ofertas, realizar
* compras
*******************************************************************************/
import java.io.Serializable;
public class TipoMercancia implements Serializable{
private static final long serialVersionUID = -4521893774105822732L;
private String tipo;
private float precio;
private int cantidad;
String servidorVenta;
public TipoMercancia(String tipo, float precio, int cantidad, String servidorVenta){
this.servidorVenta=servidorVenta;
this.tipo=tipo;
this.precio=precio;
this.cantidad=cantidad;
}
public TipoMercancia(){
}
public String getTipo(){
return tipo;
}
public float getPrecio(){
return precio;
}
public int getCantidad(){
return cantidad;
}
public String getServidor(){
return servidorVenta;
}
public void setCantidad(int nuevaCantidad){
this.cantidad=nuevaCantidad;
}
public void setPrecio(float nuevoPrecio){
this.precio=nuevoPrecio;
}
public void setTipo(String nuevoTipo){
this.tipo=nuevoTipo;
}
public void setServidorVenta (String nuevoServidorVenta){
this.servidorVenta=nuevoServidorVenta;
}}

/********************************************************************************
CLASE Utils, utilizada para tener que escribor el CLASSPATH
*******************************************************************************/
public class Utilis {
public static final String CODEBASE = "java.rmi.server.codebase";
public static void SetCodeBase(Class<?> c){
String ruta = c.getProtectionDomain().getCodeSource()
.getLocation().toString();
String path = System.getProperty(CODEBASE);
// Comprobamos si esta vacia
if (path != null && !path.isEmpty()){
ruta =path + " " + ruta;
}
System.setProperty(CODEBASE, ruta);
}}

- 22 -

PACKAGE COMERCIO.SERVIDOR
/*******************************************************************************
* CLASE MainRegulador
*******************************************************************************/
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import comercio.common.Gui;
import comercio.common.ServicioAutenticacionInterface;
import comercio.common.ServicioMercanciasInterface;
import comercio.common.Utilis;
public class MainRegulador {
public static void main(String[] args) throws Exception {
try{
int opcion=0;
//Pasamos la clase donde se encuentra la interface
Utilis.SetCodeBase(ServicioAutenticacionInterface.class);
// Creamos el objeto remoto, queda listo para recibir peticiones
ServicioAutenticacionImpl reguladorAutenticar = new ServicioAutenticacionImpl();
// Exportamos el objeto, accesible desde el puerto 7777
ServicioAutenticacionInterface remoteAutenticar = (ServicioAutenticacionInterface)
UnicastRemoteObject.exportObject(reguladorAutenticar, 7777);
// Ubicamos el registro y enviamos el cdigo
Registry registryAutenticar = LocateRegistry.getRegistry();
// Con REBIND enlazamos a un nombre y garantizamos que si un objeto remoto // se registr
previamente con
// dicho nombre, el nuevo objeto reemplazar al antiguo.
registryAutenticar.rebind("ReguladorAutenticar", remoteAutenticar);
System.out.println("Se ha levantado correctamente el SERVICIO AUTENTICAR");
// Realizamos lo mismos pasos para levantar SERVICIO MERCANCIAS
Utilis.SetCodeBase(ServicioMercanciasInterface.class);
ServicioMercanciasImpl reguladorMercancias = new ServicioMercanciasImpl();
ServicioMercanciasInterface remoteMercancias =
(ServicioMercanciasInterface)UnicastRemoteObject.exportObject
(reguladorMercancias, 7778);
Registry registryMercancias = LocateRegistry.getRegistry();
registryMercancias.rebind("ReguladorMercancias", remoteMercancias);
System.out.println("Se ha levantado correctamente el SERVICIO MERCANCIAS");
System.out.println();
do {
Gui.LimpiarPantalla();
opcion= Gui.MostrarMenu("REGULADOR", new String[]{"Listar ofertas actuales.","Listar
demandas actuales.",
"Listar clientes.","Listar distribuidores.","Salir."});
switch (opcion){
case 1: remoteMercancias.Listar(1); break;
case 2: remoteMercancias.Listar(2); break;
case 3: remoteAutenticar.MostarLista(1); break;
case 4: remoteAutenticar.MostarLista(2); break;
}
}while (opcion != 5);
System.out.println("SE VA A PROCEDER A CERRAR EL REGULADOR");
// ELIMINAMOS EL ENLACE
registryAutenticar.unbind("ReguladorAutenticar");
UnicastRemoteObject.unexportObject(reguladorAutenticar, true);
registryMercancias.unbind("ReguladorMercancias");
UnicastRemoteObject.unexportObject(reguladorMercancias, true);

- 23 -

System.out.println("REGULADOR Y SERVICIOS AUTENTIFICACION Y MERCANCIAS HAN


FINALIZADO CORRECTAMENTE");
}
catch (Exception e){
System.out.println("ERROR EN LA APLICACIN!!!!");
}
}
}

/*******************************************************************************
* CLASE ServicioAutenticacionImpl
*******************************************************************************/
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import comercio.common.ServicioAutenticacionInterface;
public class ServicioAutenticacionImpl implements ServicioAutenticacionInterface{
// MAP <numero_sesin,nombre_cliente> para almacenar los CLIENTES conectados
private static Map<Integer, String> listaClientes = new HashMap<Integer, String>();
// MAP <numero_sesin,nombre_cliente> para almacenar los DISTRIBUIDORES conectados
private static Map<Integer, String> listaDistribuidores = new HashMap<Integer, String>();
// Map <numero_sesin,nombre_objeto_remoto> para almacenar el nombre de los objetos remotos
del ServicioVentas
private static Map<Integer, String> listaServicioVentas = new HashMap<Integer, String>();
// ID para el nmero de sesin. Se empieza a asignar desde 100
private static int numero_sesion=100;
// Variable para asignar el n puerto de puerto disponible para el servicio de ventas del distribuidor
private static int numero_puerto=7778;
// MTODO QUE AUNTENTICA A LOS DISTRIBUIDORES O CLIENTE QUE LO SOLICITEN
public int Autenticar (String nombre, int tipo) throws RemoteException{
String numero, servicioventa;
// TIPO: 1 CLIENTE - 2 DISTRIBUIDOR
int idsesion=getSesion();
if (tipo==1){
// Aadimos el cliente a la lista de clientes conectados
listaClientes.put(idsesion,nombre);
}else{
// Aadimos el distribuidor a la lista de distribuidores conectados
listaDistribuidores.put(idsesion,nombre);
// El nombre del objeto remoto es --> Distribuidor+idsesion
numero=Integer.toString(idsesion);
servicioventa="Distribuidor".concat(numero);
// Aadimos el nombre del objeto remoto l
listaServicioVentas.put(idsesion, servicioventa);
}
return idsesion;
}
// MTODO QUE ELIMINA DE LAS LISTAS A LOS DISTRIBUIDORES O CLIENTE QUE LO
SOLICITEN
public void QuitarConectado(int id, int tipo)throws RemoteException{
// TIPO: 1 CLIENTE - 2 DISTRIBUIDOR
if (tipo==1){
// Eliminamos cliente de la lista cliente
//System.out.println("CLIENTE desconectado, lo eliminamos:");
listaClientes.remove(id);
}else{
// Eliminamos distribuidor de la lista distribuidor
//System.out.println("DISTRIBUIDOR desconectado, lo eliminamos:");

- 24 -

listaDistribuidores.remove(id);
listaServicioVentas.remove(id);
}
}
// MTODO QUE LISTA A LOS DISTRIBUIDORES O CLIENTE CUANDO EL REGULADOR LO
SOLICITA
public void MostarLista(int tipo)throws RemoteException{
// TIPO = 1 - CLIENTE
if (tipo==1){
int numeroClientes=listaClientes.size();
System.out.println("CLIENTES CONECTADOS A REGULADOR");
System.out.println("*******************************");
if (numeroClientes==0){
System.out.println("No hay clientes conectados");
}else{
System.out.println("Hay "+numeroClientes+" conectados");
System.out.println();
for (Entry<Integer, String> entry : listaClientes.entrySet()){
System.out.println("ID: "+entry.getKey()+"\t Nombre Cliente:
"+entry.getValue());
}
}
System.out.println();
}
// TIPO = 2 - DISTRIBUIDOR
if (tipo==2){
int numeroDistribuidores=listaDistribuidores.size();
System.out.println("DISTRIBUIDORES CONECTADOS A REGULADOR");
System.out.println("*************************************");
if (numeroDistribuidores==0){
System.out.println("No hay distribuidores conectados");
}else{
System.out.println("Hay "+numeroDistribuidores+" conectados");
System.out.println();
for (Entry<Integer, String> entry : listaDistribuidores.entrySet()){
System.out.println("ID: "+entry.getKey()+"\t Nombre Distribuidor:
"+entry.getValue());
}
}
}
System.out.println(); }
// METODO QUE DEVUELVE EL OBJETO REMOTO DEL SERVIDOR VENTAS CUANDO UN
CLIENTE LO SOLICITA
public String MostrarServidorVentas (int id) throws RemoteException{
String nombreservidor=null;
if (listaServicioVentas.containsKey(id)){
nombreservidor=listaServicioVentas.get(id);
}else{
nombreservidor=null;
}
return nombreservidor; }
// MTODO QUE DEVUELVE UN NMERO DE PUERTO DISPONIBLE AL DISTRIBUIDOR QUE
LOS SOLICITE
public int NumeroPuerto () throws RemoteException{
return ++numero_puerto; }
// MTODO QUE DEVUELVE EL NMERO DE SESIN
private static int getSesion(){
return ++numero_sesion;
}}

- 25 -

/*******************************************************************************
* CLASE ServicioMercanciasImpl
*******************************************************************************/
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import comercio.common.TipoMercancia;
import comercio.common.ServicioMercanciasInterface;
public class ServicioMercanciasImpl implements ServicioMercanciasInterface{
// ArrayList donde se almacenan las ofertas y demandas
private Map<Integer, String> listaDemandas = new HashMap<Integer, String>();
private Map<Integer, TipoMercancia> listaOfertas = new HashMap<Integer, TipoMercancia>();
// MTODO PARA LISTAR TODAS LAS OFERTAS O DEMANDAS DISPONIBLES CUANDO LO
SOLICITE EL REGULADOR
public void Listar(int tipo) throws RemoteException{
// TIPO = 1 - OFERTAS
if (tipo==1){
int numeroOfertas=listaOfertas.size();
TipoMercancia oferta = new TipoMercancia();
System.out.println("LISTADO DE OFERTAS ACTUALES");
System.out.println("****************************");
System.out.println();
if (numeroOfertas==0){
System.out.println("No hay ofertas disponibles");
}else{
System.out.println("Hay un total de: "+numeroOfertas+" ofertas");
System.out.println();
for (Entry<Integer, TipoMercancia> entry : listaOfertas.entrySet()){
System.out.println("ID del Distribuidor: "+entry.getKey());
System.out.println("===========================");
oferta =entry.getValue();
System.out.println("Mercancia: "+oferta.getTipo()+"\t \t
Precio-Kilo: "+oferta.getPrecio());
System.out.println("Cantidad: "+oferta.getCantidad()+"\t \t
Servidor de Ventas: "+oferta.getServidor());
}
}
// TIPO = 2 - DEMANDAS
}else{
int numeroDemandas = listaDemandas.size();
System.out.println("LISTADO DE DEMANDAS ACTUALES");
System.out.println("****************************");
if (numeroDemandas==0){
System.out.println("No hay demandas disponibles");
}else{
System.out.println("Hay un total de: "+numeroDemandas+" demandas");
System.out.println();
// Mostramos todas las ofertas disponibles
for (Entry<Integer, String> entry : listaDemandas.entrySet()){
System.out.println("ID del cliente: "+entry.getKey()+"\t Demanda:
"+entry.getValue());
}
}
}
System.out.println();
}

- 26 -

// MTODO QUE ELIMINA DE LAS LISTAS A LOS DISTRIBUIDORES O CLIENTE QUE LO


SOLICITEN
public void QuitarLista (int sesion, int tipo) throws RemoteException{;
// TIPO: 1 OFERTAS - 2 DEMANDAS
if (tipo==1){
listaOfertas.remove(sesion);
}else{
listaDemandas.remove(sesion);
}
}
// MTODO PARA INTRODUCIR NUEVA DEMANDA CUANDO UN CLIENTE LO SOLICITE
public boolean IntroducirDemanda (int id, String tipo) throws RemoteException{
boolean exito=false;
// Comprobamos si tiene alguna demanda en el sistemas
if (listaDemandas.containsKey(id)){
return exito;
}else{
// Si no tiene se aade.
exito = true;
listaDemandas.put(id,tipo);
return exito;
}
}
// MTODO QUE DEVUELVE LAS OFERTAS DE UN TIPO DETERMINADO DE MERCANCIA
CUAND UN CLIENTE LO SOLICITE
public Map<Integer, TipoMercancia> RecibirOfertas(String tipo) throws RemoteException{
//Map que ser devuelto con todas las coincidencias
Map<Integer, TipoMercancia> Ofertas = new HashMap<Integer, TipoMercancia>();
TipoMercancia comparar = new TipoMercancia();
String compararLista;
for (Entry<Integer, TipoMercancia> entry : listaOfertas.entrySet()){
comparar =entry.getValue();
compararLista =comparar.getTipo();
if (tipo.equals(compararLista)){
// Encontramos coincidencia, la aadimos al map
Ofertas.put(entry.getKey(), entry.getValue());
}
}
return Ofertas;
}
// MTODO PARA INTRODUCIR NUEVA OFERTA CUANDO UN DISTRIBUIDOR LO SOLICITE
public boolean IntroducirOfertas (int id, TipoMercancia oferta) throws RemoteException{
boolean exito=false;
// Comprobamos si tiene alguna oferta en el sistemas
if (listaOfertas.containsKey(id)){
return exito;
}else{
// Si no tiene se aade.
exito = true;
listaOfertas.put(id,oferta);
return exito;
}
}
}

- 27 -

/*******************************************************************************
* CLASE MainDistribuidor
*******************************************************************************/
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import comercio.common.Gui;
import comercio.common.TipoMercancia;
import comercio.common.ServicioAutenticacionInterface;
import comercio.common.ServicioMercanciasInterface;
import comercio.common.ServicioVentaInterface;
import comercio.common.Utilis;
public class MainDistribuidor {
private static int miSesion =0;
private static String nombre;
private static TipoMercancia oferta;
private static ServicioAutenticacionInterface servidorAutenticar;
private static ServicioMercanciasInterface servidorMercancias;
public static void main(String[] args) throws Exception {
try{
int opcion=0, puerto=0;
String servicioventa, numero;
// SERVICIO VENTAS
Utilis.SetCodeBase(ServicioVentaInterface.class);
ServicioVentaImpl distribuidorVenta = new ServicioVentaImpl();
/// SERVICIO AUTENTICAR //
Registry registry = LocateRegistry.getRegistry();
servidorAutenticar = (ServicioAutenticacionInterface) registry.lookup("ReguladorAutenticar");
// SERVICIO MERCANCIAS //
Registry registry2 = LocateRegistry.getRegistry();
servidorMercancias = (ServicioMercanciasInterface)
registry2.lookup("ReguladorMercancias");
nombre =Gui.IntroducirString("Introduzca nombre del distribuidor");
Autenticarse(nombre);
puerto=servidorAutenticar.NumeroPuerto();
// Exportamos el objeto, accesibles desde el puerto asignado por el regulador
ServicioVentaInterface remoteVenta = (ServicioVentaInterface)
UnicastRemoteObject.exportObject(distribuidorVenta, puerto);
// Ubicamos el registro y enviamos el cdigo
numero=Integer.toString(miSesion);
servicioventa="Distribuidor".concat(numero);
Registry registryVenta = LocateRegistry.getRegistry();
registryVenta.rebind(servicioventa, remoteVenta);
remoteVenta.setID(miSesion,nombre);
System.out.println();
System.out.println("Se ha levantado correctamente el SERVICIO VENTAS");
System.out.println("Servicio disponible desde: "+servicioventa);
System.out.println("En puerto: "+puerto);
System.out.println();
do {
Gui.LimpiarPantalla();
opcion= Gui.MostrarMenu("DISTRIBUIDOR", new String[]{"Introducir
oferta.","Mostrar ventas.",
"Eliminar oferta.","Salir"});
switch (opcion){
case 1:
float precio;
int cantidad;
boolean exito;

- 28 -

String tipo;
System.out.println("INTRODUCIR OFERTA");
System.out.println("==================");
tipo=Gui.IntroducirMercancia();
precio=Gui.IntroducirDouble("Introduzca el precio-Kilo");
cantidad =Gui.IntroducirEntero("Introduzca la cantidad");
oferta = new TipoMercancia(tipo,precio,cantidad,nombre);
if (tipo==null || precio==0.00 || cantidad ==0){
System.out.println("Los datos introducidos son incorrectos");
System.out.println("No es posible anadir la oferta");
System.out.println();
break;
}else{
exito = servidorMercancias.IntroducirOfertas(miSesion,
oferta);
if (!exito){
System.out.println("Ya tiene una oferta en el
Servidor Mercancias");
System.out.println("No es posible anadir una
nueva");
System.out.println();
break;
}else{
System.out.println("Oferta anadida correctamente");
remoteVenta.IncluirOferta(oferta);
}
}
System.out.println();
break;
case 2: remoteVenta.ListarVentas(); break;
case 3: EliminarOferta(); break;
}
}while (opcion != 4);
servidorAutenticar.QuitarConectado(miSesion,2);
servidorMercancias.QuitarLista(miSesion, 1);
registryVenta.unbind(servicioventa);
UnicastRemoteObject.unexportObject(distribuidorVenta, true);
System.out.println("Se ha cerrado correctamente el distribuidor: "+nombre);
}
catch (Exception e){
System.out.println("ERROR EN LA APLICION!!!");
servidorAutenticar.QuitarConectado(miSesion,2);
servidorMercancias.QuitarLista(miSesion, 1);
}}
// MTODO QUE REALIZA LA AUTENTICACIN EN EL REGULADOR
private static void Autenticarse (String nombre) throws RemoteException{
try{
miSesion =servidorAutenticar.Autenticar(nombre, 2);
System.out.println("DISTRIBUIDOR AUTENTICADO CORRECTAMENTE");
System.out.println("Su ID es: "+miSesion);
}
catch (Exception e){
System.out.println("ERROR NO SE HA PODIDO REGISTAR EL
DISTRIBUIDOR!!!!");
System.exit(2);
}}
// MTODO QUE ELIMINA AL CLIENTE DE LAS LISTAS DEL REGULADOR
private static void EliminarOferta()throws RemoteException{
try{
servidorMercancias.QuitarLista(miSesion, 1);

- 29 -

System.out.println("Servidor sin ofertas en el sistema");


System.out.println(); }
catch (Exception e){
System.out.println("ERROR NO SE HA PODIDO ELIMINAR LA OFERTA!!!");
}}}
/*********************************************************************************************
* CLASE ServicioVentaImpl
**********************************************************************************************/
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import comercio.common.ServicioMercanciasInterface;
import comercio.common.ServicioVentaInterface;
import comercio.common.TipoMercancia;
public class ServicioVentaImpl implements ServicioVentaInterface{
// LISTA DE LAS VENTAS REALIZADAS POR EL DISTRIBUIDOR
private Map<Integer, TipoMercancia> listaVentas = new HashMap<Integer, TipoMercancia>();
// OFERTA ACTUAL QUE TIENE EL DISTRIBUIDOR
private TipoMercancia ofertaActual;
private int idVenta=0;
private int miSesion=0;
private String nombreDistribuidor;

public void setID (int miSesion, String nombreDistribuidor) throws RemoteException{


this.miSesion=miSesion;
this.nombreDistribuidor= nombreDistribuidor;
}
// MTODO PARA LISTAR LAS VENTAS CUANDO EL DISTRIBUIDOR LO SOLICITE
public void ListarVentas () throws RemoteException{
int numeroVentas=listaVentas.size();
TipoMercancia mostrar = new TipoMercancia();
System.out.println("LISTADO DE VENTAS REALIZADAS");
System.out.println("****************************");
if (numeroVentas==0){
System.out.println("No se ha realizado ninguna venta");
}else{
System.out.println("N de ventas: "+numeroVentas+" ventas");
System.out.println();
for (Entry<Integer, TipoMercancia> entry : listaVentas.entrySet()){
System.out.println("ID de la venta: "+entry.getKey());
mostrar =entry.getValue();
System.out.println("Tipo Mercancia: "+mostrar.getTipo()+"\t Precio-kilo:
"+mostrar.getPrecio());
System.out.println("Cantidad: "+mostrar.getCantidad()+"\t \t Cliente:
"+mostrar.getServidor());
}
}
System.out.println();
}
// MTODO PARA COMPRAR MERCANCIA CUANDO EL DISTRIBUIDOR LO SOLICITE
public boolean ComprarMercancia (int cantidad, String nombreCliente) throws RemoteException,
NotBoundException{
boolean exito=false;

- 30 -

try{
// LEVANTAMOS EL SERVICIO MERCANCIAS PARA MODIFICAR LOS CAMBIOS EN EL
REGULADOR
ServicioMercanciasInterface servidorMercancias;
Registry registry = LocateRegistry.getRegistry();
servidorMercancias = (ServicioMercanciasInterface)
registry.lookup("ReguladorMercancias");
int restante=0;
if(ofertaActual.getCantidad()==cantidad){
idVenta++;
TipoMercancia compra = new
TipoMercancia(ofertaActual.getTipo(),ofertaActual.getPrecio(),cantidad,nombreClien
te);
listaVentas.put(idVenta, compra);
servidorMercancias.QuitarLista(miSesion, 1);
ofertaActual=null;
exito=true;
}else if (cantidad<ofertaActual.getCantidad()){
TipoMercancia venta=ofertaActual;
idVenta++;
restante=ofertaActual.getCantidad()-cantidad;
venta.setCantidad(cantidad);
venta.setServidorVenta(nombreCliente);
listaVentas.put(idVenta,venta);
ofertaActual= new TipoMercancia(ofertaActual.getTipo(),ofertaActual.getPrecio(),
restante, nombreDistribuidor);
servidorMercancias.QuitarLista(miSesion, 1);
servidorMercancias.IntroducirOfertas(miSesion, ofertaActual);
exito=true;
}
}
catch (Exception e){
System.out.println("ERROR EN LA APLICACIN!!!!");
}
return exito;
}
// MTODO QUE INCLUYE UNA OFERTA CUANDO EL DISTRIBUIDOR REGISTRA UNA NUEVA
public void IncluirOferta (TipoMercancia oferta) throws RemoteException{
int cantidad=oferta.getCantidad();
float precio=oferta.getPrecio();
String servidor=oferta.getServidor();
String tipo=oferta.getTipo();
ofertaActual = new TipoMercancia(tipo, precio, cantidad, servidor);
}
}

- 31 -

PACKAGE COMERCIO.CLIENTE
/*********************************************************************************************
* CLASE MainCliente
**********************************************************************************************/
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import comercio.common.ServicioAutenticacionInterface;
import comercio.common.ServicioMercanciasInterface;
import comercio.common.ServicioVentaInterface;
import comercio.common.TipoMercancia;
import comercio.common.Gui;
public class MainCliente {
private static int miSesion = 0; // Variable para almacenar ID del cliente
private static String nombreCliente;
// Variables para el Servidor, Autenticar, Mercancias y Ventas
private static ServicioAutenticacionInterface servidorAutenticar;
private static ServicioMercanciasInterface servidorMercancias;
private static ServicioVentaInterface servidorVentas;
public static void main(String[] args) throws Exception {
int opcion = 0;
try {
Registry registryAutenticar = LocateRegistry.getRegistry(); // Obtenemos el registro
//LOOKUP --> encontramos un objeto y obtenemos su referencia
servidorAutenticar = (ServicioAutenticacionInterface) registryAutenticar
.lookup("ReguladorAutenticar"); // Referencia remota del servidor
System.out.println("Acceso correcto a Servicio de Autentificacion");
Registry registryMercancias = LocateRegistry.getRegistry();
servidorMercancias = (ServicioMercanciasInterface) registryMercancias
.lookup("ReguladorMercancias");
System.out.println("Acceso correcto a Servicio Mercancias");
// PRIMER SE REALIZA AUTENTICACIN
// Solicitamos el nombre del cliente
nombreCliente = Gui.IntroducirString("Introduzca nombre de cliente");
Autenticarse(nombreCliente);
do {
Gui.LimpiarPantalla();
opcion = Gui.MostrarMenu("CLIENTE", new String[] {
"Introducir demanda.", "Recibir ofertas.",
"Comprar mercancia.", "Eliminar demanda", "Salir" });
switch (opcion) {
case 1:
AnadirDemanda();
break;
case 2:
RecibirOferta();
break;
case 3:
ComprarMercancia();
break;
case 4:
EliminarDemanda();
break;

- 32 -

}
} while (opcion != 5);
// CERRAMOS EL CLIENTE
servidorAutenticar.QuitarConectado(miSesion, 1);
servidorMercancias.QuitarLista(miSesion, 2);
System.out.println("SE HA CERRADO CORRECTAMENTE EL CLIENTE: "+
nombreCliente);
}
catch (Exception e) {
e.printStackTrace();
System.out.println("ERROR EN LA APLICACION!!!");
servidorAutenticar.QuitarConectado(miSesion, 1);
servidorMercancias.QuitarLista(miSesion, 2);
}
}
// MTODO QUE REALIZA LA AUTENTICACIN EN EL REGULADOR
private static void Autenticarse(String nombreCliente) throws RemoteException {
try{
miSesion = servidorAutenticar.Autenticar(nombreCliente, 1);
System.out.println();
System.out.println("CLIENTE AUTENTICADO CORRECTAMENTE");
System.out.println("Su ID es: " + miSesion);
System.out.println();
}
catch (Exception e){
System.out.println("ERROR NO SE HA PODIDO REGISTAR EL CLIENTE!!!!");
System.exit(2);
}
}
//MTODO QUE AADE LA DEMANDA EN EL REGULADOR
private static void AnadirDemanda() throws RemoteException {
try{
String tipo = Gui.IntroducirMercancia();
if (tipo==null){
System.out.println("El tipo de mercancia introducido es incorrectos");
}else{
boolean exito = servidorMercancias.IntroducirDemanda(miSesion, tipo);
if (!exito) {
System.out.println("No es posible anadir la demanda de " + tipo.toUpperCase());
System.out.println("Ya tiene una demanda en el Servidor Mercancias");
}else {
System.out.println("Demanda de " + tipo.toUpperCase() + " anadida
correctamente");
}
}
System.out.println();
}
catch (Exception e){
System.out.println("ERROR NO SE HA PODIDO ANADIR DEMANDA!!!");
}
}
private static void ComprarMercancia() throws RemoteException, NotBoundException {
try{
int idDistribuidor = Gui.IntroducirEntero("ID del Distribuidor");
int cantidad = Gui.IntroducirEntero("Cantidad que desea comprar");
// Obtenemos el objeto remoto del servicio Ventas
String servicioVenta = servidorAutenticar .MostrarServidorVentas(idDistribuidor);
if (servicioVenta == null) {
System.out.println("El ID del Distribuidor es incorrecto");
System.out.println("NO se ha podido realizar la compra");

- 33 -

}else if (cantidad==0){
System.out.println("La cantidad introducida es incorrecta");
System.out.println("NO se ha podido realizar la compra");
}else {
System.out.println("Procemos a conectarnos al Servicio de Ventas de: "
+ servicioVenta);
Registry registryVentas = LocateRegistry.getRegistry();
servidorVentas = (ServicioVentaInterface) registryVentas
.lookup(servicioVenta); // Nos conectamos al Servicio Ventas
System.out.println("Acceso correcto a su Servicio Mercancias");
boolean exito = servidorVentas.ComprarMercancia(cantidad, nombreCliente);
System.out.println();
if (exito) {
System.out.println("Se ha comprado la mercancia");
} else
System.out.println("No se ha podido realizar la compra, datos incorrectos");
}
System.out.println();
}
catch (Exception e){
System.out.println("ERROR EN LA APLICACIN!!!");
}}
private static void RecibirOferta() throws RemoteException {
try{
Map<Integer, TipoMercancia> ofertas = new HashMap<Integer, TipoMercancia>();
String tipo = Gui.IntroducirMercancia();
if (tipo == null){
System.out.println("El tipo de mercancia es incorrecto");
}else{
ofertas = servidorMercancias.RecibirOfertas(tipo);
if (ofertas.isEmpty()) {
System.out.print("No hay ofertas de " + tipo.toUpperCase());
System.out.println();
} else {
TipoMercancia mostrar = new TipoMercancia();
System.out.println("OFERTAS EXISTENTES DE: " + tipo.toUpperCase());
System.out.println("***********************************");
for (Entry<Integer, TipoMercancia> entry : ofertas.entrySet()) {
System.out.println("ID del Distribuidor: " + entry.getKey());
mostrar = entry.getValue();
System.out.println("Nombre del Distribuidor: "
+ mostrar.getServidor());
System.out.println(Precio-Kilo: " + mostrar.getPrecio()
+ "\t Cantidad: " + mostrar.getCantidad());
System.out.println();
}
}
}
}
catch (Exception e){
System.out.println("ERROR EN LA APLICACIN!!!!");
}}
private static void EliminarDemanda() throws RemoteException {
try{
servidorMercancias.QuitarLista(miSesion, 2);
System.out.println("Cliente sin demandas en sistema");
}
catch (Exception e){
System.out.println("ERROR NO SE HA PODIDO ELIMINAR LA DEMANDA!!!");
} }}

- 34 -

Você também pode gostar