0% encontró este documento útil (0 votos)
100 vistas

Java RMI

1) Java RMI permite crear applets basados en la web que realizan operaciones poderosas del lado del servidor como acceder a bases de datos o comunicarse con aplicaciones de servidores remotos. 2) Sin embargo, algunas limitaciones de RMI hacen que su uso en applets basados en Internet sea poco práctico. 3) El artículo describe una forma de evitar estas limitaciones mediante el uso de servlets de Java y la serialización de objetos para la comunicación applet-servidor.

Cargado por

Vanessa Chacon
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
100 vistas

Java RMI

1) Java RMI permite crear applets basados en la web que realizan operaciones poderosas del lado del servidor como acceder a bases de datos o comunicarse con aplicaciones de servidores remotos. 2) Sin embargo, algunas limitaciones de RMI hacen que su uso en applets basados en Internet sea poco práctico. 3) El artículo describe una forma de evitar estas limitaciones mediante el uso de servlets de Java y la serialización de objetos para la comunicación applet-servidor.

Cargado por

Vanessa Chacon
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 25

Java RMI (Remote Method Invocation) la tecnologa hace que sea muy fcil crear

applets basados en la web que realizan poderosos del lado del servidor las
operaciones, como acceder a una base de datos o la comunicacin con
aplicaciones de servidores remotos. Sin embargo, una serie de limitaciones RMI
hacen que su uso en Internet basados en applets poco prcticas. En este
artculo se describe una forma de evitar estas limitaciones mediante el uso de
servlets de Java y la serializacin de objetos para la comunicacin applet /
servidor, y demuestra varias maneras de utilizar esta tcnica. El objetivo de este
artculo es sobre la conversin de una aplicacin existente, pero el mismo diseo
se pueden utilizar al crear nuevas aplicaciones.

Message Passing y llamada a procedimiento remoto


Fundamentos de paso de mensajes
En general hay dos tipos de primatives: enviar (mensaje, a) y recibir
(mensaje, desde).
Recibe puede bloquear, no bloqueo, ya menudo se obtiene tanto de
opciones. Enviar puede estar bloqueando, tamponada, sin bloqueo, o
cualquier combinacin.
Los mensajes pueden ser entendidas como que se envan a travs de
canales (o direcciones). Algunos diseos permiten mltiples recibe. Si
es as, debemos hacer la pregunta aunque slo sea un receptor recibe
un mensaje (en el mejor de quetries simples, como HTTP) o todo recibe
un mensaje (en el mejor de los mensajes de apagado, etc.)
Por ltimo, algunos sistemas de empaquetar todo para que pareciera
una RPC. Esto se realiza a travs de bloqueo enva / recibe, y algunos
de maniobra. Generalmente hablando RPC es menos flexible que el
paso de mensajes, pero ms fcil para el programador. Y normalmente
ahorro de tiempo del programador es ms importante de ahorro de
tiempo de ejecucin (normalmente).
marshalling
Marshalling es el acto de agrupar todos los parmetros para una
llamada de procedimiento en un mensaje, y luego la separacin de
ellos a su regreso. En trminos generales esto es difcil pero factible. Si
un procedimiento quiere enviar 3 ints, puede enviar los 12 bytes. Si

otro procedimiento quiere enviar 3 flotadores, tambin puede enviar


12 bytes. El receptor necesita saber cmo descodificar estos 12 bytes.
Normalmente esto se logra haciendo que cada funcin (nombre,
firma) se asignan a un entero, y anteponiendo esta int en el mensaje.
Pero cmo se puede manejar los parmetros por defecto? Y qu
acerca de los punteros?
La respuesta Java es usar la inteface Serializable.
The Java RMI Basics
En trminos generales, se trata de cmo funciona todo.
El servidor crea algunos objetos, y le dice al registro de ellos.
El servidor crea skels para esos objetos y esos skels comenzar
lisstening de solicitudes.
El cliente solicita el registro de dnde se encuentran los objetos y se
le dice la direccin del servidor
El cliente crea talones para cada objeto remoto encontrado, y estos
pedir a los talones de skels para pedir al servidor para preformas
algunas operaciones en la cuenta de clientes.
Los objetos pueden vivir ms all de su uso por cualquier cliente.
El servidor puede aceptar bytecode que manipula objetos para el
cliente. Eso es una ventaja nica Java (tm).
Envo de ByteCode
Un mtodo puede recibir como argumento un tipo de objeto que nunca
ha odo hablar antes. Cmo: sucesiones.
Sin embargo, el receptor tendr que utilizar los mtodos asociados con
ese objeto, por lo que se necesita el cdigo que implementa estos
mtodos.
Desde bytecode Java es porttil, esto se puede hacer. Pero pensar en
los dolores de cabeza de clasificacin. Y pensar en los riesgos para la
seguridad!
Objetos remotos y locales
Un objeto es un objeto local, al igual que tuvimos en CS120. Cuando un
objeto local se enva a un receptor JVM, la JVM recibe una copia de todo
el objeto y cualquier cdigo de bytes necesarios como se describe
anteriormente. Cuando un objeto remoto capaz es enviado a un
receptor JVM, la JVM slo se pone un trozo, y todas las operaciones
sobre el objeto remoto se envan a travs del taln a la ubicacin de
los objetos originales.

