Ejemplo: Aplicación de estrategias de diseño con RMI

Anuncio
PROGRAMACION DISTRIBUIDA
Ejemplo de uso de estrategias
de diseño con RMI
Héctor Pérez
2
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Ejemplo de callback: SwiftEagle
shot()
Target
setDirection()
nearnessReport(target,observer)
¿signal?
Is near
explode()
SwiftEagle
(Server)
Missile
(remote)
ObserverTarget (Server)
signal()
shot(initPos,password)
getPosition():Position
setDirection(direction)
nearnessReport(target,observer)
explode()
turnOff()
Observer (remote)
MissileControler
(Client)
3
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Dos estrategias de que el Server transmita información al cliente
Polling (Estrategia client/Server estricta)
:SwiftEagle
:MissileController
Callback (Estrategia client/Server no estricta)
:SwiftEagle
:MissileController
getPosition()
Create and
register in RMI
:TargetObserver
nearnessReport(position, observer);
isInTarget()->false
getPosition()
isInTarget()->false
getPosition()
asClosedTotarget=true
observer.signal()
isInTarget()->true
4
RCSD: José M. Drake y Héctor Pérez
Organización del código
20/05/2015
5
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Especificación de la aplicación distribuida SwiftEagle (1/3)
6
RCSD: José M. Drake y Héctor Pérez
Especificación de la aplicación distribuida SwiftEagle (2/3)
TargetObserver
20/05/2015
7
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Especificación de la aplicación distribuida SwiftEagle (3/3)
TargetObserver
8
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Organización del código en paquetes
grant{
permission java.security.AllPermission;
}
grant{
permission java.security.AllPermission;
permission java.net.SocketPermission "*:1024-","accept, resolve";
}
9
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Tipos de datos comunes
public class Direction implements Serializable{
private static final long serialVersionUID = 333;
public double ux=0;
public double uy=0;
public double uz=0;
public Direction(double ux,double uy,double uz){
double mod=Math.sqrt(Math. pow(ux, 2)+ Math. pow(uy, 2)+ Math. pow(uz, 2));
if (mod!=0){this.ux=ux/mod;this.uy=uy/mod;this.uz=uz/mod;}
}
}
public class Position implements Serializable {
private static final long serialVersionUID = 444;
public double x, y, z;
public Position(double x,double y,double z){
t his.x=x; this.y=y; this.z=z;
}
}
public class UnknownException extends Exception {
private static final long serialVersionUID = 1 1 1 ;
}
public class UnreadyException extends Exception {
private static final long serialVersionUID = 222;
}
10
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Interfaces remotas definidas
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Observer extends Remote {
void signal() throws RemoteException;
}
import java.rmi.*;
public interface Missile extends Remote {
void shot(Position initPos, long password) throws UnreadyException, RemoteException;
Position getPosition() throws RemoteException;
void setDirection(Direction dir) throws RemoteException;
void nearnessReport (Position pos, Observer observer)
throws RemoteException;
void explode(long password) throws UnknownException,RemoteException;
void turnOff() throws RemoteException;
}
Parámetros que se pasan por
referencia remota
11
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Cliente: Objeto remoto TargetObserver
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Observer extends Remote {
void signal() throws RemoteException;
}
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class TargetObserver extends UnicastRemoteObject implements Observer {
public TargetObserver() throws RemoteException {
super();
}
public void signal() throws RemoteException {
MissileController.asCloseToTarget = true;
}
}
12
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Cliente: Clase principal MissileController
public class MissileController {
public static boolean asCloseToTarget=false;
public static void main(String[] args) {
String missileName=args[0];
try {
Observer observer=(Observer) new TargetObserver(); // Nuestro objeto de callback
long thePassword=(long)(Long.MAX_VALUE*Math.random());
Registry registry = LocateRegistry.getRegistry();
Missile theMissile = (Missile) registry.lookup(missileName);
theMissile.shot(new Position(0,0,0), thePassword);
//*** Comienza el control del missil ***//
theMissile.setDirection(new Direction(1,1,10));
theMissile.nearnessReport(new Position(0,0,1000), observer);//Pasamos objeto de callback al server
while(!asCloseToTarget){
¿código necesario?
Thread.sleep(500);
Position pos=theMissile.getPosition();
System.out.println("current position: "+pos.x+" "+pos.y+" "+pos.z);
}
try{ theMissile.explode( thePassword);
} catch(UnknownException u) { System.out.println("Eres un intruso y no exploto");
theMissile.turnOff();}
try { UnicastRemoteObject.unexportObject(observer, false);
} catch (NoSuchObjectException e) {...}
} catch (Exception e) { System.err.println("Excepción del cliente: " + e.toString());}
}
}
13
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Servidor: Clase servidora SwiftEagle (1/3)
public class SwiftEagle extends Thread implements Missile {
….
public void shot(Position initPos, long password) throws UnreadyException { . . .}
public Position getPosition() throws RemoteException {. . .}
public void setDirection(Direction dir)throws RemoteException {. . .}
public void explode(long password)throws UnknownException, RemoteException{. . . }
public void turnOff() throws RemoteException{. . .}
Observer observer;
public void nearnessReport(Position target, Observer observer) throws RemoteException {
this.target=target;
this.observer=observer;
}
Objeto de callback
public void run(){… observer.signal(); . . . }
14
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Servidor: Clase servidora SwiftEagle (2/3)
public class SwiftEagle extends Thread implements Missile {
...
public void run() {
while (!interrupted()) {
try {sleep(UPDATE_PERIOD);
} catch (InterruptedException e){break;}
pos.x+=vel*dir.ux*UPDATE_PERIOD/1000.0; // Actualizamos pos.y y pos.z también
...
if (target!=null) {
double currentTargetDist=Math.sqrt( . . .);
if (currentTargetDist>targetDist){
target=null;
targetDist=Double.MAX_VALUE;
callback
try {
observer.signal();
} catch (RemoteException e) {…}
} else {targetDist=currentTargetDist;}
}
}
try {UnicastRemoteObject.unexportObject(this, false);
} catch (NoSuchObjectException e) {…}
} // Close run
15
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Servidor: Clase servidora SwiftEagle (3/3)
public class SwiftEagle extends Thread implements Missile {
…/….
public static void main (String[] args) {
String missileName= null;
if (args.length >=1)
missileName = args[0];
SwiftEagle eagle=new SwiftEagle();
try{
Remote rmtRef= UnicastRemoteObject.exportObject(eagle,0);
Registry theRegistry=LocateRegistry.createRegistry(1099);
theRegistry.rebind(args[0], rmtRef);
} catch (RemoteException e) {
System.err.println("Error en Servidor SwiftEagle " +args[0]);
System.exit(-1);
}
System.out.println("Servidor SwiftEagle " +args[0]+ " READY");
} // Close main
} // Close SwftAegle
16
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Ejecución
Cliente
Servidor SwitfEagle
17
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Variaciones (1/2)
! ¿Cómo minimizar los cambios en el código de
negocio?
18
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Uso del patrón proxy
clase modificada
clase nueva
19
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Cliente: Nueva clase proxy SwiftEagle
public class SwiftEagle {
Registry registry = null;
String missileName = “Misil7831”;
Missile theMissile = null;
// Constructor del proxy
public SwiftEagle(){
try {
registry = LocateRegistry.getRegistry(); // Localiza el Registry en el puerto 1099
this.theMissile = (Missile) registry.lookup(missileName); // Localiza el misil
} catch (RemoteException e) {. . .}
catch (NotBoundException e) {. . .}
}
Invocación remota
public void setDirection(Direction dir) {
try {
theMissile.setDirection(dir);
} catch (RemoteException e) {. . .}
}
public Position getPosition() throws RemoteException {. . .}
}
...
20
RCSD: José M. Drake y Héctor Pérez
20/05/2015
Cliente: Clase principal MissileController modificada
public class MissileController {
public static boolean asCloseToTarget=false;
public static void main(String[] args) {
try {
Observer observer=(Observer) new TargetObserver(); // Nuestro objeto de callback
long thePassword=(long)(Long.MAX_VALUE*Math.random());
// *** Se genera el proxy ***//
SwiftEagle theMissile = new SwiftEagle ();
Código nuevo
theMissile.shot(new Position(0,0,0), thePassword);
//*** Comienza el control del missil ***//
theMissile.setDirection(new Direction(1,1,10));
theMissile.nearnessReport(new Position(0,0,1000), observer);//Pasamos objeto de callback al server
while(!asCloseToTarget){
Thread.sleep(500);
Position pos=theMissile.getPosition();
System.out.println("current position: "+pos.x+" "+pos.y+" "+pos.z);
}
try{ theMissile.explode( thePassword);
} catch(UnknownException u) { System.out.println("Eres un intruso y no exploto");
theMissile.turnOff();}
try { UnicastRemoteObject.unexportObject(observer, false);
} catch (NoSuchObjectException e) {...}
} catch (Exception e) { System.err.println("Excepción del cliente: " + e.toString());}
}
}
21
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Variaciones (2/2)
! ¿Cómo minimizar los cambios en el código de
negocio?
! ¿Cómo implementar la carga dinámica de clases?
22
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Carga dinámica de clases (1/6)
grant{
permission java.security.AllPermission;
}
grant{
permission java.security.AllPermission;
permission java.net.SocketPermission "*:1024-","accept, resolve";
}
23
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Carga dinámica de clases (2/6)
public class SwiftEagle extends Thread implements Missile {
…/….
public static void main (String[] args) {
String missileName= null;
if (args.length >=1)
missileName = args[0];
SwiftEagle eagle=new SwiftEagle();
try{
Remote rmtRef= UnicastRemoteObject.exportObject(eagle,0);
Registry theRegistry=LocateRegistry.getRegistry();
theRegistry.rebind(args[0], rmtRef);
} catch (RemoteException e) {
System.err.println("Error en Servidor SwiftEagle " +args[0]);
System.exit(-1);
}
System.out.println("Servidor SwiftEagle " +args[0]+ " READY");
} // Close main
} // Close SwftAegle
24
RCSD: José M. Drake y Héctor Pérez
SwiftEagle: Carga dinámica de clases (3/6)
20/05/2015
25
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Carga dinámica de clases (4/6)
! Dado que el registro no tiene acceso a las clases del
proyecto, debemos indicarle dónde puede
descargarlas (http, file, ftp, etc)
26
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Carga dinámica de clases (5/6)
! Por defecto, el rmiregistry sólo permite cargar las
clases que están en su CLASSPATH
27
RCSD: José M. Drake y Héctor Pérez
20/05/2015
SwiftEagle: Carga dinámica de clases (6/6)
! Para habilitar la carga dinámica de stubs, debemos modificar
la propiedad UseCodebaseOnly del rmiregistry
" si es TRUE, la carga de clases sólo se realiza desde el CLASSPATH y desde
el java.rmi.server.codebase de la JVM del rmiregistry
Descargar