Un objeto se convierte remoto capaces de implementar interfaces


remotas. Slo los mtodos definidos en las interfaces remotas pueden
ser llamados remotamente. Interfaces remotas son creados por
Una interfaz remota ampla el java.rmi.Remote interfaz.
Cada mtodo de la interfaz declara java.rmi.RemoteException en su
clusula throws, adems de las excepciones especficas de la
aplicacin.
Los objetos remotos deben
Declarar las interfaces remotas estn aplicando
Definir el constructor para el objeto remoto
Proporcione una implementacin para cada mtodo remoto en las
interfaces remotas
Pasar argumentos en RMI
Los argumentos de las o los valores devueltos por mtodos remotos
pueden ser de cualquier tipo, incluidos los objetos locales, objetos
remotos, y los tipos primitivos. Ms precisamente, cualquier entidad de
cualquier tipo puede ser pasado a o por un mtodo remoto siempre
que la entidad es una instancia de un tipo que es un tipo de datos
primitivo, un objeto remoto, o un objeto serializable, lo que significa
que implementa la interfaz java.io.Serializable.
Unos pocos tipos de objetos no cumplen ninguno de estos criterios y
por lo tanto no se puede pasar o regresar de un mtodo remoto. La
mayora de estos objetos, tal como un descriptor de archivo,
encapsular la informacin que tiene sentido slo dentro de un nico
espacio de direcciones. Muchas de las clases fundamentales, incluidos
los de la java.lang y java.util paquetes, implementar la interfaz
Serializable.
Las normas que rigen cmo los argumentos y valores de retorno se
transmiten son los siguientes.
Los objetos remotos son esencialmente pasa por referencia. Una
referencia a un objeto remoto es un esbozo, que es un proxy del lado
del cliente que implementa el conjunto completo de interfaces remotas
que el objeto remoto implementa.

Los objetos locales son pasados por copia, utilizando la serializacin


de objetos. Por defecto, todos los campos se copian, excepto los que
estn marcados esttico o transitorio. El comportamiento por defecto
de serializacin se puede reemplazar en una base de clase por clase.
Al pasar un objeto por referencia (como se hace con los objetos
remotos)
significa que los cambios realizados en el estado del objeto de las
llamadas a mtodos remotos se reflejan en el objeto remoto original.
Cuando se pasa un objeto remoto, slo aquellas interfaces que son
interfaces remotos estn disponibles para el receptor; cualquier
mtodo
definido en la clase de implementacin o definido en no remoto
interfaces implementadas por la clase no estn disponibles para ese
receptor.
Haga una interfaz remota
Esta interfaz debe extenderse java.rmi.Remote. Cada funcin dentro de
ella debe lanzar java.rmi.RemoteException. Las funciones juntas debe
capturar el comportamiento del servicio que desea realizar.
public interface RemoteInterface extends java.rmi.Remote
{
public java.util.Date askTime() throws java.rmi.RemoteException;
public
void tellTime(java.util.Date d)
throws
java.rmi.RemoteException;
}
Make a Remote Object
This object should extend java.rmi.server.UnicastRemoteObject and
implement the interface you created above. Hopefully the functions
you make here do the service you are trying to create.
public
class RemoteObject
extends
java.rmi.server.UnicastRemoteObject
implements RemoteInterface{
public RemoteObject() throws java.rmi.RemoteException{
// Empty constructor
}
public
java.util.Date
askTime()
throws
java.rmi.RemoteException{ System.out.println("RemoteObject.askTime
called"
+
new

java.util.Date() + "\n");
return new java.util.Date();
}
public
void tellTime(java.util.Date d)
throws
java.rmi.RemoteException{
System.out.println("RemoteObject.tellTime called" + d + "\n");
}
}
Make a Server
The server should have a 'main' that ... Installs a new security manager
Possibly starts an rmiregistry (if it's not already running)
Creates an object of type equal to the interface of the remote object
you just made.
Binds the object to a name on the registry public class Server{
public static void main(String[] args){
try{
System.setSecurityManager(new
java.rmi.RMISecurityManager());
RemoteInterface v=new RemoteObject();
java.rmi.registry.LocateRegistry.createRegistry(5099);
java.rmi.Naming.rebind("//:5099/count", v);
}catch(java.rmi.UnknownHostException x){x.printStackTrace();}
catch(java.rmi.RemoteException x){x.printStackTrace();}
catch(java.net.MalformedURLException x){x.printStackTrace();}
catch(Exception x){x.printStackTrace();}
}
}

Make a Client
The client should
Call lookup to get an object of type remoteobject_stub.
access the remote object

Use that to

public class Client{


public static void main(String[] args){ RemoteInterface s=null;
try{
s=(RemoteInterface)java.rmi.Naming.lookup("rmi://euclid.nmu.edu:509

9/count");
s.tellTime(new java.util.Date()); System.out.println(s.askTime());
}catch (Exception x){x.printStackTrace();}
}
}
Las ventajas de usar RMI en Applets
En teora, la eleccin de RMI como medio de comunicacin entre los
applets de Java y aplicaciones de servidor en el Internet es una gran
idea. Los beneficios del uso de RMI en dicha aplicacin son
convincentes, por las siguientes razones:
RMI es parte del ncleo de Java 1,1 especificacin, as como Java 2
Standard Edition. Esto significa que el applet RMI ser apoyado por
todos los JDK 1.1 y el cliente 1.2-compatible, as que usted no tiene
que preocuparse sobre cmo crear sus propias clases de comunicacin
y empaquetarlos con su applet. Incluido en el estndar Java 1,1 y 1,2
paquetes de tiempo de ejecucin (JRE y JDK) es una versin ejecutable
del registro RMI, el servidor responsable de proporcionar el acceso a
objetos RMI. Esto le permite desplegar basado en RMI
aplicaciones de servidor sin necesidad de un servidor de aplicaciones
caro o aadir otra en el lado del servidor.
Aunque RMI tpicamente hace una conexin directa entre el applet y el
servidor, sino que tambin su operacin a travs de un tnel HTTP si
fuera necesario. Esto permite a los usuarios que se conectan a Internet
a travs de un proxy HTTP
servidor para utilizar applets RMI.
RMI permite que el cdigo del applet para ejecutar las operaciones del
lado del servidor con sintaxis simple llamada a la funcin, as que es
increblemente fcil de escribir el cdigo para como una aplicacin
distribuida.
Las limitaciones de Applets RMI en Internet
Aunque el uso de RMI en Internet basados en applets parece una
buena idea, en la prctica, la inestabilidad de las conexiones a Internet
y la falta de apoyo de cliente que sea poco prctico. Entre los
obstculos para el despliegue de applets RMI en Internet son los
siguientes:
A pesar de apoyar la mayora de la Java 1.1, los navegadores web ms
populares - Netscape Navigator y Microsoft Internet Explorer - no
apoyan adecuadamente RMI. Navigator soporta RMI en la mayora de

plataformas, pero no admite HTTP tunneling, para que los usuarios de


Netscape conectados a la web a travs de un servidor proxy no puede
utilizar un applet RMI. Mientras tanto, Netscape para Macintosh no es
compatible con RMI en absoluto. Internet Explorer 4.0-5.0 tambin
carece de soporte RMI, aunque se supone que es un parche disponible
para aadir las clases que faltan (las clases RMI a travs del sitio web
de Microsoft, pero las instrucciones para su instalacin no est
incluida). Como resultado de ello, un gran porcentaje de los internautas
no pueden utilizar applets RMI en su navegador actual.
El registro de RMI pueden experimentar problemas al manejar las
conexiones a travs de Internet. Un error que hace que el registro de
dejar de aceptar nuevas conexiones se produce con demasiada
frecuencia con los clientes web RMI, lo que requiere que el registro se
apaga y se reinicia. Adems, en entornos de ejecucin Java JDK
anteriores a 1.2.2, el servidor de sockets creados para manejar las
conexiones de clientes basados en Internet RMI pueden vivir
indefinidamente (consumiendo recursos del servidor) incluso despus
de que los clientes se apagan.
El registro RMI no es tan flexible como la mayora de aplicaciones de
servidor, respondiendo slo a las conexiones de clientes realizadas a
un nombre de host especfico. Esto significa que la aplicacin de
servidor RMI no puede admitir varios dominios en un nico servidor
web, lo que limita sus opciones de implementacin. Muchas
aplicaciones pueden requerir que los datos intercambiados entre el
cliente y el servidor de ser encriptado, comprimido, o manipulados de
alguna otra manera. Hacer esto con RMI es bastante simple, slo
requiere que implemente sus propias clases socket y una fbrica de
socket RMI que crea sus tomas especiales. Sin embargo, haciendo caso
omiso de la fbrica toma por defecto RMI desactiva la capacidad de
hacer HTTP tnel de acceso, lo que impide a los usuarios del servidor
proxy.
Implementar una aplicacin de servidor RMI requiere una configuracin
adicional cortafuegos de red. De forma predeterminada, los objetos
RMI estn obligados a azar, "annimos" nmeros puerto del servidor,
por lo que es imposible predecir los puertos que deben estar a
disposicin de los clientes de Internet. Funcionalidad RMI nuevo a Java
2 permite especificar un nmero de puerto cuando se crea un objeto
remoto, pero la implementacin todava requiere que los cortafuegos
permiten el acceso a los puertos no utilizados normalmente por
aplicaciones basadas en web.
Ejemplo de aplicacin

En este artculo usted estar trabajando con una aplicacin de


ejemplo: un simple basada en web de cliente de base de datos. La
aplicacin consta de un applet de Java que muestra los valores de base
de datos y un objeto del lado del servidor Java que realiza tareas de
base de datos (aadir, quitar, modificar y recuperar datos) en nombre
del applet. La comunicacin entre el applet y el objeto de servidor es a
travs de RMI.
El grfico siguiente muestra la arquitectura original de la solicitud:

El lado del servidor de esta ilustracin es una aplicacin Java que hace
tres cosas: crea un registro RMI, crea una instancia de la base de datos
de acceso a objetos (UserDatabaseImpl), y enlaza el objeto en el
registro para que est disponible para los clientes remotos. Estas son
las lneas de cdigo de la aplicacin de servidor que realizan estas
tareas:
// Create the registry on port 1099
Registry reg =
java.rmi.registry.LocateRegistry.createRegistry(
1099);
// Create the database object
UserDatabaseImpl db = new UserDatabaseImpl();
//
Bind
the
object
to
the
registry
as
"DB1"
java.rmi.Naming.rebind("DB1", db);
Una vez que el objeto de base de datos est obligado al registro, el
applet cliente puede utilizar java.rmi.Naming.lookup () para obtener
una referencia a la misma. Aqu est el cdigo de cliente:
UserDatabase db; //The remote database object
...
String host = this.getCodeBase().getHost(); String name = "//" + host
+ "/DB1";
db = (UserDatabase)java.rmi.Naming.lookup(name);

Una vez que el applet tiene una referencia al objeto remoto, puede
ejecutar operaciones de bases de datos mediante la invocacin de
mtodos en este objeto. Al igual que con otros objetos RMI, el objeto
de base de datos (UserDatabaseImpl) implementa una interfaz remota
(UserDatabase) que se extiende java.rmi.Remote. Esta interface
remoto define los mtodos del objeto de base de datos que pueden ser
ejecutados por el applet del cliente, y se parece a esto:

public interface UserDatabase


extends java.rmi.Remote
{
public String createUser(
UserData data) throws RemoteException;
public void editUser(
String userid, UserData data)
throws RemoteException;
public void deleteUser(
String userid) throws RemoteException;
public UserData getUser(
String userid) throws RemoteException;
public Hashtable listUsers(
) throws RemoteException;
}
Para ejecutar una operacin de base de datos del applet cliente
simplemente llama a uno de estos mtodos en el objeto remoto. Por
ejemplo, para obtener una lista de los usuarios actualmente en la base
de datos, el applet cliente ejecuta:
Usuarios Hashtable = db.listUsers ();

Resumen de los cambios


Aunque los fragmentos de cdigo anteriores demuestran la facilidad
con que RMI permite crear applets que tienen acceso a su base de
datos y realizar otras tareas en el servidor, usted todava desea
eliminarlo de la parte cliente de la aplicacin debido a los problemas

descritos anteriormente. Al hacer esto, usted tiene los siguientes


objetivos:
Haga todas las transacciones basadas en objetos. En otras palabras,
para cumplir una tarea que desea enviar objetos completos al servidor
y recibir uno o ms objetos a cambio. RMI permite hacer esto
fcilmente a travs de las llamadas a funciones, y en los cambios que
desea mantener este intercambio orientado a objetos.
Usar HTTP para todas las comunicaciones del applet / servidor.
Mediante el uso de slo HTTP, puede hacer que el applet lo ms
compatible posible con los servidores proxy y firewalls de red.
Haga los cambios cero a la aplicacin de servidor RMI. En lugar de
volver a escribir el cdigo de servidor slo quiere agregar una capa de
servlet para facilitar la comunicacin applet, por lo que no debera
tener que tocar los objetos de servidor que ya ha implementado.
Escriba un mnimo de cdigo nuevo. Una vez ms, no quiero hacer
ninguna ms trabajo de lo que sea necesario.
Para lograr estos objetivos va a aadir una serie de servlets de Java del
lado del servidor que ejecutar las transacciones RMI en nombre del
applet cliente. Para comunicarse con los servlets a travs de HTTP,
vamos a crear un objeto proxy en el cliente cuyos mtodos sern
similares a los mtodos del objeto servidor RMI. Cuando el applet se
ejecuta actualmente mtodos directamente en el objeto RMI, en su
lugar va a ejecutar mtodos en el objeto proxy, preservando toda la
sintaxis de la funcin en el cdigo del applet.
Una vez realizados los cambios en la arquitectura de la aplicacin se
ver as:

Los Servlets

La capa de servlet de su nueva arquitectura contendr una serie de


servlets que cada uno ejecuta un mtodo nico en el objeto remoto.
Aqu estn los servlets se le hacen y la forma de UserDatabase estn
asociados con:

Debido a que los servlets se ejecutan cada una nica llamada RMI, van
a ser muy simple. Cada servlet llevar a cabo las mismas tareas
bsicas:
1.Preprese una referencia al objeto de la base de datos del registro
RMI.
2.Read en valores de los parmetros del cliente.
3.Execute el mtodo apropiado en el objeto de base de datos.
4.Write el valor de retorno para el applet.

El primero de estos pasos-que consigue el objeto de base de datos


desde el registroser comn para todos los servlets, por lo que tendr que definir de
una vez en un servlet super-clase y que todos sus especficas mtodo
servlets extenderla. en
definicin de este servlet padre desea proporcionar flexibilidad al hacer
que el
ubicacin del registro RMI configurable a travs de un parmetro de
inicializacin. Esto le permite localizar el registro en un sistema distinto
del web
servidor (posiblemente uno detrs de un firewall), que no se poda
hacer cuando el
subprograma se requiere acceso al registro. Una vez que tenga el lugar
del registro se puede obtener el objeto de base de datos a travs de
java.rmi.Naming.lookup () al igual que el cdigo del applet original
hace.
He aqu, pues es el cdigo para DatabaseServlet, el servlet superclase:
public class DatabaseServlet extends HttpServlet
{

String registry; // The path to the RMI


//registry
UserDatabase db; // The database access
//object
public void init( ServletConfig config)
throws ServletException
{
super.init(config);
// Get the location of
//the RMI registry.
registry = config.getInitParameter( "registry");
// If undefined, assume the local host
if (registry == null) registry = "//localhost";
try {
// Now get the database object
String name = registry + "/DB1";
db = (UserDatabase)Naming.lookup(
name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Ahora que tiene su padre servlet puede crear los servlets individuales
que se extienden a ste. De este modo, podrs seguir la receta
anterior: lectura de los valores de los parmetros, ejecutar el mtodo
de base de datos y devuelve el resultado. Todas estas operaciones se
producir en el mtodo del servlet doPost (), que tambin incluir el
cdigo necesario para abrir y cerrar los flujos de E / S en el applet.
Esta es su primera servlet, UserCreateServlet, que ejecuta el mtodo
createUser () base de datos en nombre del applet:
public class UserCreateServlet extends DatabaseServlet
{
public void doPost( HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException
{
//
Open
the
I/O
streams
ObjectInputStream
in
ObjectInputStream(
req.getInputStream() ); ObjectOutputStream out =

new

new ObjectOutputStream(
resp.getOutputStream() );
try {
// 1. Read in parameters from
//the applet
UserData data = ( UserData)in.readObject();
// 2. Execute the RMI call
String id = db.createUser(data);
// 3. Write the result out.writeObject(id);
} catch (
Exception e) { e.printStackTrace(
); }
// Close the I/O streams
in.close();
out.close();
}
}
Un par de notas sobre este cdigo:
Usted est utilizando ObjectInputStream y ObjectOutputStream aqu
porque quiere mantener a objetos basados en las transacciones entre
el applet y el servidor. En este servlet podra haber devuelto el valor de
la cadena de resultado en lugar del objeto String entero, pero la
pervivencia de un objeto / objetos en el planteamiento de hace su vida
mucho ms simple.
Aunque usted no declar ni inicializar el objeto de base de datos (db)
en el cdigo para UserCreateServlet, no hace falta. Una vez ms, este
servlet
extiende DatabaseServlet, el servlet padre ha definido anteriormente,
por lo que
obtiene una referencia al objeto base de datos del registro RMI cuando
el servlet se inicializa.
En la definicin de los servlets que usted puede simplemente copiar y
pegar el contenido de UserCreateServlet. El nico cdigo que tiene que
cambiar en cada servlet (adems del nombre de la clase, por

supuesto) son las tres lneas de cdigo en el bloque try / catch-esas


son las nicas lneas especficas de mtodo. As que para crear nuestro
servlet UserGetServlet, que ejecuta el mtodo de base de datos
getUser (), slo tiene que cambiar estas lneas a ser:
// 1. Read in parameters from
//the applet
String id = (String)in.readObject();
// 2. Execute the RMI call
UserData data = db.getUser(id);
// 3. Write the result out.writeObject(data);
En estos dos servlets que he ledo en un objeto y un objeto escrito,
pero se puede leer o escribir tantos objetos como quieras. En el caso
del mtodo de la base de datos editUser (), debe recuperar dos
parmetros del applet cuando regresaba ninguno. En el applet que se
ejecuta este mtodo (UserEditServlet) que comience con la misma
plantilla de tres lneas y slo tiene que aadir un extra de readObject ()
para obtener la lnea segundo parmetro, y retire la writeObject () la
lnea que escribe la Valor de retorno:
// 1. Read in parameters from
//the applet
String
id
=
(String)in.readObject();
( UserData)in.readObject();

UserData

data

// 2. Execute the RMI call db.editUser(id, data);


// 3. Write the result
// [no return value]
Sus otros servlets todos siguen el mismo formato, por lo que no se
imprimir a todos aqu Descargar el cdigo
Client objeto proxy
Ahora que tiene servlets que pueden ejecutar sus mtodos RMI a
travs de HTTP, el applet cliente necesita saber cmo utilizar estos
servlets. Aunque se puede reescribir cada llamada al mtodo RMI en el
applet para incluir las llamadas servlet correspondiente, que puede ser

un montn de cambios en el cdigo existente. Es por eso que vamos a


usar un objeto proxy que sintaxis duplica el objeto de base de datos y
hace todo de la comunicacin servlet necesario, lo que le permite
mantener casi la totalidad de su actual cdigo del applet en el tacto.
En la creacin de su objeto proxy, UserDatabaseProxy, se inicia con la
interfaz UserDatabase que define los mtodos remotos disponibles. Los
mtodos de su objeto proxy debe ser idntica a la interfaz, que define
estos mtodos:
String createUser(UserData data)
void editUser(
String userid, UserData data)
void deleteUser(String userid)
UserData getUser(String userid)
Hashtable listUsers()
Al igual que hizo al crear los servlets, podrs seguir una receta sencilla
para definir cada uno de estos mtodos en el objeto proxy. En cada uno
de estos mtodos que quiere lograr lo siguiente: Abra una conexin
con el servlet de destino, escriba uno o ms parmetros al servlet, y
leer el resultado de la ejecucin de servlets y devolverlo a la applet.
Para ayudar a lograr esto usted va a utilizar una clase auxiliar llamada
ServletWriter. Esta clase gestiona los flujos de E / S entre el applet y
servlet y ejecuta la actual transaccin HTTP POST. Al igual que los
servlets, ServletWriter utiliza ObjectInputStream y ObjectOutputStream
pasar objetos enteros entre el cliente y el servidor. El mtodo nico
definido por ServletWriter es:
PostObjects ObjectInputStream servlet (URL, Serializable objs []) donde
servlet define la URL del servlet de destino y objs define una lista de
objetos serializables que se escriben en el servlet. El mtodo devuelve
el ObjectInputStream de que sus mtodos pueden recuperar los
valores devueltos por el servlet. Ver cdigo ServletWriter.java para ms
detalles. Con ServletWriter a su disposicin, esto es lo que cada uno de
sus mtodos de objeto de proxy har:
1.Cree una URL para el servlet de destino.
2.Crear una matriz de objetos serializable que contiene los parmetros
del mtodo.
3.Call ServletWriter.postObjects () para ejecutar la operacin de
servlet.
4.Read y devolver el valor del resultado.
Paso 1 aqu requiere que conozca la URL base para el servidor web
servlet. Dado que este valor ser el mismo para cada mtodo, lo vas a
definir de una vez por colocarlo en el constructor del objeto de proxy:

URL webBase;// The URL to


UserDatabaseProxy(URL web)
{
webBase = web;
}

the

servlet

web

server

public

Debido a que la direccin URL del servidor web servlet se inicializa


durante la construccin, cada uno de sus mtodos pueden crear la
direccin URL de servlets sus correspondientes relativos a esta URL
base.
Con eso fuera del camino, ahora se puede escribir cada uno de los
mtodos del objeto proxy. Vamos a empezar con createUser (), que los
datos puestos a UserCreateServlet:
public String createUser( UserData data) throws Exception
{
// 1. Create a URL for the target
//servlet
URL servlet = new URL(
webBase, "servlet/UserCreateServlet");
// 2. Create an array of parameter
//objects
Serializable objs[] = { data };
// 3. Execute the servlet
//transaction
ObjectInputStream in = ServletWriter.postObjects( servlet, objs);
// 4. Read and return the
(String)in.readObject(); in.close();
return id;
}

result

value

String

id

Al igual que con los servlets, la creacin de otros mtodos en el objeto


proxy requiere principalmente de copiar y pegar este primer mtodo.
Aqu est el cdigo para el mtodo getUser (), que difiere del mtodo
anterior slo en el nombre del servlet objetivo (UserGetServlet) y el
tipo del objeto de retorno:
public UserData getUser(

String userid) throws Exception


{
// 1. Create a URL for the target servlet
URL servlet = new URL(webBase, "servlet/UserGetServlet");
// 2. Create an array of parameter objects
Serializable objs[] = { userid };
// 3. Execute the servlet transaction
ObjectInputStream in = ServletWriter.postObjects(
servlet, objs);
// 4. Read and return the result
(UserData)in.readObject(); in.close();
return data;
}

value

UserData

data

Los otros mtodos de su objeto proxy est construido de manera


similar,
por
lo
que
no
mencionarlos
a
todos
aqu.
UserDatabaseProxy.java

Cambios Applet
Una vez que tenga su objeto proxy y servlets en su lugar, todo lo que
necesita hacer es actualizar el applet con el uso del objeto de proxy en
lugar del objeto original RMI. Aqu de nuevo es el cdigo original para
acceder a la base de datos:
UserDatabase db; //The remote database object
...
String host = this.getCodeBase().getHost(); String name = "//" + host
+ "/DB1";
db = (UserDatabase)Naming.lookup(name);
el objeto RMI, es necesario crear la direccin URL del servidor web
servlet (requerido por el constructor de UserDatabaseProxy). Para ello
se construye una URL desde el protocolo, el nombre de host y nmero
de puerto de la base de cdigo del applet:
UserDatabaseProxy db; // The proxy
//database object

URL codebase = this.getCodeBase();


// Get the host, protocol, and port
String host = codebase.getHost();
String protocol = codebase.getProtocol();
int port = codebase.getPort();
// Build the URL for the servlet
//web server
URL servletBase = new URL(
protocol + "://" + host + ":" + port);
// Create the proxy object
db = new UserDatabaseProxy(servletBase);
Con el cdigo original de RMI ha sustituido con este cdigo proxy
nuevo objeto, que est bsicamente hecho con el applet cambios-sin
otras modificaciones son necesarias, ya que la sintaxis de llamada de
funcin en el objeto proxy db es la misma que para el objeto db RMI .
Hiciste trampa aqu un poco a quitar importancia a manejo de
excepciones, ya que su mtodo remoto llama tirar RemoteException
mientras que sus mtodos de objeto proxy puede lanzar una serie de
excepciones (MalformedURLException, ClassCastException, etc), pero
se entiende la idea.
Eso es todo-usted hace. El applet de cliente ahora puede utilizar HTTP
en lugar de RMI para comunicarse con el objeto de acceso a base de
datos en el lado del servidor, y usted ni siquiera tiene que cambiar una
sola lnea de cdigo de servidor existente (y slo una media docena de
lneas en el applet) . Con apenas estos pocos cambios que ha hecho el
applet ms compatible, su servidor ms flexible, y su comunicacin
mucho ms confiable y amigable de Internet.

Ms all de lo bsico
Al modificar la aplicacin de ejemplo anterior se dise el servlets para
imitar lo que su objeto no RMI, es decir, toman un cierto nmero de
parmetros y devolver un solo objeto de un tipo especfico (o ninguno).
Pero a diferencia de las llamadas a mtodos RMI, los servlets pueden
ser muy flexibles en la manera en que manejan y devolver datos. Los
siguientes ejemplos ilustran algunas de las opciones disponibles para
las aplicaciones applet / servlet / RMI.

Recepcin de varios objetos de una llamada


En los cambios anteriores que ha creado un servlet que, al igual que su
objeto RMI, responde a una solicitud de devolucin de un applet
Hashtable que puede contener un gran nmero de objetos. Esto
funciona, pero al igual que con el original RMI
llamada al mtodo, el cliente se quedar esperando el Hashtable
acaba de ser devuelto. Esto evita que el applet muestre una barra de
progreso o parar la operacin despus de slo un subconjunto de
valores se han recuperado, caractersticas muy deseables si un gran
nmero de entradas estn involucrados. (Por supuesto, usted puede
obtener una lista de los objetos de uno en uno-a-tiempo, haciendo un
llamado servidor separado para cada uno, pero si lo hace en miles de
objetos es poco prctico.)
En lugar de esperar a que nuestro servlet para devolver un Hashtable,
puede enviar las claves y valores de Hashtable que como objetos
individuales. Para ver cmo, aqu est la doPost () original mtodo de
UserListServlet, que recupera la lista de usuarios de la base de la
aplicacin de ejemplo:
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
ObjectInputStream
in
=
new
ObjectInputStream( req.getInputStream() ); ObjectOutputStream out =
new ObjectOutputStream( resp.getOutputStream() ); try {
Hashtable database =
db.listUsers();
out.writeObject(database);
} catch (
Exception e) { e.printStackTrace(
); }
// Close the I/O streams in.close();
out.close();
}
Aqu hay otra versin del servlet anterior, pero ste informa al cliente
el nmero de entradas que hay en el valor de retorno, y luego enva el
Hashtable una clave y un valor a la vez:
public void doPost( HttpServletRequest req,

HttpServletResponse resp)
throws ServletException, IOException
{
ObjectInputStream in =
new ObjectInputStream(
req.getInputStream() );
ObjectOutputStream out =
new ObjectOutputStream(
resp.getOutputStream(
) );
try {
Hashtable database =
db.listUsers();
// Tell the client how many
//entries are coming
int num = database.size(); Integer numInt = new Integer(
num);
out.writeObject(numInt);
// Write each key and
//value of
//the Hashtable
Enumeration keys =
database.keys(); while ( keys.hasMoreElements(
))
{
String nextKey = keys.nextElement(); UserData nextData
( UserData)database.get(
nextKey); out.writeObject(nextKey); out.writeObject(nextData);
}
} catch (
Exception e) { e.printStackTrace(
); }
// Close the I/O streams in.close();
out.close();
}

En esta nueva versin del servlet va a enviar los datos Hashtable


exactamente igual que la versin anterior, pero ahora ests dejando
que el cliente sepa qu cantidad de datos que viene antes de empezar
a enviarlo. Esto le da al cliente mucha ms flexibilidad en el
tratamiento de estos datos.

Obviamente, si usted cambia de servlet como este tiene que cambiar


su objeto proxy para hacer frente a estos valores de retorno. Aqu est
el cdigo original del objeto proxy de la aplicacin de ejemplo:
public Hashtable listUsers(
) throws Exception
{
servlet = new URL(webBase, "servlet/UserListServlet"); Serializable
objs[] = {};
in = ServletWriter.postObjects(
servlet, objs); Hashtable database = (
Hashtable)in.readObject();
in.close();
return database;
}
Aqu hay otra versin de la misma funcin que recupera datos desde el
servlet nuevo, y tambin muestra sus avances en la interfaz de usuario
del applet:
public Hashtable listUsers(
java.awt.Label label) throws Exception
{
servlet = new URL(
webBase, "servlet/UserListServlet"); Serializable
ObjectInputStream in = ServletWriter.postObjects(
servlet, objs);
// Initialize the return value
Hashtable database = new Hashtable(
);
// Get the number of data
//values coming
Integer numInt = ( Integer)in.readObject();
int num = numInt.intValue();
// Read each key/value pair and
//add to the Hashtable
for (int x = 1; x <= num; x++)
{
label.setText(

objs[]

{};

"Getting data (
" + x + "/" + num + ")..."); String nextKey = (
String)in.readObject();
UserData nextData = ( UserData) in.readObject();
database.put(
nextKey, nextData);
}
in.close();
return database;
}
Cuando el applet se ejecuta esta versin de Listusers (), el nombre
dado muestra el nmero total de entradas y el nmero actual se leer
(por ejemplo, "Obtencin de datos (7/26) ...").
La combinacin de Servlets
Otro de los cambios que puede realizar en la aplicacin de ejemplo es
el de consolidar todas sus servlets en un servlet individual, con todos
los mtodos RMI llama contenido en un solo doPost () mtodo. Esto
complica el servlet, ya que se necesita para cambiar entre varios
bloques de cdigo basado en la operacin a realizar, sino que
simplifica la implementacin, eliminando la necesidad de mltiples
servlets.
He aqu un servlet que implementa toda la base de datos del mtodo
que llama a sus cinco servlets, utilizando un cdigo entero enviado por
el applet para determinar la accin apropiada:
public class UniversalServlet extends DatabaseServlet
{
static final int LIST
= 0; static final int GET = 1; static final int
CREATE = 2; static final int EDIT
= 3; static final int DELETE = 4;
public void doPost( HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException
{
// Open the I/O streams
ObjectInputStream in =
new ObjectInputStream(
req.getInputStream()
);
ObjectOutputStream
ObjectOutputStream( resp.getOutputStream(

out

new

) );
try {
// Find out which operation to perform
Integer codeInt = ( Integer)in.readObject();
int code =
codeInt.intValue();
if (code == LIST) { Hashtable database = db.listUsers();
out.writeObject(database);
}
else if (code == GET) { String id = ( String)in.readObject(); UserData
data = db.getUser(id); out.writeObject(data);
}
else if (
code == CREATE) { UserData data = (
UserData)in.readObject();
String id =
db.createUser( data); out.writeObject(id);
}
else if (code == EDIT) { String id = (
String)in.readObject();
UserData data = ( UserData)in.readObject(); db.editUser(id, data);
}
else if (code == DELETE) { String id = (
String)in.readObject();
db.deleteUser(id);
}
} catch (
Exception e) { e.printStackTrace(
); }
// Close the I/O streams in.close();
out.close();
}
}
Observe que en este nuevo cdigo servlet que los parmetros para
cada operacin son de slo lectura despus de que el cdigo se lee
entero y determinar qu bloque de cdigo a ejecutar. A diferencia de
los servlets anteriores, no se puede leer todos los parmetros de la
corriente de entrada al comienzo de este doPost (), ya que no se
conoce el nmero y tipo de parmetros a leer hasta despus de saber
qu operacin se debe ejecutar. Para utilizar este servlet es necesario
cambiar todos los mtodos de su objeto proxy en consecuencia,

utilizando un cdigo entero para especificar la operacin a realizar. Por


ejemplo, he aqu una versin de createUser el objeto de proxy () del
mtodo que utiliza el UniversalServlet arriba:
public String createUser( UserData data) throws Exception
{
URL servlet = new URL(
webBase, "servlet/UniversalServlet");
Integer code =
new Integer(2); //CREATE Serializable objs[] =
{ code, data };
ObjectInputStream in = ServletWriter.postObjects(
servlet, objs);
String id = ( String)in.readObject(); in.close();
return id;
}
La nica modificacin que hemos hecho aqu es crear un entero que
corresponde a la operacin realizada (en este caso, la creacin de una
entrada de base de datos) y aadir este entero a la matriz de
parmetros enviados
al servlet.
Manejo de varios tipos de objetos
Tambin se puede construir el applet para dar cabida a diferentes tipos
de objetos en respuesta a la llamada de servlet mismo. Por ejemplo, si
al recuperar informacin de su base de datos se encuentra con un
servlet RemoteException, es posible que su applet para recibir la
excepcin. Para ello, puede escribir el objeto RemoteException a
ObjectOutputStream del servlet en lugar del valor de retorno que
estabas esperando. Aunque esto podra causar una ClassCastException
que se produzca en el objeto proxy cuando intent leer el valor de
retorno, puede utilizar instanceof para determinar si la salida del
servlet el valor de retorno o una excepcin, como en este ejemplo:

public UserData getUser(


String userid) throws Exception
{
URL servlet = new URL(webBase, "servlet/UserGetServlet");

Serializable objs[] = { userid };


objectInputStream in = ServletWriter.postObjects( servlet, objs);
// Read the value as an Object
Object obj = in.readObject();
// Is it an Exception?
if (obj instanceof Exception) {
throw (Exception)obj;
}
else {
UserData data = ( UserData)obj; in.close();
return data;
}
}
Aqu usted est leyendo en el valor de retorno desde el servlet como
tipo Object
y luego utilizar instanceof para determinar si se trata de una
excepcin. Si es as, lo lanzas como una excepcin y echarlo a permitir
que el acuerdo applet con l como
necesario, de lo contrario, se asume el valor devuelto es un objeto
UserData,
proyectarlo como tal, y devolverlo a la applet.
conclusin
Como se puede ver, las opciones para trabajar con applet / servlet
comunicacin son mucho mayores que cuando se utiliza RMI en el
applet, los ejemplos que se muestran aqu son slo un comienzo. Al
insertar otra capa en su solicitud puede tardar un poco ms trabajo, la
recompensa es un applet que es ms compatible, comunicacin cliente
/ servidor que es ms flexible, y una aplicacin de servidor RMI que es
ms fiable.

También podría gustarte