Professional Documents
Culture Documents
Java TM
ndice de Contenidos
Concordar los Requerimientos del Proyecto con la Tecnologa
Requerimientos del Proyecto
Elegir el Software
La Aplicacin Casa de Subastas
Una Aplicacin Multi-Fila con JavaBeans
Beans de Entidad y Sesin
Examinar un Bean de Manejo de Contenedor
Mtodos de Bsqueda de Manejo de Contenedor
Manejo de Datos y Transaciones
Persistencia del Bean
Manejar Transaciones
Mtodos de Bsqueda de Manejo del Bean
Clculo Distribuido
Servicios de Bsqueda
RMI
CORBA
Tecnologa JDBC
Servelts
Tecnologa JNI
Ejemplos JNI
Strings y Arrays
Otros Problemas de Programacin
Proyecto Swing: Construir un Interface de Usuario
Componentes y Modelos de Datos
El API de Impresin
Impresin Avanzada
Depuracin de Applets, Aplicaciones y Servlets
Recoleccin de Evidencias
Ejecutar Tests y Analizar
Depurar Servlets
Depurar Eventos AWT
Analizar la Pila
Problemas de Versiones
Tcnicas de Rendimiento
Aumentar el Rendimiento por Diseo
Trucos de Conexin
Caractersticas de Rendimiento y Herramientas
Anlisis de Rendimiento
Enlazar Aplicaciones Cliente/Servidor
Desarrollar la Aplicacin Subasta
Archivos JAR
Plataforma Solaris
Plataforma Win32
Ms Tpicos de Seguridad
Appelts Firmados
Escribir un Controlador de Seguridad
Apndice A: Seguridad y Permisos
Apndice B: Clases, Mtodos y Permisos
Apndice C: Mtodos de SecurityManager
Eplogo
Oz it o
Concordar los Requerimientos del Proyecto con la
Tecnologa
El desafo de escribir un libro sobre el desarrollo de una aplicacin avanzada para la
plataforma JavaTM es encontrar un proyecto lo suficientemente pequeo, pero al
mismo tiempo, los suficientemente completo para garantizar las tecnicas de
programacin avanzadas.
El proyecto presentado en este libro es una casa de subastas basada en web. La
aplicacin est inicialmente escrita para la plataforma Enterprise JavaBeansTM. En
los captulos posteriores expandieremos el corazn del ejemplo descrito aqu
aadiendo funcionalidades avanzadas, mejoras y soluciones alternativas a algunas
de las cosas que obtendrs gratis cuando use la plataforma Enterprise JavaBeans.
Para mantener la explicacin sencilla, la aplicacin de ejemplo slo tiene un
conjunto bsico de transaciones para poner y pujar tems a subasta. Sin embargo,
la aplicacin escala para manejar mltiples usuarios, proporciona un entorno de
tres filas basado en transaciones, controla la seguirad, e integra sistemas basados
en la legalidad. Este captulo cubre cmo determinar los requerimientos del
proyecto y el modelo de aplicacin -- pasos importantes que siempre deberan
realizarse antes de empezar a codificar.
Requerimientos de Proyecto y Modelado
Elegir el Software
Tienes Prisa?
Esta tabla te enlaza directamente con los tpicos especficos.
Tpico Seccin
Demostracin de Subasta La Subasta de Duke
Requerimientos del Proyecto Entrevista Base
Modelar el Proyecto
Modelado La Casa Identifica Compradores y Vendedores
La Casa Determina la Mayor Puja
La Casa Notifica a Compradores y Vendedores
Alguien Busca un tem
Alguien Ve un tem en Venta
Alguien Ve los Detalles de un tem
El Vendedor Pone un tem en Venta
El Compador Puja por tems
Diagrama de Actividad
Elegir el Software Los APIs de JavaTM
Oz it o
Requerimientos del Proyecto y Modelado
El primer paso para determinar los requerimientos del proyecto es la entrevista con el usuario base para saber que se espera de una subasta on-line. Este es un paso importante, y
no puede pasarse por alto porque es una base slida de informacin que nos ayudar a definir las capacidades clave de nuestra aplicacion.
El captulo 2 pasea a travs del cdigo de la aplicacin, explica como trabaja la plataforma Enterprise JavaBeans, y nos cuenta cmo ejecutar una demostracin en vivo. Si nunca
has visto o usado una subasta on-line, aqu hay una maqueta de las pginas HTML de la aplicacin de ejemplo.
Entrevista al usuario Base
Modelo de Proyecto
Re q u e rim ie n t o s d e l u s u a rio
Pujar por o Vender un tem
Modelo de Proyecto
Despus de analizar los requerimientos, podemos construir un diagrama de flujo de la aplicacin para obtener un mejor entendimiento de los elementos necesarios en la aplicacin
y cmo interactua.
Un diagrama de flujo muestra la relacin entre los actores y procesos dentro del sistema. Un proceso es una funcin nica en un sistema, y un actor es la persona o software que
realiza la accin o proceso. Por ejemplo, un comprador es el actor que realiza la funcin (proceso) de pujar por un tem de la subasta, y el vendedor es el actor que realiza el
proceso de postear un tem para su subasta.
Aunque, no todos los actores son personas. Por ejemplo, el software es el actor que determina cuando un tem se ha cerrado, encuentra la puja ms alta, y notifica la venta al
comprador y al vendedor.
El Unified Modeling Language (UML) es la herramienta que se usa para los diagramas de procesos. El siguiente diagrama usa UML para describir los procesos del comprador y del
vendedor para una aplicacin de subasta on-line.
En UML, los sistemas se agrupan en cuadrados, los actores se representas por figuras humanas, los procesos se denotan mediante valos, y las lneas muestran como los actores
usan el sistema.
La siguiente descripcin define el proyecto. Estas descripciones no son parte del UML, pero son una herramienta til para la definicin de proyectos.
Una aplicacin de subastas es usada por compradores y vendedores. Un comprador necesita saber quen es el vendedor a quien tiene que pagarle, y el vendedor necesita conocer a
los compradores para responder a sus preguntas sobre el producto y para finalizar la venta. Por eso, para postear o pujar por un tem de la subasta, los compradores y vendedores
necesitan estar registrados. El registro necesita obtener la siguiente informacin sobre los compradores y vendedores:
User ID y password para comprar y vender.
Direccin de E-mail para que pueda comunicarsele la puja ms alta cuando se cierre la subasta.
Informacin de la tarjeta de crdito para que la casa de subastas pueda cobrar al vendedor por listar sus tems.
Una vez registrado, el usuario puede postear o pujar por un tem en venta.
La aplicacin de subastas hace consultas a la base de datos y graba e informa de las transaciones diarias. La aplicacin busca tems que se han cerrado y determina la puja ms
alta.
La aplicacin subasta usa el e-mail para notificar al que ha pujado ms alto y al vendedor, y cobrarle al vendedor por los servicios.
Los compradores y vendedores introducen un string de bsqueda para localizar todos los tems en subasta de la base de datos.
Para popularizar la subasta y conseguir nuevos vendedores y compradores, la aplicacin pemite que cualquiera vea los tems de la subasta sin requerir que est registrado. Para
hacer esto sencillo, la subasta permite que cualquiera vea una lista de los tems de alguna de estas tres formas:
Todos los tems en subasta.
La lista sumarizada enlaza con la siguiente informacin detallada de cada tem. Esta informacin est disponible para cualquiera sin necesidad de identificacin.
Sumario del tem.
Precio Actual
Nmero de pujas
ID del vendedor
Puja ms alta
Para postear un tem para su venta, un vendedor necesita identificarse a s mismo y describir el tem, de esta forma:
User ID y password para la identificacin del vendedor
Una pgina de sumario detallado por cada tem permite a los usuarios registrados identificarse a s mismos y pujar por el tem proporcionando la siguiente informacin:
User ID
Password
Cantidad de la Puja
Diagrama de Actividad
El diagrama de actividad muestra el flujo de tareas dentro de la casa de subastas como una totalidad. Este diagrama muestra la aplicacin subasta. El crculo negro de la izquierda
muestra el principio de las actividades, y el crculo blanco punteado en el centro denota donde terminan las actividades.
Oz it o
Elegir el Software
Con la aplicacin modelada y los requerimientos del proyecto definidos, es hora de
pensar en los APIs de JavaTM que vamos a usar. La aplicacin est claramente
basada en cliente y servidor porque queremos acomodar desde 1 hasta n
compradores, vendedores y mirones al mismo tiempo. Como el registro de los
datos de los tems en subasta deben almacenarse y recuperarse de alguna
manejar, necesitares el API para acceder a bases de datos.
Oz it o
Cdigo de la Aplicacin de la Casa de Subastas
La aplicacin de ejemplo es una casa de subastas basada en el Web y escrita para la plataforma Enterprise JavaBeansTM. El interface de usuario es un conjunto de pginas HTML
que obtienen la entrada del usuario y le muestran la informacin. Detrs de las pginas HTML hay un servelt que pasa datos entre el navegador y el servidor Enterprise JavaBeans.
Este servidor maneja la lectura y escritura de la base de datos.
Este captulo describe el cdigo de la aplicacin, cmo funciona con el servidor Enterprise JavaBeans, y dnde obtener este servidor para ejcutar el ejemplo. O, si lo prefieres, aqu
hay una maqueta de la aplicacin subasta.
Una Aplicacin Multi.Hilo con Enterprise Beans
Beans de Entidad y de Sesin
Examinar un Bean de Contenedor Controlador
Mtodos Buscadores del Contendor Controlador
Tienes Prisa?
Esta tabla contiene enlaces directos a los tpicos especficos.
Tpico Seccin
Una Aplicacin Multi-Hilo con Enterprise Beans El Enterprise Beans Definido
Beans de Entidad y de Sesin
La Casa de Subastas Funciona
Desarrollar y Ejecutar Aplicaciones
Cmo funcionan las aplicaciones Multi-Hilo?
Beans de Entidad y de Sesin El servelt Auction
Beans Entity
Beans Session
Clases Contenedor
Examinar un Bean de Contenedor Controlador Variables Miembro
Mtodo Create
Mtodos de Contexto de Entidad
Mtodo Load
Mtodo Store
Guardar la Conexin
Descriptor de Desarrollo
Mtodos del Buscador de Contenedo Controlador AuctionServlet.searchItems
BidderBean.getMatchingItemsList
AuctionItemHome.findAllMatchingItems
AuctionItemBean Deployment Descriptor
Oz it o
Un Aplicacin Multi-Fila con Beans de Enterprise
La proliferacin de aplicaciones basadas en internet - e intranet - ha creado una gran necesidad de aplicaciones transacionales distribuidas que aumente la velocidad, seguridad y
rendimiento de la tecnologa del lado del servidor. Una forma de conseguir estas necesidades es usar un modelo multi-fila donde una pequea aplicacin cliente invoca lgica de
negocio que se ejecuta en el servidor.
Normalmente, las pequeas aplicaciones clientes multi-hilo son dificiles de escribir porque se involucran muchas lneas de cdigo intrincado para manejar la transacin, el control de
estados, multithreads, solape de recursos y otros detalles complejos de bajo nivel. Y para rematar estas dificultades, tenemos que retrabajar este cdigo cada vez que escribamos
una aplicacin porque es tan de bajo nivel que no es reutilizable.
Si pudieramos usar un cdigo de manejo de transaciones preconstruido por alguien o incluso si puedieramos reutilizar algo de nuestro propio cdigo, ahorrariamos mucho tiempo y
energa que podramos utilizar para resolver otros problemas. Bien, la tecnologa Enterprise JavaBeansTM puede darnos la ayuda necesaria. Esta tecnologa hace sencillas de escribir
las aplicaciones transacionales distribuidas porque separa los detalles de bajo nivel de la lgica del negocio. Nos concentramos en crear la mejor solucin para nuestro negocio y
dejamos el resto a la arquitectura oculta.
Este captulo describe cmo crear la aplicacin de subastas del ejemplo usando los servicios proporcionados por la plataforma Enterprise JavaBeans. En los siguientes captulos
veremos como podemos personalizar estos servicios e integrar estas caractersticas en aplicaciones existentes no EJB.
Enterprise Beans Definidos
Bid d e rBe a n un Bean de sesin que usa Au c t io n I t e m Be a n para recuperar una listra de los tems de la subastas, slo los nuevos tems, tems cerca del cierre, e tems cuyo
sumario corresponde con una cadena de busqueda en la base de datos. Tambin comprueba la identidad del usuario y la password cuando alguien hace una puja, y almacena
las nuevas pujas en la base de datos.
S e lle rBe a n es un Bean de sesin que usa Re g is t ra t io n Be a n para comprobar la identidad del usuario y la password cuando alguien postea un tem para su subasta, y
Au c t io n I t e m Be a n para aadir nuevos tems a la base de datos de la subasta.
Como se ve en la figura superior, un Bean de entidad o de sesin realmente es una coleccin de clases e interfaces. Todos los Beans de entidad y de sesin consisten en un interfae
remoto, un interface home, y la clase del Bean. El servidor busca el interface home del Bean que est ejecutndose en el servidor JavaBeans de Enterprise, lo usa para crear el
interface remoto, e invoca a los mtodos del Bean a travs del interface remoto.
Un Interface remoto de un Bean Enterprise decribe los mtodos del Bean, o qu hace el Bean. Un programa cliente u otro Bean Enterprise llama a los mtodos definidos en el
interface remoto para invocar la lgica de negocios implementada por el Bean.
Un interface home de un Bean de Enterprise describe cmo un programa cliente u otro Bean Enterprise crea, encuentra (slo los Beans de entidad), y elimina ese Bean de
Enterpise de su contenedor.
El contenedor, mostrado en cyan en el grfico, proporciona el interface entre el Bean Interface y las funcionalidades de bajo nivel especficas de la plataforma que soporta el
Bean.
Como todo est sujeto a las especificaciones, todos los Beans Enterprise son intercambiables con contenedores, herramientas de desarrollo, y servidores creados por otros
vendedores. De hecho, podriamos escribir nuestro propio Bean Enterprise porque es posible, y algunas veces deseable, usar Beans Enterprise escritos por uno o ms proveedores
que ensamblaremos dentro de una aplicacin de JavaBeans Enterprise.
Servicio de Bsqueda
Para encontrar los objetos del servidor remoto en el momento de la ejecucin, el programa cliente necesita una forma de buscarlos. Una de estas formas es usar el API Java
Naming y Directory InterfaceTM (JNDI). JNDI es un interface comn para interfaces existentes de nombres y directorios. Los contenedores de los JavaBeans de Enterprise usan JNDI
como interface para el servicio de nombres del Remote Method Invocation (RMI).
Durante el desarrollo, el servicio JNDI registra el interface remoto con un nombre. Siempre que el programa cliente use el mismo servicio de nombres y pregunte por el interface
remoto con su nombre registrado, podr encontrarlo. El programa cliente llama al mtodo lo o k u p sobre un objeto ja v a x . n a m in g . Co n t e x t para preguntar por el interface remoto
con su nombre registrado. El objeto ja v a x . n a m in g . Co n t e x t es donde se almacenan las uniones y es un objeto diferente del contexto del JavaBean de Enterprise, que se cubre
ms adelante..
Comunicacin de Datos
Una vez que el programa cliente obtiene una referencia al objeto servidor remoto, hace llamadas a los mtodos de este objeto. Como el programa cliente tiene una referencia al
objeto servidor remoto, se usa una tcnica llamada "envolver datos" para hacer que parezca que el objeto servidor remoto es local para el programa cliente.
La "ordenacin de datos" es donde las llamadas a mtodos del objeto servidor remoto se empaquetan con sus datos y se envan al objeto servidor remoto. El objeto servidor
remoto desempaqueta (desordena) los mtodos y los datos, y llama al Bean Enterprise. El resultado de la llamda al Bean es empaquetado de nuevo y pasado de vuelta al cliente a
travs del objeto servidor remoto, y son desempaquetados.
Los contenedores de JavaBeans Enterprise usan servicios RMI para ordenar los datos. Cuando se compila un Bean, se crean unos ficheros s t u b (taln) y s k e le t o n (esqueleto). El
fichero t a l n proporciona la configuracin del empaquetado y desempaquetado de datos en el cliente, y el e s q u e le t o proporciona la misma informacin para el servidor.
Los datos se pasan entre el programa cliente y el servidor usando serializacin. La serializacin es una forma de representar objetos JavaTM como bytes que pueden ser enviados a
travs de la red como un stream y pueden ser reconstuidos en el mismo estado en el que fueron enviados originalmente.
Oz it o
Beans de Entidad y de Sesin
El ejemplo usa dos Beans de entidad y dos de sesin. Los Beans de entidad, Au c t io n I t e m Be a n y Re g is t ra t io n Be a n , representan tems persistentes que podran estar
almacenados en un base de datos, y los Beans de sesin, S e lle rBe a n y Bid d e rBe a n , representan operaciones de vida corta con el cliente y los datos.
Los Beans de sesin son el interface del cliente hacia los beans de entidad. El SellerBean procesa peticiones para aadir nuevos tems para la subasta. El BidderBean procesa
peticiones para recuperar tems de la subasta y situar las pujas por esos tems. El cambio o adicin de datos a la base de datos en un Bean controlado por contenedor se le deja a
los Beans de entidad:
Auction Servlet
Beans de Entidad
Beans de Sesin
Clases Contenedor
AuctionServlet
El AuctionServlet es esencialmente la segunda fila en la aplicacin y el punto focal para las actividades de la subasta. Acepta entradas finales del usuario desde el navegador
mediante el protocolo de transferencia de hypertexto (HTTP ), pasa la entrada al Bean Enterprise apropiado para su proceso, y muestra el resultado del proceso al usuario final en
el navegador.
Aqu hay un diagrama del tipo Unified Modeling Language (UML) para la clase Au c t io n S e rv le t .
Los mtodos de Au c t io n S e rv le t mostrados arriba invocan a la lgica del negocio que se ejecuta en el servidor buscando un Bean Enterprise y llamando a uno o ms de sus
mtodos. Cuando el servelt aade cdigo HTML a una pgina para mostrarsela al usuario, la lgica se ejecuta en el cliente.
Por ejemplo, el mtodo lis t AllI t e m s ( o u t ) ejecuta cdigo en el cliente para generar dinmicamente una pgina HTML para que la vea el cliente en un navegador. La pgina HTML
se rellena con los resultados de una llamada a Bid d e rBe a n que ejecuta la lgica en el servidor para generar una lista de todos los tems de la subasta.
if(enum != null) {
//Put retrieved items on servlet page.
displayitems(enum, out);
addLine("", out);
}
} catch (Exception e) {
//Pring error on servlet page.
addLine("AuctionServlet List All Items error",out);
System.out.println("AuctionServlet <list>:"+e);
}
out.flush();
}
Beans de Entidad
Au c t io n I t e m Be a n y Re g is t ra t io n Be a n son Beans de entidad. Au c t io n I t e m Be a n aade nuevos tems de subasta a la base de datos y actualiza la cantidad pujada por los
usuarios cuando stos pujan por el tem. Re g is t ra t io n Be a n aade informacin a la base de datos sobre usuarios registrados. Ambos Beans consisten en las clases descritas aqu.
Aqu estn las clase de Au c t io n I t e m Be a n . Recuerda que estos Beans de Enterprise son objetos distribuidos que usan el API RMI (Invocacin Remota de Mtodos), por eso, cuando
ocurre un error se lanza una excepcin RMI remota.
AuctionItem.java
AuctionItemHome.java
AuctionItemBean.java
AuctionItemPk.java
Au c t io n I t e m es un interface remoto. Describe qu hace el Bean declarando los mtodos definidos por el usuario que proporcionan la lgica de negocio para este Bean. Estos
mtodos son usados por el cliente para interactuar con el Bean sobre la conexin remota. Su nombre se mapea a la tabla AUCTI ON I TEMS que puedes ver abajo.
Au c t io n I t e m Ho m e es el interface home. Describe cmo se crea el Bean, como encontrarlo, y eliminarlo de su contenedor. Las herramientas de desarrollo del servidor de Beans de
Enterprise proporcionarn la implementacin para este interface.
Au c t io n I t e m Be a n es el Bean de Enterprise. Implementa En t it y Be a n , proporciona la lgica de negocio para los mtodos definidos por el desarrollador, e implementa los mtodos
de En t it y Be a n para crear el Bean y seleccionar el contexto de sesin. Esta es una clase que necesita implementar el desarrollador del Bean. Sus campos variables mapean a los
campos de la tabla AUCTI ON I TEMS que puedes ver abajo.
Au c t io n I t e m P K es la clase clave primaria. El servidor de Beans Enterprise requiere que un Bean de Entidad Manejado por Contenedor tenga una clase clave primaria con un
campo pblico primario (o campos, si se usan claves primarias compuestas). El desarrollador del Bean implementa esta clase. El campo I D es la clave primaria en la tabla
AUCTI ON I TEMS que puedes ver ms abajo, por eso el campo id es un campo pblico de esta clase. Al campo id se le asigna un valor cuando se construye la clase de la clave
primaria.
Podemos pedirle al contenedor que maneje la persistencia de la base de datos de un Bean Enterprise o escribir el cdigo para manejar la persistencia por nosotros mismos. En este
captulo, todos los beans son manejados por el contenedor. Con esto nosotros slo decimos qu campos son manejados por el contenedor y le dejamos al servidor de JavaBeans de
Enterprise que haga el resto. Esto es fenomenal para las aplicaciones sencillas, pero si tuvieramos que codificar algo ms complejo, necesitaramos ms control.
Cmo escribir los servicios ocultos de los JavaBeans Enterprise para ganar ms control o proporcionar servicios similares para las aplicaciones que no usen JavaBeans de Enterprise
se cubre en el captulo 3.
Re g is t ra t io n Be a n consta de las mismas clases y tablas de base de datos que el Bean Au c t io n I t e m , excepto que la lgica de negocio real, los campos de la tabla de la base de
datos, y la clave primaria son de alguna forma diferentes. En vez de describir las clases, podemos navegar por ellas y luego volver a la descripcin de las clases de Au c t io n I t e m si
tenemos alguna pregunta.
Registration.java
RegistrationHome.java
RegistrationBean.java
RegistrationPK.java
Tabla Registration
Beans de Sesin
Bid d e rBe a n y S e lle rBe a n son los Beans de sesin. Bid d e rBe a n recupera una lista de los tems de la subasta, busca tems, chuequea el ID y la password del usuario cuando
alguien hace una puja, y almacena las nuevas pujas en la base de datos. S e lle rBe a n chequea el ID y la password del usuario cuando alguien postea un tem para su subasta, y
aade nuevos tems para subasta a la base de datos.
Ambos Beans de sesin estn desarrollados inicialmente como Beans sin estado. Un Bean sin estado no mantiene un registro de lo que hizo el cliente en una llamada anterior;
mientras que un Bean con estado completo si lo hace. Los Beans con estado completo son muy tiles si la operacin es algo ms que una simple bsqueda y la operacin del cliente
depende de algo que ha sucedido en una llamada anterior.
Aqu estn las clase de Bid d e rBe a n . Recuerda que estos Beans de Enterprise son objetos distribuidos que usan el API RMI (Invocacin Remota de Mtodos), por eso, cuando
ocurre un error se lanza una excepcin RMI remota.
No exiten claves primarias porque estos Beans son temporales y no hay accesos a la base de datos. Para recuperar tems de la base de datos, Bid d e rBe a n crea un ejemplar de
Au c t io n I t e m Be a n , y para procesar las pujas, crea un ejemplar de Re g is t ra t io n Be a n .
Bidder.java
BidderHome.java
BidderBean.java
Bid d e r es un interface remoto. Describe lo que hace el Bean declarando los mtodos definidos por el desarrollador que proporcionan la lgica de negocio para este Bean. Esto son
los que que el cliente llama de forma remota.
Bid d e rHo m e es el interface home. Descibe cmo se crear el Bean, como se busca y como se elimina de su contenedor.
Bid d e rBe a n es el Bean de Enterprise. Implementa S e s s io n Be a n , proporciona la lgica de negocio para los mtodos definidos por el desarrollador, e implementa los mtodos de
S e s s io n Be a n para crear el Bean y seleccionar el contexto de sesin.
S e lle rBe a n consta de los mismos tipos de clase que un Bid d e rBe a n , excepto que la lgica de negocio es diferente. En vez de describir las clases, puedes navegar por ellas y luego
volver a la explicacin de Bid d e rBe a n si tienes alguna duda.
Seller.java
SellerHome.java
SellerBean.java
Clases Contenedor
Las clases que necesita el contenedor para desarrollar un Bean Enterprise dentro de un servidor de JavaBeans Enterprise particular se generan con una herramienta de desarrollo.
Las clases incluyen _ S t u b . c la s s y _ S k e l. c la s s que proporcionan el RMI en el cliente y el servidor respectivamente.
Estas clases se utilizan para mover datos entre el programa cliente y el servidor de JavaBeans de Enterprise. Adems, la implementacin de las clases se crea para los interfaces y
las reglas de desarrollo definidas para nuestro Bean.
El objeto S t u b se instala o se descarga en el sistema cliente y proporciona un objeto proxy local para el cliente. Implementa los interfaces remotos y delega de forma transparente
todas las llamadas a mtodos a travs de la red al objeto remoto.
El objeto S k e l se instala o se descarga en el sistema servidor y proporciona un objeto proxy local para el servidor. Despempaqueta los datos recibidos a travs de la red desde el
objeto S t u b para procesarlos en el servidor.
Oz it o
Examinar un Bean Controlado por Contenedor
Esta seccin pasea a travs del cdigo de RegistrationBean.java para ver lo fcil
que es hacer que el contenedor maneje la persistencia del almacenamiento de
datos en un medio oculto como una base de datos (por defecto).
Variables Miembro
Mtodo Create
Mtodos de Contexto de Entidad
Mtodo Load
Mtodo Store
Connection Pooling
Descriptor de Desarrollo
Variables Miembro
Un entorno de contenedor controlador necesita saber qu variables son para
almacenamiento persistente y cuales no. En el lenguaje JavaTM, la palabra clave
t ra n s ie n t indica variables que no son incluidas cuando los datos de un objeto se
serializan y escriben en un almacenamiento permanente. En la clase
Re g is t ra t io n Be a n . ja v a , la variable En t it y Co n t e x t est marcada como t ra n s ie n t
para indicar que su dato no ser escrito en ningn medio de almacenamiento.
El dato de En t it y Co n t e x t no se escribe en el almacenamiento permanente porque
su propsito es proporcionar informacin sobre el contexto en el momento de
ejecucin del contenedor. Por lo tanto, no contiene datos sobre el usuario
registrado y no debera grabarse en un medio de almacenamiento. Las otras
variables estn declaradas como p u b lic , por lo que el contenedor de este ejemplo
puede descubrirlas usando el API Reflection.
Mtodo Create
El mtodo e jb Cre a t e del Bean es llamado por el contenedor despus de que el
programa cliente llame al mtodo c re a t e sobre el interface re m o t o y pase los
datos de registro. Este mtodo asigna los valores de entrada a las variables
miembro que representan los datos del usuario. El contenedor maneja el
almacenamiento y carga de los datos, y crea nuevas entradas en el medio de
almacenamiento oculto.
this.theuser=theuser;
this.password=password;
this.emailaddress=emailaddress;
this.creditcard=creditcard;
this.balance=0;
Mtodo Load
El mtodo e jb Lo a d del Bean es llamado por el contenedor para cargar los datos
desde el medio de almacenamiento oculto. Esto sera necesario cuando
Bid d e rBe a n o S e lle rBe a n necesiten chequear la ID y password del usuario.
Connection Pooling
La carga y almacenamiento de datos en la base de datos puede tardar mucho
tiempo y reducir el rendimiento general de la aplicacin. Para reducir el tiempo de
conexin, el servidor de Weblogic BEA usa una cola de conexiones JDBCTM para
hacer un cache con las conexiones con la base de datos, por eso las conexiones
estn siempre disponibles cuando la aplicacin las necesita.
Sin embargo, no estamos limitados a la cola de conexiones JDBC. Podemos
sobreescribir el comportamiento de la cola de conexiones del Bean y sustituirla
nosotros mismos.
Descriptor de Desarrollo
La configuracin restante para un Brans persistente controlado por contenedor
ocurre en el momento del desarrollo. Lo que ves abajo es un Descriptor de
Desarrollo basado en texto usado en un servidor de BEA Weblogic Enterprise
JavaBeans.
(environmentProperties
(persistentStoreProperties
persistentStoreType jdbc
(jdbc
tableName registration
dbIsShared false
poolName ejbPool
(attributeMap
creditcard creditcard
emailaddress emailaddress
balance balance
password password
theuser theuser
); end attributeMap
); end jdbc
); end persistentStoreProperties
); end environmentProperties
<persistence-type>Container</persistence-type>
<cmp-field><field-name>creditcard
</field-name></cmp-field>
<cmp-field><field-name>emailaddress
</field-name></cmp-field>
<cmp-field><field-name>balance
</field-name></cmp-field>
<cmp-field><field-name>password
</field-name></cmp-field>
<cmp-field><field-name>theuser
</field-name></cmp-field>
<resource-ref>
<res-ref-name>registration</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Los campos del contenedor controlador se mapean directamente a su nombre
contraparte en la tabla de la base de datos. El recurso de autorizacin del
contenedor (re s - a u t h ) significa que el contenedor maneja el login a la tabla
REGI S TRATI ON .
Oz it o
Mtodos de Bsqueda del Contenedor Controlador
La facilidad de bsqueda de la casa de subastas est implementada como un mtodo fin d e r del contenedor. Arranca cuando el usuario escribe una cadena de bsqueda y pulsa el
botn S u b m it en la pgina principal para localizar un tem de la subasta. Como se muestra en el diagrama, el navegador pasa la cadena de bsqueda al mtodo
Au c t io n S e rv le t . s e a rc h I t e m , que luego la pasa al mtodo Bid d e rBe a n . g e t Ma t c h in g I t e m s Lis t .
En este punto, Bid d e rBe a n . g e t Ma t c h in g I t e m s Lis t pasa la cadena de bsqueda al mtodo fin d AllMa t c h in g I t e m s declarado en el interface Au c t io n I t e m Ho m e . Este mtodo es
un mtodo b u s c a d o r, y la implementacin del contenedor vara la forma en que maneja las llamadas a los mtodos fin d e r. Los contenedores BEA Weblogic buscan en el descriptor
de desarrollo del Bean la informacin sobre los mtodos fin d e r.
En el caso de la busqueda, el descriptor de desarrollo mapea la cadena de bsqueda pasada a Au c t io n I t e m Ho m e . fin d AllMa t c h in g I t e m s al campo s u m m a ry en la tabla
Au c t io n I t e m s de la base de datos. Este le dice al servidor Enterprise JavaBeansTM que recupere datos de todos los campos que en el campo s u m m a ry contengan el texto de la
cadena de bsqueda.
Esta seccin pasea a travs de las diferentes partes del cdigo de bsqueda fin d e r.
AuctionServlet.searchItems
BidderBean.getMatchingItemsList
AuctionItemHome.findAllMatchingItems
Descriptor de Desarrollo de AuctionItemBean
AuctionServlet.searchItems
El mtodo s e a rc h I t e m s recupera el texto de la cadena del navegador, crea una pgina HTML para mostar el resultado de la bsqueda, y le pasa la cadena de bsqueda al mtodo
Bid d e rBe a n . g e t Ma t c h in g I t e m s Lis t . Bid d e rBe a n es un Bean de sesin que recupera una lista de tems de la subasta y chequea la ID y la password del usuario para los usuarios
que quieren pujar por algn articulo.
Los resultados de la bsqueda se devuelven a este mtodo en una variable En u m e ra t io n .
if(enum != null) {
displayitems(enum, out);
addLine("", out);
}
} catch (Exception e) {
addLine("AuctionServlet Search Items error",
out);
System.out.println("AuctionServlet <newlist>:
"+e);
}
out.flush();
}
BidderBean.getMatchingItemsList
El mtodo Bid d e rBe a n . g e t Ma t c h in g I t e m s Lis t llama al mtodo Au c t io n I t e m Ho m e . fin d AllMa t c h in g I t e m s y le pasa la cadena de bsqueda. Au c t io n I t e m Be a n es un bean de
entidad que maneja actualizaciones y recuperaciones de tems de la subasta.
El resultado de la bsqueda es devuelto a este mtodo en una variableEn u m e ra t io n .
Enumeration enum=null;
try{
//Create Home interface for AuctionItemBean
AuctionItemHome home = (AuctionItemHome)
ctx.lookup("auctionitems");
AuctionItemHome.findAllMatchingItems
El mtodo Au c t io n I t e m Ho m e . fin d AllMa t c h in g I t e m s no est implementado por Au c t io n I t e m Be a n . Las implementaciones del mtodo Au c t io n I t e m Be a n fin d e r estn
definidas en el descriptor de desarrollo de Au c t io n I t e m Be a n cuando se usan contenedores de BEA Weblogic.
Cuando se usan estos contenedores, incluso si el Bean tiene implementaciones del mtodo fin d e r, son ignorados y en su lugar se consultan las selecciones en el descriptor de
desarrollo.
(finderDescriptors
"findAllItems()" "(= 1 1)"
"findAllNewItems(java.sql.Date newtoday)"
"(= startdate $newtoday)"
"findAllClosedItems(java.sql.Date closedtoday)"
"(= enddate $closedtoday)"
"findAllMatchingItems(String searchString)"
"(like summary $searchString)"
); end finderDescriptors
Oz it o
Manejo de Datos y Transaciones
Cuando usamos la arquitectura Enterprise JavaBeansTM, los datos se leen y
escriben en la base de datos sin tener que escribir ningn cdigo SQL. Pero qu
pasa si no quereos almacenar los datos en una base de datos, o si queremos
escribir nuestros propios comandos SQL, o manejar transaciones?
Podemos sobreescribir el contenedor controlador interno de persistencia e
implementar un Bean controlador de persistencia usando nuestro propio
almacenamiento de datos y nuestro cdigo de manejo de transaciones.
La persistencia del Bean controlador se convierte en til cuando queremos ms
control del que proporciona el contenedor controlador. Por ejemplo podramos
sobreescribir la mayora de los contenedores para que mapeen un Bean en una fila
de la tabla, implementar nuestros propios mtodos fin d e r, o personalizar el cach.
Este captulo presenta dos versiones de la clase Re g is t ra t io n Be a n del captulo
anterior. Una versin lee y escribe los datos del usuario en un fichero usando
streams de entrada y salida serializados. La otra versin proporciona nuestros
propios comandos SQL para leer y escribir en la base de datos. Tambin explica
cmo podemos escribir nuestro propio cdigo de manejo de transaciones.
Bean-Controlador de Persistencia y la plataforma JDBCTM
Manejar Transaciones
Mtodos de Bsqueda del Bean Controlador
Tienes Prisa?
Esta tabla te lleva directamente a los tpicos especficos
T p ic o S e c c i n
Bean-Controlador de Persistencia y la Conectar con la base de datos
Plataformna JDBC Mtodo Create
Mtodo Load
Mtodo Refresh
Mtodo Store
Mtodo Find
Manejo de Transaciones Por qu Manejar Transaciones?
Sincronizacin de Sesin
Transaction Commit Mode
Mtodos de Bsqueda del Bean-Controlador AuctionServlet.searchItems
SearchBean
Oz it o
Bean-Controlador de Persistencia y la Plataforma
JDBC
Puede que haya algunas veces que querramos sobreescribir la persistencia del
contenedor controlador e implementar mtodos de Beans de entidad o de sesin
para usar nuestros propios comandos SQL. Este tipo de persistencia controlada por
el Bean puede ser til si necesitamos aumentar el redimiento o mapear datos de
mltiples Beans en una sla fila de la tabla de la base de datos.
Esta seccin nos muestra cmo convertir la clase RegistrationBean.java para
acceder a la base de datos con la clase P re p a re d S t a t e m e n t del JDBC.
Conectar con la Base de Datos
Mtodo Create
Mtodo Load
Mtodo Refresh
Mtodo Store
Mtodo Find
this.theuser=theuser;
this.password=password;
this.emailaddress=emailaddress;
this.creditcard=creditcard;
this.balance=0;
try {
con=getConnection();
ps=con.prepareStatement("insert into registration (
theuser, password,
emailaddress, creditcard,
balance) values (
?, ?, ?, ?, ?)");
ps.setString(1, theuser);
ps.setString(2, password);
ps.setString(3, emailaddress);
ps.setString(4, creditcard);
ps.setDouble(5, balance);
if (ps.executeUpdate() != 1) {
throw new CreateException (
"JDBC did not create a row");
}
RegistrationPK primaryKey = new RegistrationPK();
primaryKey.theuser = theuser;
return primaryKey;
} catch (CreateException ce) {
throw ce;
} catch (SQLException sqe) {
throw new CreateException (sqe.getMessage());
} finally {
try {
ps.close();
} catch (Exception ignore) {}
try {
con.close();
} catch (Exception ignore) {}
}
}
Mtodo Load
Este mtodo obtiene la clave primaria desde el contexto de entidad y lo pasa al
mtodo re fre s h que carga los datos.
Mtodo Refresh
El mtodo re fre s h es el cdigo suministrado por el programador para cargar los
datos desde la base de datos. Chequea la clave primaria, obtiene la conexin con la
base de datos, y crea un objeto P re p a re d S t a t e m e n t para consultar en la base de
datos la clave primaria especificada.
Los datos se leen desde la base de datos en un Re s u lt S e t y se asignan a las
variables miembro globales para que Re g is t ra t io n Be a n tenga la informacin ms
actualizada del usuario.
if (pk == null) {
throw new RemoteException ("primary key
cannot be null");
}
Connection con = null;
PreparedStatement ps = null;
try {
con=getConnection();
ps=con.prepareStatement("select password,
emailaddress, creditcard,
balance from registration
where theuser = ?");
ps.setString(1, pk.theuser);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
if (rs.next()) {
theuser = pk.theuser;
password = rs.getString(1);
emailaddress = rs.getString(2);
creditcard = rs.getString(3);
balance = rs.getDouble(4);
}
else {
throw new FinderException (
"Refresh: Registration ("
+ pk.theuser + ") not found");
}
}
catch (SQLException sqe) {
throw new RemoteException (sqe.getMessage());
}
finally {
try {
ps.close();
}
catch (Exception ignore) {}
try {
con.close();
}
catch (Exception ignore) {}
}
}
Mtodo Store
Este mtodo obtiene una conexin con la base de datos y crea un
P re p a re d S t a t e m e n t para actualizarla.
Oz it o
Control de Transaciones
No sera maravilloso si cada operacin que intentara nuestra aplicacin tuviera
xito? Desafortunadamente, en el mundo multi-thread de las aplicaciones
distribuidas y recursos compartidos, esto no es siempre posible.
Por qu? Primero de todo, los recursos compartidos deben mantener una vista
consistente de los datos de todos los usuarios. Esto significa que leer y escribir
tiene que ser controlado para que los usuarios no se sobreescriban los datos unos
a los otros, o los errores de transacin no corrompan la integridad de los datos.
Tambin, si trabajamos en una red con retardos intermitenes o cadas de
conexiones, el potencial para que las operaciones fallen en una aplicacin basada
en web se incrementa con el nmero de usuarios.
Los fallos de operaciones son inevitables, lo mejor es recuperar luego la seguridad,
y aqu es donde entra el control de transaciones. Las bases de datos modernas y
los controladores de transaciones nos permiten deshacer y repetir el estado de una
secuencia de operaciones fallidas para asegurar que los datos son consistentes
para el acceso desde mltiples threads.
Esta seccin aade cdigo al S e lle rBe a n del ejemplo de la casa de subastas para
que pueda manejar la insercin de itms en la subasta ms all del controlador de
transaciones por defecto proporcionado por su contenedor.
Por qu Controlar las Transaciones?
Sincronizacin de Sesin
Ejemplo de Contenedor Controlador
Cdigo
Modo de Entrega de la Transacin
Configurador del Servidor
Descripciones de Atributos de Transacin
Descripciones del Nivel de Aislamiento
Ejemplo de Bean-Controlador
Sincronizacin de Sesisn
Un Bean de sesin controlado por contenedor puede opcionalmente incluir
sincronizacin de sesin para controlar la entrega automtica por defecto
propocionada por el contenedor. El cdigo de sincronizacin permite al contenedor
notificar al Bean cuando se alcanzan los puntos importantes en la transacin.
Adems de recibir la notificacin, el Bean puede tomar cualquier accin necesaria
antes de que la transacin proceda con el siguiente punto.
N o t a : Un Bean de Sesin que usa transaciones controladas por Bean no
necesita sincronizacin de sesin porque tiene la entrega totalmente
controlada.
Cdigo
try{
Context jndiCtx = new InitialContext(p);
RegistrationHome rhome =
(RegistrationHome) sCtx.lookup("registration");
RegistrationPK rpk=new RegistrationPK();
rpk.theuser=seller;
Registration newseller=rhome.findByPrimaryKey(rpk);
if((newseller == null) ||
(!newseller.verifyPassword(password))) {
return(Auction.INVALID_USER);
}
//Call to afterBegin
newseller.adjustAccount(-0.50);
}catch(Exception e){
System.out.println("insert problem="+e);
success=false;
return Auction.INVALID_ITEM;
}
//Call to beforeCompletion
//Call to afterCompletion
(controlDescriptors
(DEFAULT
isolationLevel TRANSACTION_SERIALIZABLE
transactionAttribute REQUIRED
runAsMode CLIENT_IDENTITY
runAsIdentity guest
); end DEFAULT
); end controlDescriptors
Aqu est el equivalente en lenguaje XML.
<container-transaction>
<method>
<ejb-name>SellerBean<ejb-name>
<method-name>*<method-name>
<method>
<transaction-type>Container<transaction-type>
<trans-attribute>Required<trans-attribute>
<container-transaction>
En este ejemplo, S e lle rBe a n est controlado por el Bean.
<container-transaction>
<method>
<ejb-name>SellerBean<ejb-name>
<method-name>*<method-name>
<method>
<transaction-type>Bean<transaction-type>
<trans-attribute>Required<trans-attribute>
<container-transaction>
D e s c rip c i n d e At rib u t o d e Tra n s a c i n : Un Bean Enterprise usa un t ra n s a ct io n
a t t rib u t e para especificar si una transacin de Bean es manejada por el propio
Bean o por el contenedor, y cmo manejar las transaciones que empezaron en otro
Bean.
El servidor de JavaBeans de Enterprise slo puede controlar una transacin a la
vez. Este modelo sigue el ejemplo configurado por el Object Transaction Service
(OTS) de la OMG, y significa que la especificacin actual de los JavaBeans
Enterpirse no proporcionan una forma para transaciones anidadas. Una transacin
anidada es un nueva transacin que arranca dentro de otra transacin existente.
Mientras que las transaciones anidadas no estn permitidas, continuar una
transacin existente en otro Bean es correcto.
Cuando se entra en un Bean, el servidor crea un contexto de transacin para
controlar la transacin. Cuando la transacin es manejada por le Bean, accedemos
para comenzar, entregar o deshacer la transacin cuando sea necesario.
Aqu estn los atributos de transacin con una breve descripcin de cada uno de
ellos. Los nombres de los atributos cambiaron entre las especificaciones 1.0 y 1.1
de los JavaBeans Enterprise.
Es p e c ific a c i n 1 . Es p e c ific a c i n 1 . 0
TRAN S ACTI ON _ S ERI ALI ZABLE: Este nivel proporciona la mxima integridad de
los datos. El Bean decide la cantidad de accesos exclusivos. Ninguna otra
transacin puede leer o escribir estos datos hasta que la transacin serializable se
complete.
En este contexto, serializable significa p ro ce s o co m o u n a o p e ra ci n s e ria l, y no
debera confundirse con la serializacin de objetos para preservar y restaurar sus
estados. Ejecutar transaciones como una sla operacin serial es la seleccin ms
lenta. Si el rendimiento es un problema, debemos usar otro nivel de aislamiento
que cumpla con los requerimientos de nuestra aplicacin, pero mejore el
rendimiento.
TRAN S ACTI ON _ REP EATABLE_ READ : En este nivel, los datos leidos por una
transacin pueden ser leidos, pero no modificados, por otra transacin. Se
garantiza que el dato tenga el mismo valor que cuando fue ledo por primera vez, a
menos que la primera transacin lo cambie y escriba de nuevo el valor cambiado.
TRAN S ACTI ON _ READ _ COMMI TTED : En este nivel, los datos ledos por una
transacin no pueden ser ledos por otra transacin hasta que la primera
transacin los haya entregado o deshecho
TRAN S ACTI ON _ READ _ UN COMMI TTED :En este nivel, los datos involucrados en
una transacin pueden ser ledos por otros threads antes de que la primera
transacin se haya completado o se haya deshecho. Las otras transaciones no
pueden saber si los datos fueron finalmente entregados o deshechos.
try{
Context ectx = new InitialContext(p);
RegistrationHome rhome = (
RegistrationHome)ectx.lookup("registration");
RegistrationPK rpk=new RegistrationPK();
rpk.theuser=seller;
Registration newseller=
rhome.findByPrimaryKey(rpk);
if((newseller == null)||
(!newseller.verifyPassword(password))) {
return(Auction.INVALID_USER);
}
AuctionItemHome home = (
AuctionItemHome) ectx.lookup("auctionitems");
AuctionItem ai= home.create(seller,
description,
auctiondays,
startprice,
summary);
if(ai == null) {
//Roll transaction back
uts.rollback();
return Auction.INVALID_ITEM;
}
else {
//Commit transaction
uts.commit();
return(ai.getId());
}
}catch(Exception e){
System.out.println("insert problem="+e);
//Roll transaction back if insert fails
uts.rollback();
return Auction.INVALID_ITEM;
}
}
Oz it o
Mtodos de Bsqueda de Bean Controlador
La bsqueda en el contenedor controlador descrita en el captulo 2 est basada en el mcanismo del mtodo fin d e r donde el descriptor de desarrollo, en lugar del Bean, especifica el
comportamiento del mtodo fin d e r. Mientras el mecanismo del mtodo fin d e r funciona bien para consultas sencillas, no puede manejar operaciones complejas que impliquen ms de un
tipo de Bean o tablas de bases de datos. Tambin, la especificacin 1.1 de los JavaBeans de Enterprise actualmente no proporciona para poner las reglas del mtodo fin d e r en el
descriptor de desarrollo.
Por eso, para consultas y bsquedas ms complejas, tenemos que escribir bsquedas y consultas controladas por el Bean. Esta seccin explica cmo escribir una versin de la facilidad
de bsqueda de la casa de subastas controlada por el Bean. La bsqueda controlada por el Bean inplica cambios en el mtodo Au c t io n S e rv le t . s e a rc h I t e m s y un nuevo Bean de sesin,
S e a rc h Be a n .
AuctionServlet.searchItems
SearchBean
AuctionServlet.searchItems
La bsqueda empieza cuando el usuario final enva una cadena de bsqueda a la facilidad de bsqueda de la pgina principal de la casa de subastas, y pulsa el boton S u b m it . Esto llama
a Au c t io n S e rv le t , que recupera la cadena de bsqueda desde la cabecera HTTP y la pasa al mtodo s e a rc h I t e m .
N o t a : La lgica de bsqueda para este ejemplo es bastante simple. El propsito es mostrar cmo mover la lgica de bsqueda a otro Bean Enterprise separado para que
podamos mover bsquedas ms complejas nosotros solos.
La
operacin s e a rc h I t e m se hace en dos partes: 1) usar la cadena de bsqueda para recuperar las claves primarias, y 2) usar las claves primarias para recuperar los tems de la subasta
P a rt e 1 : Lo primero que hace el mtodo searchItems es pasar la cadena de bsqueda enviada por el usuario final al Bean de sesin S e a rc h Be a n .
S e a rc h Be a n (descrito en la siguiente seccin) implementa una bsqueda controlada por Bean que recupera una lista de claves primarias para todos los tems de la subasta cuyo campo
S u m m a ry contenga caracteres que correspondan con los de la cadena de bsqueda. Esta lista es devuelta al mtodo s e a rc h I t e m s en una variable En u m e ra t io n .
Enumeration enum=(Enumeration)
search.getMatchingItemsList(searchString);
Pa r
2 : El mtodo s e a rc h I t e m s usa la lista En u m e ra t io n devuelta en la parte 1 y usa AuctionItemBean para recuperar cada Bean por turno llamando a fin d By P rim a ry Ke y sobre cada clave
primaria de la lista. Esta es una bsqueda controlada por contenedor basada en el mecanismo del mtodo fin d e r descrito en el captulo 2.
SearchBean
La clase SearchBean.java define una bsqueda controlada por el Bean para claves primarias de tems de subasta con los campos s u m m a ry que contienen caracteres que corresponden
con la cadena de bsqueda. Este Bean establece una conexin con la base de datos, y proporciona los mtodos g e t Ma t c h in g I t e m s Lis t y EJBCre a t e .
Como este Bean controla su propio acceso a la base de datos, tiene que establecer su propia conexin con ella. No puede delegar esto al contenedor..
La conexin con la base de datos se establece ejemplarizando una clase D riv e r esttica y proporcionando el mtodo g e t Co n n e c t io n . Este mtodo requiere una clase esttica
D riv e rMa n a g e r para registrar un driver con la base de datos que corresponda con la URL. En este caso la URL es w e b lo g ic . jd b c . jt s . D riv e r.
El mtodo g e t Ma t c h in g I t e m s Lis t busca Au c t io n I t e m s Be a n y crea un objeto P re p a re d S t a t e m e n t para hacer una consulta a la base de datos por los campos s u m m a ry que
contengan la cadena de bsqueda. Los datos se leen desde la base de datos dentro de un Re s u lt S e t , almacenado en un Ve c t o r, y devuelto a Au c t io n S e rv le t .
ResultSet rs = null;
PreparedStatement ps = null;
Vector v = new Vector();
Connection con = null;
try{
//Get database connection
con=getConnection();
//Create a prepared statement for database query
ps=con.prepareStatement("select id from
auctionitems where summary like ?");
ps.setString(1, "%"+searchString+"%");
//Execute database query
ps.executeQuery();
//Get results set
rs = ps.getResultSet();
//Get information from results set
AuctionItemPK pk;
while (rs.next()) {
pk = new AuctionItemPK();
pk.id = (int)rs.getInt(1);
//Store retrieved data in vector
v.addElement(pk);
}
rs.close();
return v.elements();
}catch (Exception e) {
System.out.println("getMatchingItemsList:
"+e);
return null;
}finally {
try {
if(rs != null) {
rs.close();
}
if(ps != null) {
ps.close();
}
if(con != null) {
con.close();
}
} catch (Exception ignore) {}
}
}
Mtodo Create
El mtodo e jb Cre a t e crea un objeto ja v a x . n a m in g . I n it ia lCo n t e x t . Esta es una clase JNDI (Java Nanimg and Directory) que permite a S e a rc h Be a n acceder a la base de datos sin
relacionarse con el contenedor:
Oz it o
Clculo Distribuido
Tan recientemente como hace diez aos, el clculo distribuido generalmente
significaba que teniamos clientes PCs en una habitacin con un servidor en otra. El
problema con esta arquitectura es que si se pierde la conexin con el servidor, los
clientes no pueden actualizar las bases de datos de la compaa.
Para evitar esta prdida de tiempo, se crearon los diferentes modelos de red. Un
ejemplo es el modelo de servidor maestro y esclavo donde si el maestro falla, el
esclavo toma el relevo. El problema con los distintos modelos de red es que todos
requieren alguna forma de intervencin manual y se unieron con un sistema
operativo o un lenguaje. Y aunque estas aproximaciones consiguieron reducir el
tiempo de parada, no cumplen con los sistemas de distribucin heterognea que
consiste en una mezcla de protocolos de red y mquinas.
La plataforma JavaTM combinada con otros avances como Common Object Request
Broker Architecture (CORBA), servidores multi-fila, y redes sin cables han llevado
un paso mas all la realizacin de la computacin totalmentedistribuida, de la
tradicional aproximacin cliente y servidor.
Ahora podemos construir aplicaciones que incluyan servicios de redundancia por
defecto. Si una conexin de servidor falla, podemos usar un servicio de otro
servidor. CORBA y los puentes "Distributed Component Object Model" (DCOM)
significan que los objetos pueden ser transferidos entre casi todas las mquinas y
lenguajes. Y con el nuevo sistema de software JiniTM, el entorno de clculo
distribuido pude estar pronto en todos los hogares, oficinas o escuelas.
Servicios de Bsqueda
Tienes Prisa?
Esta tabla te llevar directamente a los tpicos especificados.
T p ic o S e c c i n
Servicios de Bsqueda Java Naming and Directory Interface (JNDI)
Common Object Request Broker Architecture
(CORBA) Naming Service
Interoperable Object References (IOR)
Remote Method Invocation (RMI)
RMI Over Internet Inter-ORB Protocol (IIOP)
JINI Lookup Services
Aumentar el Rendimiento de la Bsqueda
Remote Method Sobre RMI
Invocation (RMI) RMI en la aplicacin Subasta
Introduccin a la Clase
Sumario de Ficheros
Compilar el Ejemplo
Arrancar el Registro RMI
Arrancar el Servidor Remoto
Establecer Comunicaciones Remotas
La clase RegistrationServer
Exportar un Objeto Remoto
Pasar por Valor y por Referencia
Recoleccin de Basura Distribuida
Interface Registration
Interface ReturnResults
La Clase SellerBean
Common Object Esquema de Mapeo IDL
Request Broker Referencia Rpida
Architecture (CORBA)
Configurar el Mapeo IDL
Otros Tipos IDL
CORBA en la Aplicacin de Subasta
CORBA RegistrationServer
Fichero de Mapeos IDL
Compilar el Fichero de Mapeos IDL
Ficheros Stub y Skeleton
Object Request Broker (ORB)
Hacer Accesible el Servidor CORBA
Aadir un nuevo ORB
Accesos al Servicio de Nombres por clientes
CORBA
Clases Helper y Holder
Recoleccin de Basura
Retrollamadas CORBA
Uso de Cualquier Tipo
Conclusin
Tecnologa JDBC Drivers JDBC
Conexiones a Bases de Datos
Sentencias
Sentencias Callable
Sentencias
Sentencias Preparadas
Guardar los Resultados de la Base de Datos
Hojas de Resultados
Hojas de Resultados Scrollables
Controlar Transaciones
Caracteres de Escape
Mapeo de Tipos de Bases de Datos
Mapeo de Tipos de Datos
Oz it o
Servicios de Bsqueda
Los servicios de bsqueda permiten las comunicaciones a travs de la red. Un programa cliente puede usar un protocolo de bsqueda para obtener informacin sobre programas
remotos o mquinas que usen esa informacin para establecer una comunicacin.
Un servicio de bsqueda comn con el que podramos estar familiarizados es el Directory Name Service (DNS). Mapea direcciones de Internet Protocol (IP) a nombres de
mquinas. Los programas usan el mapeo DNS para buscar direcciones IP asociadas con un nombre de mquina y usar la direccin IP para establecer una comunicacin.
De la misma forma, el AuctionServlet presentado en Chapter 2 usa el servicio de nombres interno de la arquitectura de JavaBeans Enterprise para buscar unas referencias a Beans
Enterprise registrados con el servidor de JavaBeans Enterprise.
Adems de los servicios de nombres, algunos protocolos de bsqueda proporcionan servicios de directorio. Este servicios como el Lightweight Directory Access Protocol (LDAP) y el
NIS+ de Sun proporcionan otra informacin y servicios ms all de los disponibles con el servicio de nombres. Por ejemplo, NIS+ asocia un atributo w o rk g ro u p con una cuenta de
usuario. Este atributo puede usarse para restringir el acceso a una mquna, por lo que slo los usuarios especificados en el w o rk g ro u p tienen acceso.
Este captulo describe como se usa el "Naming and Directory Interface (JNDI)" de Java en la aplicacin de subastas para buscar los Beans de Enterprise. Tambin explica como usar
algunos de los otros muchos servicios de bsqueda que tenemos disponibles. El cdigo para usar estos servicios no es tan sencillo como el cdigo de la bsqueda en la aplicacin de la
subasta del captulo 2, pero las ventajas que ofrecen estos otros servicios hacen que algunas veces merezca la pena ese cdigo ms complejo.
Java Naming and Directory Interface (JNDI)
RegistrationHome rhome =
(RegistrationHome) ctx.lookup("registration");
RegistrationPK rpk=new RegistrationPK();
rpk.theuser=buyer;
Registration newbidder =
rhome.findByPrimaryKey(rpk);
En el lado del servidor, el descriptor de desarrollo para el Re g is t ra t io n Be a n tiene su valor b e a n h o m e n a m e como re g is t ra t io n . Las herramientas de JavaBeans de Enterprise
generan el resto del cdigo de nombres para el servidor.
El servidor llama a c t x . b in d para unir el nombre re g is t ra t io n al contexto JNDI. El parmetro t h is referencia a la clase _ s t u b que representa el Re g is t ra t io n Be a n .
ctx.bind("registration", this);
JNDI no es la nica forma de localizar objetos remotos. Los servicios de bsqueda tambin estn disponibles en las plataformas RMI, JNI y CORBA. Podemos usar directamente los
servicios de bsqueda de estas plataformas directamente desde el API del JNDI. JNDI permite a las aplicaciones cambiar el servicio de nombres con poco esfuerzo. Por ejemplo, aqu
est el cdigo que hace que el mtodo Bid d e rBe a n . e jb Cre a t e use el servicio de bsqueda de o rg . o m b . CORBA en vez del servicio de bsqueda por defecto de BEA Weblogic.
CORBA RegistrationServer
Este cdigo del programa RegistrationServer crea un objeto N a m e Co m p o n e n t que indica dnde est localizado el Re g is t ra t io n Be a n usando a u c t io n y Re g is t ra t io n Be a n como el
nombre completo:
try{
org.omg.CORBA.Object nameServiceObj =
orb.resolve_initial_references("NameService");
NamingContext nctx =
NamingContextHelper.narrow(nameServiceObj);
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
NameComponent[] tempComponent =
new NameComponent[1];
for(int i=0; i < fullname.length-1; i++ ) {
tempComponent[0]= fullname[i];
try{
nctx=nctx.bind_new_context(tempComponent);
}catch (Exception e){}
}
tempComponent[0]=fullname[fullname.length-1];
tnameserv
Esto arranca el Re g is t ra t io n S e rv e r CORBA en el puerto TCP por defecto 900. Si necesitamos usar otro puerto diferente, podemos arrancar el servidor de esta forma. En sistemas Unix,
slo el administrador puede acceder a los nmeros de puerto inferiores a 1025,
CORBA SellerBean
En el lado del cliente, la bsqueda CORBA usa el objeto N a m e Co m p o n e n t para construir el nombre. Arrancamos el servidor de objetos de esta forma:
java registration.RegistrationServer
La diferencia en el cliente es que este nombre se pasa al mtodo re s o lv e que devuelve el objeto CORBA. El siguiente cdigo del objeto SellerBean ilustra este punto:
Servidor IOR
Para crear un IOR todo lo que tenemos que hacer es llamar al mtodo o b je c t _ t o _ s t rin g desde la clase ORB y pasarle un ejemplar del objeto. Por ejemplo, para convertir el objeto
Re g is t ra t io n S e rv e r en un IOR, necesitamos aadir la lnea S t rin g re f = o rb . o b je c t _ t o _ s t rin g ( rs ) ; del siguiente cdigo en el programa principal:
Cliente IOR
Este ejemplo usa una conexin HTTP para convertir el string IOR de nuevo en un objeto. Podemos llamar al mtodo s t rin g _ t o _ o b je c t desde la clase ORB. Este mtodo llama al IOR
desde el Re g is t ra t io n S e rv e r y devuelve el string ORB. Este string se pasa al ORB usando el mtodo ORB. s t rin g _ t o _ o b je c t , y el ORB devuelve la referencia al objeto remoto:
SellerHome shome =
(SellerHome)Naming.lookup(
"rmi://appserver:1090/seller");
Este cdigo devuelve la referencia remota de S e lle rHo m e desde el objeto unido al nombre s e lle r en la mquina llamada a p p s e rv e r. La parte rm i de la URL es opcional y podramos
haber visto URLs RMI sin ella, pero si estmos usando JNDI o RMI-IIOP, incluir rm i en la URL nos ahorra confusiones posteriores. Una vez que tenemos la referencia a S e lle rHo m e ,
podemos llamar a sus mtodos.
En contraste con la bsqueda JNDI realizada por Au c t io n S e rv le t . ja v a , que requiere una bsqueda de dos estados para crear un contexto y luego la bsqueda real, RMI inicializa la
conexin con servidor de nombres RMI, rm ire g is t ry , y tambin obtiene la referencia remota con una llamada.
Esta referencia remota ser el cliente inquilino de rm ire g is t ry . Inquilino significa que a menos que el cliente informe al servidor de que todava necesita una referencia al objeto, el
alquiler expira y la memoria es liberada. Esta operacin de alquiler es transparente para el usuario, pero puede ser ajustada seleccionando el valor de la propiedad
ja v a . rm i. d g c . le a s e Va lu e en el servidor, en milisegundos cuando se arranca el servidor de esta forma:
N o t a : El compilador rm ic proporciona la opcin - iio p para generar el stub y las clases tie necesarias para RMI-IIOP.
Servidor IIOP
El protocolo RMI-IIOP se implementa como un plug-in JNDI, por lo que como antes, necesitamos crear un I n it ia lCo n t e x t :
Ciente IIOP
En el lado del cliente, la bsqueda RMI se cambia para usar un ejemplar del I n it ia lCo n t e x t en lugar del N a m in g . lo o k u p de RMI. El objeto devuelto es mapeado al objeto requerido
usando el mtodo n a rro w de la clase ja v a x . rm i. P o rt a b le Re m o t e Ob je c t . P o rt a b le Re m o t e Ob je c t reemplaza Un ic a s t Re m o t e Ob je c t que estaba disponible anteriormente en cdigo
de servidor RMI.
Viejo cdigo de bsqueda RMI:
127.0.0.1 localhost
129.1.1.1 myserver1
129.1.1.2 myserver2
Oz it o
Invocacin Remota de Mtodos
El API de Invocacin Remota de Mtodos (RMI) permite las comunicaciones entre cliente y servidor a travs de la red entre programas escritos en Java. El servidor de JavaBeans
Enterprise implementa de forma transparente el cdigo RMI necesario para que el programa cliente pueda referenciar a los Beans Enterprise que se ejecutan en el servidor y acceder a
ellos como si se estuvieran ejecutando localmente en el programa cliente.
El tener el RMi incluido internamente el servidor JavaBeans de Enterprise es muy conveniente y nos ahorra tiempo de codificacin, pero si necesitamos usar caractersticas avanzadas
de RMI o integrar RMI con una aplicacin existente, necesitamos sobreescribir la implementacin por defecto RMI y escribir nuestro propio cdigo RMI.
El captulo reemplaza el Re g is t ra t io n Be a n manejado por contenedor del Captulo 2: Beans de Entidad y de Sesin con un servidor de registro basado en RMI. El Bean S e lle rBe a n del
captulo 2, tambin se modifica para llamar al nuevo servidor de registro RMI usando una llamada a lo o k u p de Java 2 RMI.
Sobre RMI
Sobre RMI
El API RMI nos permite accede a un servidor de objetos remoto desde un programa cliente haciendo sencillas llamadas a mtodos del servidor de objetos. Mientras que otras
arquitecturas distribuidas para acceder a servidores de objetos remotos como "Distributed Component Object Model" (DCOM) y "Common Object Request Broker Architecture" (CORBA)
devuelven referencias al objeto remoto, el API RMI no slo devuelve referencias, si no que proporciona beneficios adicionales.
El API RMI maneja referencias a objetos remotos (llamadas por referencia) y tambin devuelve una copia del objeto (llamada por valor).
Si el programa cliente no tiene acceso local a la clase para la que se ejemplariz un objeto remoto, los servicios RMI pueden descargar el fichero class.
Para transferir ojbjetos, el API RMI usa el API Serialization para empaquetar (colocar) y desempaquetar (descolocar) los objetos. Para colocar un objeto, el API Serialization convierte el
objeto a un Stream de bytes, y para descolocar el objeto, el API Serialization convierte un stream de bytes en un objeto.
Una de las desventajas iniciales del RMI era que la nica relacin con la plataforma Java para escribir interfaces hacen dficil la intregracin con sistemas legales existentes. Sin
embargo, RMI sobre "Internet Inter-ORB Protocol" (IIOP) explicado en el Captulo 4: Servicios de Bsqueda permite a RMI comunicarse con cualquier sistema o lenguaje que soporte
CORBA.
Si combinamos la integracin mejorada con la habilidad de RMI para trabajar a travs de firewalls usando proxies HTTP, podramos encontrar distribuciones para la lgica de nuestro
negocio usando RMI ms fciles que una solucin basada en sockets.
N o t a : La transferencia de cdigo y datos son partes clave de la especificacin JINI. De hecho, si aadieramos un servicio de uniones a los servicios RMI crearamos algo muy
similar a los que obtenemos con la arquitectura JINI.
La nueva bsqueda personalizada sevuelve los resultados al cliente llamante mediante una llamada a un Callbak RMI. Est bsqueda es similar a los mtodos fin d e r usados en los
Beans de ejemplos usados en los captulos 2 y 3, excepto en que la versin RMI, puede tardar ms tiempo en generar los resultados porque el sevidor de registros remoto llama al
mtodo remoto exportado por el cliente SellerBean basado en RMI.
Si el cliente llamante est escrito en Java, y no es, por ejemplo, una pgina web, el servidor puede actualizar el cliente tan pronto como los resultados estuvieran listos. Pero, el
protocolo HTTP usado en la mayora de los navegadores no permite que los resultados sean enviados sin que haya una peticin. Esto significa que el resultado de una pgina web no se
crea hasta que los resultados estn listos, lo que aade un pequeo retraso.
Las dos clases principales en la implementacin de la subasta basada en RMI son SellerBean y el remoto RegistrationServer. S e lle rBe a n es llamado desde AuctionServlet para insertar
un tem para la subasta en la base de datos, y chequear balances negativos en las cuentas.
Los modelos de ejemplo de la arquitectura JavaBeans Enterprise en los que los detalles de registro del usuario se han separado del cdigo para crear y encontrar detalles de registro. Es
decir, los detalles de registro de usuario proporcionados por la clase Registration.java se separan del cdigo para crear y encontrar un objeto Re g is t ra t io n , que est en la clase
RegistrationHome.java.
La implementacin del interface remoto de RegistrationHome.java est unida al rm ire g is t ry . Cuando un programa cliente quiere manipular detalles del registro del usuario, primero
tiene que buscar la referencia al objeto RegistrationHome.java en el rm ire g is t ry .
Sumario de Ficheros
Todo los fciheros de cdigo fuente para el ejemplo basado en RMI se describen en la siguiente lista.
SellerBean.java: Programa cliente que llama a los mtodos remotos Re g is t ra t io n S e rv e r. v e rify p a s s w d y Re g is t ra t io n S e rv e r. fin d Lo w Cre d it Ac c o u n t s . S e lle rBe a n tambin
exporta su mtodo u p d a t e Re s u lt s que llama a Re g is t ra t io n S e rv e r cuando completa su bsqueda Re g is t ra t io n S e rv e r. fin d Lo w Cre d it Ac c o u n t s .
RegistrationServer.java: Servidor de objetos remotos que implementa los interfaces remotos Re g is t ra t io n Ho m e y Re g is t ra t io n .
Registration.java: Interface remoto que declara los mtodos remotos g e t Us e r, v e rify p a s s w d , y otros mtodos para el manejo de los detalles de registro del usuario.
RegistrationHome.java: Interface remoto que declara los mtodos remotos c re a t e , fin d By P rim a ry Ke y , y fin d Lo w Cre d it Ac c o u n t s que crean o devuelven ejemplares de detalles
de registro.
RegistrationImpl.java: El fichero fuente Re g is t ra t io n S e rv e r. ja v a incluye la implementacin para el interface remoto Re g is t ra t io n como la clase Re g is t ra t io n I m p l.
RegistrationPK.java: Clase que representa los detalles de registro de usuario usando slo la clave primaria del registro de la base de datos.
ReturnResults.java: Interface remoto que declara el mtodo u p d a t e Re s u lt s la clase S e lle rBe a n lo implementa como callback.
AuctionServlet.java: Versin modificada de la clase original Au c t io n S e rv le t conde las cuentas de registro se crean mediante llamadas directas al Re g is t ra t io n S e rv e r de RMI. El
servelt de subasta tambin llama al mtodo S e lle rBe a n . a u d it Ac c o u n t s , que devuelve una lista de los usuarios con un bajo balance en la cuenta.
El mtodo a u d it Ac c o u n t s es llamado con la siguiente URL, donde hace un simple chequeo para verificar que la peticin viene del host local.
http://phoenix.eng.sun.com:7001/
AuctionServlet?action=auditAccounts
Tambin necesitaremos un fichero de polica java.policy para conceder los permisos necesarios para ejecutar el ejemplo en plataformas Java 2.
La mayora de las aplicaciones RMI necesitan dos permisos socket, para accesos a los socket y a HTTP para especificar los puertos. Los dos permisos de threads fueron listados en una
pila cuando sea necesario por la clase Re g is t ra t io n I m p l para crear un thread interno.
En la plataforma Java 2, cuando un programa no tiene todos los permisos que necesita, la "Mquina Virtual Java" genera una pila de seguimiento que lista los permisos que necesitan
ser aadidos al fichero de polica de seguridad.
grant {
permission java.net.SocketPermission
"*:1024-65535", "connect,accept,resolve";
permission java.net.SocketPermission "*:80",
"connect";
permission java.lang.RuntimePermission
"modifyThreadGroup";
permission java.lang.RuntimePermission
"modifyThread";
};
Compilar el Ejemplo
Antes de describir el cdigo basado en RMI de las clases anteriores, aqu est la secuencia de comandos para compilar el ejemplo en las plataformas Unix y Win32:
Unix:
javac registration/Registration.java
javac registration/RegistrationPK.java
javac registration/RegistrationServer.java
javac registration/ReturnResults.java
javac seller/SellerBean.java
rmic -d . registration.RegistrationServer
rmic -d . registration.RegistrationImpl
rmic -d . seller.SellerBean
Win32:
javac registration\Registration.java
javac registration\RegistrationPK.java
javac registration\RegistrationServer.java
javac registration\ReturnResults.java
javac seller\SellerBean.java
rmic -d . registration.RegistrationServer
rmic -d . registration.RegistrationImpl
rmic -d . seller.SellerBean
Como estamos usando nuestro propio cdigo RMI, tenemos que arrancar explcitamente el RMI Registry para que el objeto S e lle rBe a n pueda encontrar los Beans remotos de
Enterprise. El Re g is t ra t io n S e rv e r usa el registro RMI para registrar o unir los Beans enterprise que pueden ser llamados de forma remota. El cliente S e lle rBe a n contacta con el
registro para buscar y obtener las referencias a los Beans Au c t io n I t e m y Re g is t ra t io n .
Como RMI permite que el cdigo y los datos sean transferidos, debemos asegurarnos que el sistema c la s s lo a d e r no carga clases extras que puedan ser enviadas errneamente al
cliente. En este ejemplo, las clases extras podran ser las clases Stub y Skel, y las clases Re g is t ra t io n S e v e r y Re g is t ra t io n I m p l, y para evitar que lo sean cuando arrancamos el
registro RMI. Como el path actual podra ser incluido automticamente, necesitamos arrancar el RMI Registry desde fuera del espacio de trabajo.
Los sigueintes comandos evitan el envo de clases extras, desconfigurando la variable CLAS S P ATH antes de arrancar el Registro RMI en el puerto 1099. Podemos especificar un puerto
diferente aadiendo el nmero de puerto de esta forma: rm ire g is t ry 4 3 2 1 &. Si cambiamos el nmero de puerto debemos poner el mismo nmero en las llamadas al cliente <lo o k u p
y al servidor re b in d .
Unix:
export CLASSPATH=""
rmiregistry &
Win32:
unset CLASSPATH
start rmiregistry
Una vez que rm ire g is t ry se est ejecutando, podemos arrancar el servidor remoto, Re g is t ra t io n S e rv e r. El programa Re g is t ra t io n S e rv e r registra el nombre re g is t ra t io n 2 con el
servidor de nombres rm ire g is t ry , y cualquier cliente puede usar este nombre para recuperar una referencia al objeto remoto, Re g is t ra t io n Ho m e .
Para ejecutar el ejemplo, copiamos las clasesRe g is t ra t io n S e rv e r y Re g is t ra t io n I m p l y las clases stub asociadas a un rea accesible de forma remota y arrancamos el programa
servidor.
Unix:
cp *_Stub.class
/home/zelda/public_html/registration
cp RegistrationImpl.class
/home/zelda/public_html/registration
cd /home/zelda/public_html/registration
java -Djava.server.hostname=
phoenix.eng.sun.com RegistrationServer
Windows:
copy *_Stub.class
\home\zelda\public_html\registration
copy RegistrationImpl.class
\home\zelda\public_html\registration
cd \home\zelda\public_html\registration
java -Djava.server.hostname=
phoenix.eng.sun.com RegistrationServer
Las siguientes propiedades se usan para configurar los clientes y servidores RMI. Estas propiedades pueden seleccionarse dentro del programa o suministrarlas como propiedades en la
lnea de comandos para la JVM.
La propiedad ja v a . rm i. s e rv e r. c o d e b a s e especifica dnde se localizan las clases accesibles pblicamente. En el servidor esto puede ser un simple fichero URL para apuntar al
directorio o fichero JAR que contiene las clases. Si el URL apunta a un directorio, debe terminar con un carcter separador de ficheros , "/".
Si no usamos un fichero URL, tampoco necesitaremos un servidor HTTP para descargar las clases remotas o tener que enviar manualmente el stub del cliente y las clases de
interfaces remotos, por ejemplo, un fichero JAR.
La propiedad ja v a . rm i. s e rv e r. h o s t n a m e es el nombre completo del host del servidor donde residen las clases con acceso pblico. Esto es slo necesario si el servidor tiene
problemas para generar por s mismo un nombre totalmente cualificado.
La propiedad ja v a . rm i. s e c u rit y . p o lic y especifica el policy file con los permisos necesarios para ejecutar el objeto servidor remoto y para acceder a la descarga de las clases del
servidor remoto.
N o t a : En la plataforma Java 2, el fichero del lado delservidor, _ S k e l. c la s s ya no es necesario porque sus funciones han sido reemplazadas por las clases de la "Java Virtual
Machine".
Colocar Datos
Colocar y descolocar los datos significa que cuando llamamos al mtodo Re g is t ra t io n Ho m e . c re a t e desde S e lle rBe a n , esta llamada es reenviada al mtodo
Re g is t ra t io n S e rv e r_ S t u b . c re a t e . El mtodo Re g is t ra t io n S e rv e r_ S t u b . c re a t e envuelve los argumentos del mtodo y los enva a un stream serializado de bytes para el mtodo
Re g is t ra t io n S e rv e r_ S k e l. c re a t e .
El
mtodo Re g is t ra t io n S e rv e r_ S k e l. c re a t e desenvuelve el stream de bytes serializado, re-crea los argumentos de la llamada original a Re g is t ra t io n Ho m e . c re a t e , y devuelve el
resultado de la llamada real Re g is t ra io n S e rv e r. c re a t e de vuelta, junto con la misma ruta, pero esta vez, se empaquetan los datos en el lado del servidor.
Colocar y descolocar los datos tiene sus complicaciones. El primer problema son los objetos serializados que podran ser incompatiles entre versiones del JDK. Un objeto serializado
tiene un identificador almacenado con el objeto que enlaza el objeto serializado con su versin. Si el cliente RMI y el servidor son incompativles con su ID de serie, podramos necesitar
generar Stubs y Skels compatibles usando la opcin - v c o m p a t del compilador rm ic .
Otro problema es que no todos los objetos son serializables por defecto. El objeto inicial Re g is t ra t io n Be a n est basado en la devolucin de un objeto En u m e ra t io n que contiene
elementos Re g is t ra t io n en un Ve c t o r. Devolver la lista desde el mtodo remoto, funciona bien, pero cuando intentamos envar un vector como un parmetro a un objeto remoto,
obtendremos una excepcin en tiempo de ejecucin en la plataforma Java 2.
Afortunadamente, en el API Collections, la plataforma Java ofrece alternativas a la descolocacin de objetos anterior. En este ejemplo, un Arra y Lis t del API Collections reemplaza el
Ve c t o r. Si el API Collections no es una opcin, podemos crear una clase envoltura que extienda S e ria liz a b le y proporcione implementaciones para los mtodos re a d Ob je c t y
w rit e Ob je c t para convertir el objeto en un stream de bytes.
La clase RegistrationServer
La clase RegistrationServer extiende ja v a . rm i. s e rv e r. Un ic a s t Re m o t e Ob je c t e implementa los mtodos c re a t e , fin d By P rim a ry Ke y y fin d Lo w Cre d it Ac c o u n t s declarados en el
interface Re g is t ra t io n Ho m e . El fichero fuente RegistrationServer.java tambin incluye la implementacin del interface remoto Re g is t ra t io n como la clase Re g is t ra t io n I m p l.
Re g is t ra t io n I m p l tambin extiende Un ic a s t Re m o t e Ob je c t .
Cualquier objeto que querramos que se accesible remotamente necesita extender el interface ja v a . rm i. s e rv e r. Un ic a s t Re m o t e Ob je c t o usar el mtodo e x p o rt Ob je c t de la clase
Un ic a s t Re m o t e Ob je c t . Si extendemos Un ic a s t Re m o t e Ob je c t , tambin obtendremos los mtodos e q u a ls , t o S t rin g y h a s h Co d e para el objeto exportado.
Aunque la clase Re g is t ra t io n I m p l no est unida al registro, todava est referenciada remotamente porque est asociada con los resultados devueltos por Re g is t ra t io n Ho m e .
Re g is t ra t io n I m p l extiende Un ic a s t Re m o t e Ob je c t , sus resultados son pasados por referencia, y slo una copia del Bean de registro del usuario existente en la Java VM a la vez.
En el caso de reportar resultados como en el mtodo Re g is t ra t io n S e rv e r. fin d Lo w Cre d it Ac c o u n t s , la clase Re g is t ra t io n I m p l se puede usar una copia del objeto remoto. Si no
extendemos la clase Un ic a s t Re m o t e Ob je c t en la definicin de la clase Re g is t ra t io n I m p l, se devolver un nuevo objeto Re g is t ra t io n en cada peticin. En efecto los valores son
pasados pero no la referencia al objeto en el servidor.
Al usar referencias remotas a objetos en el servidor desde fuera del cliente el recolector de basura del servidor introduce algunos problemas potenciales con la memoria. Cmo conoce
el servidor cuando se mantiene una referencia a un objeto Re g is t ra t io n que no est siendo usado por ningn cliente porque abort o se cay la conexin de red?
Para evitar bloqueos de memoria en el servidor desde los clientes, RMI usa un mecanismo de alquiler cuando ofrecen las referencias a los objetos exportados. Cuando se exporta un
objeto, la JVM incrementa la cuenta del nmero de referencias a este objeto y configura el tiempo de expiracin, o tiempo de prstamo, por el nmero de referencias del objeto.
Cuando el alquiler expira, la cuenta de referencias de este objeto se decrementa y si alcanza 0, el objeto es seleccionado para la recoleccin de basura por la JVM. Hay que configurar el
cliente que mantiene un pico de referencia al objeto remoto a que renueve el alquiler si necesita el objeto ms alla del tiempo de alquiler. Este pico de referencia es una forma de
referirse a un objeto en la memoria sin mantenerlo lejos del recolector de basura.
Este tiempo de alquiler es una propiedad configurable medida en segundos. Si tenemos una red rpida, podramos acortar el valor por defecto, y crear un gran nmero de referencias a
objetos transitorias.
El siguiente cdigo selecciona el tiempo de alquiler a 2 minutos.
public registration.RegistrationPK
create(String theuser,
String password,
String emailaddress,
String creditcard)
throws registration.CreateException{
// code to insert database record
}
public registration.Registration
findByPrimaryKey(registration.RegistrationPK pk)
throws registration.FinderException {
if ((pk == null) || (pk.getUser() == null)) {
throw new FinderException ();
}
return(refresh(pk));
}
if(pk == null) {
throw new FinderException ();
}
try{
con=getConnection();
ps=con.prepareStatement("select theuser,
balance from registration
where balance < ?");
ps.setDouble(1, 3.00);
ps.executeQuery();
rs = ps.getResultSet();
RegistrationImpl reg=null;
while (rs.next()) {
try{
reg= new RegistrationImpl();
}catch (RemoteException e) {}
reg.theuser = rs.getString(1);
reg.balance = rs.getDouble(2);
ar.add(reg);
}
rs.close();
client.updateResults(ar);
}catch (Exception e) {
System.out.println("findLowCreditAccounts: "+e);
return;
}
finally {
try{
if(rs != null) {
rs.close();
}
if(ps != null) {
ps.close();
}
if(con != null) {
con.close();
}
}catch (Exception ignore) {}
}
} //run
};
Thread t = new Thread(bgthread);
t.start();
}
}
El mtodo m a in carga el driver JDBC. Esta versin usa la base de datos Postgres, instala el RMI S e c u rit y Ma n a g e r, y contacta con el registro RMI para unir el objeto remoto
Re g is t ra t io n Ho m e al nombre re g is t ra t io n 2 . No necesita unir el interface remoto, Re g is t ra t io n porque la clase es cargada cuando es referenciada por Re g is t ra t io n Ho m e .
Por defecto, el servidor de nombres usa el puerto 1099. Si queremos usar un nmero de puerto diferente, podemos aadirlo con dos puntos de esta forma: k q 6 p y :4 3 2 1 . Si cambiamos
aqu el nmero de puerto, debemos arrancar el RMI Registry con el mismo nmero de puerto.
El mtodo m a in tambin instala un RMI Fa ilu re Ha n d le r. Si el servidor falla al crear el socket servidor, el manejador de fallos devuelve t ru e que instruye al servidor RMI para que
reintente la operacin.
Naming.rebind("
//phoenix.eng.sun.com/registration2",rs);
}catch (Exception e) {
System.out.println("Exception thrown "+e);
}
}
}
class RMIFailureHandlerImpl
implements RMIFailureHandler {
public boolean failure(Exception ex ){
System.out.println("exception "+ex+" caught");
return true;
}
}
Interface Registration
El interface Registration declara los mtodos implementados por Re g is t ra t io n I m p l en el fichero fuente Re g is t ra t io n S e rv e r. ja v a .
package registration;
import java.rmi.*;
import java.util.*;
Interface RegistrationHome
El interface RegistrationHome declara los mtodos implementados por la clase Re g is t ra t io n S e rv e r. Estos mtodos reflejan el interface Home definido en el ejemplo JavaBeans de
Enterprise. El mtodo fin d Lo w Cre d it Ac c o u n t s toma un interface remoto como su nico parmetro.
package registration;
import java.rmi.*;
import java.util.*;
Interface ReturnResults
El interface ReturnResults declara el mtodo implementado por la clase S e lle rBe a n . El mtodo u p d a t e Re s u lt s es llamado desde Re g is t ra t io n S e rv e r.
package registration;
import java.rmi.*;
import java.util.*;
La Clase SellerBean
La clase SellerBean incluye la implementacin del mtodo callback y llama al objeto Re g is t ra t io n S e rv e r usando RMI. El mtodo u p d a t e Ac c o u n t s se hace accesible mediante una
llamada a Un ic a s t Re m o t e Ob je c t . e x p o rt Ob je c t ( t h is ) ;. El mtodo a u d it Ac c o u n t s espera un objeto method Bo o le a n .
El mtodo u p d a t e Ac c o u n t s enva una notificacin a todos los mtodos que esperan el objeto Bo o le a n cuando ha sido llamado desde el servidor y recibe los resultados.
package seller;
import java.rmi.RemoteException;
import java.rmi.*;
import javax.ejb.*;
import java.util.*;
import java.text.NumberFormat;
import java.io.Serializable;
import javax.naming.*;
import auction.*;
import registration.*;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
try{
RegistrationHome regRef = (
RegistrationHome)Naming.lookup(
"//phoenix.eng.sun.com/registration2");
RegistrationPK rpk= new RegistrationPK();
rpk.setUser(seller);
Registration newseller = (
Registration)regRef.findByPrimaryKey(rpk);
if((newseller == null) ||
(!newseller.verifyPassword(password))) {
return(Auction.INVALID_USER);
}
AuctionItemHome home = (
AuctionItemHome) ectx.lookup(
"auctionitems");
AuctionItem ai= home.create(seller,
description,
auctiondays,
startprice,
summary);
if(ai == null) {
return Auction.INVALID_ITEM;
}else{
return(ai.getId());
}
}catch(Exception e){
System.out.println("insert problem="+e);
return Auction.INVALID_ITEM;
}
}
Oz it o
Common Object Request Broker Architecture (CORBA)
Las implementaciones de RMI y de JavaBeans Enterprise de la aplicacin de subasta usan el lenguaje Java para implementar los distintos servicios de la subasta. Sin embargo,
podramos necesitar intergrarlo con aplicaciones escritas en C, C++ u otros lenguajes y ejecutarlo en un millar de sistemas operativos y mquinas distintas.
Una forma de integracin con otras aplicciones es transmitir datos en un formato comn como caracteres de 8 bits sobre sockets TCP/IP. La desventaja es tener que gastar mucho
tiempo en derivar un mensaje de protocolo y mapeado de varias estructuras de datos hacia y desde el formato de transmisin comn para que los datos puedan ser enviados y
recibidos sobre la conexin TCP/IP.
Aqu es donde pueden ayudar el "Common Object Request Broker Architecture" (CORBA) y su "Interface Definition Language" (IDL). IDL proporciona un formato comn para
representar un objeto que puede ser distribuido a otras aplicaciones. Las otras aplicaciones podran incluso no entender de objetos, pero mientras puedan proporcionar un mapeado
entre el formato comn IDL y sus propia representacin de datos, la aplicacin podr compartir los datos.
Este captulo describe el esquema de mapeo de IDL a lenguaje Java, y cmo reemplazar el original Re g is t ra t io n Be a n basado en contenedor controlador por su equivalente servidor
CORBA. Los programas S e lle rBe a n . ja v a y Au c t io n S e rv le t . ja v a tambin se modifican para interoperar con el programa CORBA Re g is t ra t io n S e rv e r.
Esquema de Mapeo IDL
Referencia Rpida
Configurar Mapeos IDL
Otros Tipos IDL
CORBA en la Aplicacin Subasta
CORBA RegistrationServer
Fichero de Mapeos IDL
Compilar el Fichero de Mapeos IDL
Ficheros Stub y Skeleton
Object Request Broker (ORB)
Poner Disponible el Servidor CORBA
Conectar un Nuevo ORB
Acceso al Servicio de Nombres por Clientes CORBA
Clases Helper y Holder
Recoleccin de Basura
CORBA Callbacks
Usar el Tipo Any
Conclusin
Referencia Rpida
Aqu tenemos una tabla de referencia rpida de los tipos de datos del lenguaje Java y los de IDL CORBA, y las excepciones de tiempo de ejecucin que se pueden lanzar cuando la
conversin falla. Los tipos de datos de esta tabla que necesitan explicacin se cubren ms abajo.
Tip o d e D a t o Ja v a Fo rm a t o I D L Ex c e p t io n
byte octet
boolean boolean
char char DATA_CONVERSION
char wchar
double double
float float
int long
int unsigned long
long long long
long unsigned long long
short short
short unsigned short
java.lang.String string DATA_CONVERSION
java.lang.String wstring MARSHAL
Va lo re s s in S ig n o : Los tipos de datos Java: b y t e , s h o rt , in t , y lo n g estn representados por entereros de complemento a dos de 8, 16, 32 y 64 bits. Esto significa que un valor s h o rt
Java representa un rango desde -215 hasta 215 - 1 desde -32768 hasta 32767 inclusives. El tipo con signo equivalente IDL para un short, s h o rt , es igual en el rango, pero el tipo
s h o rt IDL sin signo usa el rango desde 0 hata 215 desde 0 hasta 65535.
Esto significa que en el caso de s h o rt , si un valor short sin signo mayor de 32767 es pasado a un programa escrito en Java, el valor s h o rt ser representado como un nmero
negativo. Esto puede causar confusin en los lmites de test para valores mayores que 32767 o menores que 0.
Tip o s c h a r I D L: El lenguaje Java usa un unicode de 16 Bits, pero los tipos c h a r y s t rin g de IDL son carcateres de 8 bits. Podemos mapear un c h a r Java a un c h a r IDL de 8 bits para
transmitir caracteres multi-byte si usamos un array para hacerlo. Sin embargo, el tipo de caracter ancho de IDL w c h a r est especialmente diseado para lenguajes con caracteres
multi-bytes y aloja el nmero fijo de bytes que sea necesario para contener el conjunto del lenguaje para cada una de las letras.
Cuando se mapea desde el tipo c h a r de Java al tipo c h a r de IDL, se puede lanzar la excepcin D ATA_ CON VERS I ON si el caracter no entra en los 8 bits.
Tip o s s t rin g I D L: El tipo s t rin g IDL puede ser lanzado como una secuencia de tipos c h a r IDL, tambin lanza la excepcin D ATA_ CON VERS I ON . El tipo w s t rin g IDL es equivalente a
una secuencua de w c h a rs terminada por un w c h a r N ULL.
Un tipo s t rin g y un tipo w s t rin g de IDL pueden tener un tamao fijo o sin mximo definido. Si intentamos mapear un ja v a . la n g . S t rin g a un s t rin g IDL de tamao fijo y el
ja v a . la n g . S t rin g es demasidado largo, se lanzar una excepcin MARS HAL.
El mapeo del lenguaje Java a IDL se sita en un fichero con extensin . id l. El fichero es compilado para que pueda ser accedido por los programas CORBA que necesitan enviar y recibir
datos. Esta seccin explica cmo construir los mapeos para las sentencias de paquete y los tipos de datos Java. La siguiente seccin en Implementacin CORBA de RegistrationServer
describe cmo usar esta informacin para configurar el fichero de mapeo IDL para el servidor Re g is t ra t io n CORBA.
P a q u e t e s e I n t e rfa c e s Ja v a : Las sentencias de paquete Java son equivalentes al tipo m o d u le de IDL. Este tipo puede ser anidado, lo que resulta en que las clases Java generadas se
crean en subdirectorios anidados.
Por ejemplo, si un programa CORBA contiene esta sentencia de paquete:
package registration;
el fichero de mapeo debera tener este mapeo a mdulo IDL para ella:
module registration {
};
Si un programa CORBA contiene una herencia de paquete como esta:
package registration.corba;
su mapeo IDL de mdulo ser este:
module registration {
module corba {
};
};
Las clases distribuidas estn definidas como interfaces Java y se mapean al tipo interface de IDL. IDL no define accesos como p u b lic o p riv a t e que podramos encontrar en el lenguaje
Java, pero permite descender desde otros interfaces.
Este ejemplo aade el interface Java Re g is t ra t io n a un re g is t ra t io n m o d u le IDL.
module registration {
interface Registration {
};
}
Este ejemplo aade el interface Java Re g is t ra t io n a un re g is t ra t io n m o d u le IDL, e indica que el interface Re g is t ra t io n desciende del interface Us e r.
module registration {
interface Registration: User {
};
}
M t o d o s Ja v a : Los mtodos Java se mapean a operaciones IDL. Las operaciones IDL son similares a los mtodos Java excepto en que no hay el concepto de control de acceso.
Tambin tenemos que ayudar al compilador IDL especificando qu parmetros son de entrada in , de entrada/salida in o u t o de salida o u t , definidos de esta forma:
in - El parmetro se pasa dentro del mtodo pero no se modifica.
Este mapeo IDL incluye los mtodos de los interfaces Re g is t ra t io n y Re g is t ra t io n Ho m e a operaciones IDL usando un tipo mdulo IDL.
module registration {
interface Registration {
boolean verifyPassword(in string password);
string getEmailAddress();
string getUser();
long adjustAccount(in double amount);
double getBalance();
};
interface RegistrationHome {
Registration findByPrimaryKey(
in RegistrationPK theuser)
raises (FinderException);
}
}
Arra y s Ja v a : Los Arrays Java son mapeados a los tipos a rra y o s e q u e n c e IDL usando una definicin de tipo.
Este ejemplo mapea el array Java d o u b le b a la n c e s [ 1 0 ] a un tipo a rra y IDL del mismo tamao.
exception CreateException {
};
interface RegistrationHome {
RegistrationPK create(
in string theuser,
in string password,
in string emailaddress,
in string creditcard)
raises (CreateException);
}
Estos otros tipos bsicos IDL no tienen un equivalente exacto en el lenguaje Java. Muchos de estos deberan sernos familiares si hemos usado C C++. El lenguaje Java proporciona
mapeo para estos tipos porque los programas escritos en Java pueden recibir datos desde programas escritos en C C++.
a t t rib u t e IDL
e n u m IDL
s t ru c t IDL
u n io n IDL
An y IDL
P rin c ip a l IDL
Ob je c t IDL
a t rib u t o I D L: El tipo a t t rib u t e IDL es similiar a los mtodos g e t y s e t usados para acceder a los campos en el software de JavaBeans.
En el caso de un valor declarado como un atributo IDL, el compilador IDL genera dos mtodos con el mismo nombre que el atributo IDL. Un mtodo devuelve el campo y otro lo
selecciona. Por ejemplo, este tipo a t t rib u t e :
interface RegistrationPK {
attribute string theuser;
};
define estos mtodos:
//return user
String theuser();
//set user
void theuser(String arg);
e n u m I D L: El lenguaje Java tiene una clase En u m e ra t io n para representar una coleccin de datos. El tipo e n u m IDL es diferente porque es declarado como un tipo de dato y no una
coleccin de datos.
El tipo e n u m IDL es una lista de valores que pueden se referenciados por un nombre en vez de por su posicin en la lista. En el ejemplo, podemos ver que referirnos al cdigo de
estado de un e n u m IDL por un nombre es mucho ms legible que hacerlo por su nmero. Esta lnea mapea los valores s t a t ic fin a l in t de la clase fin a l Lo g in Erro r. Podemos
referirnos a estos valores como lo haramos con un campo esttico:Lo g in Erro r. I N VALI D _ US ER.
enum LoginError {
INVALID_USER, WRONG_PASSWORD, TIMEOUT};
Aqu hay una versin del tipo e n u m que incluye un subrayado anterior para que pueda ser usado en sentencias s w it c h :
switch (problem) {
case LoginError._INVALID_USER:
System.out.println("please login again");
break;
}
s t ru c t I D L: Un tipo s t ru c t IDL puede ser comparado con una clase Java que slo tiene campos, que es cmo lo mapea el compilador IDL.
Este ejemplo declara una s t ru c t IDL. Observamos que los tipos IDL pueden referenciar otros tipos IDL. En este ejemplo Lo g in Erro r viene del tipo e n u m declarado arriba.
struct ErrorHandler {
LoginError errortype;
short retries;
};
u n io n I D L: Una u n io n IDL puede representar un tipo de una lista de tipos definidos para esa unin. La u n io n mapea a una clase Java del mismo nombre con un mtodo
d is c rim in a t o r usado para determinar el tipo de esa unin.
Este ejemplo mapea la unin Glo b a lErro rs a una clase Java con el nombre Glo b a lErro rs . Se podra aadir un case por defecto c a s e : D EFAULT para manejar cualquier elemento que
podra estar en el tipo Lo g in Erro rs e n u m , y no est especificado con una sentencia c a s e aqu.
switch (ge.discriminator().value()) {
case: LoginError._INVALID_USER:
System.out.println(ge.message);
break;
}
Tip o An y : si no sabemos que tipo est siento pasado o devuelto desde una operacin, podemos usar el tipo An y , que representa cualquier tipo IDL. La siguiente operacin retorna y
pasa un tipo desconocido:
interface RegistrationHome {
Any customSearch(Any searchField, out count);
};
Para crear un tipo An y , se pide el tipo al "Object Request Broker" (ORB). Para seleccionar un valor de un tipo An y , usamos un mtodo in s e rt _ < t y p e > . Para recuperar un valor,
usamos el mtodo e x t ra c t _ < t y p e > .
Este ejemplo pide un objeto del tipo An y , y usa el mtodo in s e rt _ t y p e para seleccionar un valor.
Esta seccin describe el fichero Registration.idl, que mapea los interfaces remotos Re g is t ra t io n Ho m e y Re g is t ra t io n desde la aplicacin de subastas de JavaBeans de Enterprise a sus
equivalentes IDL y muestra como compilar el fichero Re g is t ra t io n . id l en las clases del servidor de registos CORBA.
El servidor de registros CORBA implementa los mtodos c re a t e y fin d By P rim a ry Ke y desdel el fichero Re g is t ra t io n Be a n . ja v a original, y lo ampla con los dos mtodos siguientes
para ilustrar las retrollamadas CORBA, y como usar el tipo An y .
fin d Lo w Cre d it Ac c o u n t s ( in Re t u rn Re s u lt s rr) , que usa una callback para devolver una lista de cuentas con bajo saldo.
a n y c u s t o m S e a rc h ( in a n y s e a rc h fie ld , o u t lo n g c o u n t ) , que devuelve un resultado de bsqueda diferente dependiendo del tipo de campo enviado.
Aqu est el fichero Registration.idl que mapea los tipos de datos y mtodos usados en los programas Re g is t ra t io n Ho m e y Re g is t ra t io n a sus equivalentes IDL.
module registration {
interface Registration {
boolean verifyPassword(in string password);
string getEmailAddress();
string getUser();
long adjustAccount(in double amount);
double getBalance();
};
interface RegistrationPK {
attribute string theuser;
};
exception CreateException {
};
exception FinderException {
};
interface ReturnResults {
void updateResults(in IDLArrayList results)
raises (FinderException);
};
interface RegistrationHome {
RegistrationPK create(in string theuser,
in string password,
in string emailaddress,
in string creditcard)
raises (CreateException);
Registration findByPrimaryKey(
in RegistrationPK theuser)
raises (FinderException);
void findLowCreditAccounts(in ReturnResults rr)
raises (FinderException);
any customSearch(in any searchfield, out long count);
};
};
El fichero IDL tiene que ser convertido en clases Java que puedan ser usadas en una red distribuida CORBA. La plataforma Java 2 compila los ficheros . id l usando el programa
id lt o ja v a . Este programa ser reemplazado eventualmente con el comando id lj.
Los argumentos - fn o - c p p indican que no hay compilador C++ instalado.
Stubs y Skeletons
Corba y RMI son similares en que la compilacin genera un fichero stub para el cliente y un fichero skeleton para el servidor. El stub (o proxy), y el skeleton (o sirviente) se usan para
envolver o desenvolver datos entre el cliente y el servidor. El skeleton (o sirviente) est implementado mediante el servidor. En este ejemplo, el interface Re g is t ra t io n Ho m e genera
una clase _ Re g is t ra t io n Ho m e I m p lBa s e (la clase skeleton o sirviente) que extiende la clase Re g is t ra t io n S e rv e r generada.
Cuando se solicita un objeto CORBA remoto o se llama a un mtodo remoto, la llamada del cliente pasa a travs de la clase stub antes de alcanzar el servidor. Este clase proxy invoca la
peticin CORBA para el programa cliente. El siguiente ejemplo es el cdigo generado automticamente por la clase Re g is t ra t io n Ho m e S t u b . ja v a .
org.omg.CORBA.Request r = _request("create");
r.set_return_type(
registration.RegistrationPKHelper.type());
org.omg.CORBA.Any _theuser = r.add_in_arg();
orb.disconnect(rs);
Una vez conectado a un objeto servidor CORBA, el ORB Java2 mantiene vivo el servidor y espera peticiones del cliente para el servidor CORBA.
Aunque este objeto est ahora siendo mapeado por el ORB, los clientes todava no tienen el mecanismo para encontrar el objeto remoto. Esto puede resolverse uniendo el objeto
servidor CORBA a un servicio de nombres.
El servicio de nombres Java 2 llamado t n a m e s e rv , por defecto usa el puerto 900; sin embargo, este valor puede modificarse seleccionado el argumento - ORBI n it ia lP o rt p o rt n u m b e r
cuando se arranca t n a m e s e rv o seleccionando la propiedad o rg . o m g . CORBA. ORBI n it ia lP o rt cuando arrancamos los procesos cliente y servidor.
Las siguientes secciones describen el mtodo m a in de la clase Re g is t ra t io n S e rv e r.
java.util.Properties props=System.getProperties();
props.put("org.omg.CORBA.ORBInitialPort", "1050");
System.setProperties(props);
ORB orb = ORB.init(args, props);
Las siguientes lneas muestran que la referencia inicial de nombres es inicializada por la peticin del servicio llamado N a m e S e rv ic e . El N a m in g Co n t e x t es recuperado y el nombre
construido y unido al servicio de nombres como elementos N a m e Co m p o n e n t . El nombre de este ejemplo tiene una raz llamada a u c t io n que es este objeto que se est uniendo como
Re g is t ra t io n Be a n desde la raz a u c t io n . El nombre podra ser comparado por una clase mediante el nombre de a u c t io n . Re g is t ra t io n Be a n .
org.omg.CORBA.Object nameServiceObj =
orb.resolve_initial_references("NameService") ;
NamingContext nctx =
NamingContextHelper.narrow(nameServiceObj);
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
El ORB IDL de Java 2 realmente no incluye ninguno de los servicios disponibles en muchos otros ORBs comerciales como los servicios de seguridad o eventos (notificacin). Podemos
usar otro ORB en el runtime de Java 2 configurando dos propiedades e incluyendo cualquier codigo de objeto adaptador que sea necesario.
Usar un nuevo ORB en el servidor de registros requiere que las propiedades o rg . o m g . CORBA. ORBCla s s y o rg . o m g . CORBA. ORBS in g le t o n Cla s s apunten a las clases ORB
apropiadas. En este ejemplo se usa el ORB ORBacus en lugar del ORB IDL de Java 2. Para usar otro ORB, el cdigo de abajo debera conectarse dentro del mtodo
Re g is t ra t io n S e rv e r. m a in .
En el cdigo de ejemplo, se usa un ORB S in g le t o n Cla s s . Este ORB no es un ORB completo, y su uso primario es como factora para Ty p e Co d e s . La llamada a ORB. in it ( ) en la ltima
lnea crea el ORB Singleton.
java registration.RegistrationServer
-ORBservice NameService
iiop://localhost:1060/DefaultNamingContext
Los cliente CORBA acceden al servicio de nombres de una forma similar a como lo hace el servidor, excepto que en lugar de unir un nombre, el cliente resuelve el nombre construido
desde el N a m e Co m p o n e n t s .
Las clases Au c t io n S e rv le t y S e lle rBe a n usan el siguiente cdigo para buscar el servidor CORBA:
RegistrationHome regRef =
RegistrationHomeHelper.narrow(
nctx.resolve(fullname));
En el caso del ORB ORBacus, los clientes tambin necesitan un "Basic Object Adapter" si se usan retrollamadas en el mtodo S e lle rBe a n . a u d it Ac c o u n t s . El contexto de nombrado
tambin se configura de forma diferente para el servidor ORBacus arrancado anteriormente:
Object obj =
((com.ooc.CORBA.ORB)orb).get_inet_object (
"localhost",
1060,
"DefaultNamingContext");
NamingContext nctx = NamingContextHelper.narrow(obj);
Recoleccin de Basura
Al contrario que RMI, CORBA no tiene un mecanismo de recoleccin de basura distribuido. Las referencias a un objeto son locales al proxy del cliente y al sirviente del servidor. Esto
significa que cada Mquina Virtual Java1 (JVM) es libre de reclamar un objeto y recoger la basura si no tiene ms referencias sobre l. Si un objeto no es necesario en el servidor,
necesitamos llamar a o rb . d is c o n n e c t ( o b je c t ) para permitir que el objeto sea recolectado.
//AuctionServlet.java
private void auditAccounts(ServletOutputStream out,
HttpServletRequest request) throws IOException{
// ...
if(si != null) {
ArrayList ar=si.auditAccounts();
for(Iterator i=ar.iterator(); i.hasNext();) {
Registration user=(Registration)(i.next());
addLine("<TD>"+user.getUser() +
"<TD><TD>"+user.getBalance()+
"<TD><TR>", out);
}
addLine("<TABLE>", out);
}
El objeto S e lle rBe a n llama al mtodo CORBA Re g is t ra t io n Ho m e . fin d Lo w Cre d it Ac c o u n t s implementado en el fichero Re g is t ra t io n S e rv e r. ja v a , y se pasa una referencia a s
mismo. La referencia es pasada siempre que la clase S e lle rBe a n implemente el interface Re t u rn Re s u lt s declarado en el Re g is t ra t io n . id l.
//SellerBean.java
public ArrayList auditAccounts() {
try{
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
RegistrationHome regRef =
RegistrationHomeHelper.narrow(
nctx.resolve(fullname));
regRef.findLowCreditAccounts(this);
synchronized(ready) {
try{
ready.wait();
}catch (InterruptedException e){}
}
return (returned);
}catch (Exception e) {
System.out.println("error in auditAccounts "+e);
}
return null;
}
El mtodo Re g is t ra t io n S e rv e r. fin d Lo w Cre d it Ac c o u n t s recupera los registros de usuario desde la tabla Registration de la base de datos que tengan un valor de crdito menor de
tres. Entonces devuelve la lista de registros Registration en un Arra y Lis t llamando al mtodo S e lle rBe a n . u p d a t e Re s u lt s que tiene una referencia a ella.
//RegistrationServer.java
public void findLowCreditAccounts(
final ReturnResults client)
throws Finder Exception {
Runnable bgthread = new Runnable() {
public void run() {
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
ArrayList ar = new ArrayList();
try{
con=getConnection();
ps=con.prepareStatement(
"select theuser,
balance from registration
where balance < ?");
ps.setDouble(1, 3.00);
ps.executeQuery();
rs = ps.getResultSet();
RegistrationImpl reg=null;
while (rs.next()) {
try{
reg= new RegistrationImpl();
}catch (Exception e) {
System.out.println("creating reg"+e);
}
reg.theuser = rs.getString(1);
reg.balance = rs.getDouble(2);
ar.add(reg);
}
rs.close();
RegistrationImpl[] regarray =
(RegistrationImpl [])ar.toArray(
new RegistrationImpl[0]);
client.updateResults(regarray);
}catch (Exception e) {
System.out.println(
"findLowCreditAccounts: "+e);
return;
}
finally {
try{
if(rs != null) {
rs.close();
}
if(ps != null) {
ps.close();
}
if(con != null) {
con.close();
}
}catch (Exception ignore) {}
}
}//run
};
Thread t = new Thread(bgthread);
t.start();
}
El mtodo S e lle rBe a n . u p d a t e Re s u lt s actualiza el Arra y Lis t global de registros de Registration devuelto por el objeto Re g is t ra t io n S e rv e r y notifica al mtodo
S e lle rBe a n / a u d it Ac c o u n t s que puede devolver este Arra y Lis t de registros Registration al Au c t io n S e rv le t .
http://localhost.eng.sun.com:7001/
AuctionServlet?action=customSearch&searchfield=2
El parmetro s e a rc h fie ld puede ser seleccionado como un nmero o un string. El mtodo Au c t io n S e rv le t . c u s t o m Fin d pasa el campo de bsqueda directamente al mtodo
S e lle rBe a n . c u s t o m Fin d que recupera un S t rin g que luego es mostrado al usuario:
//SellerBean.java
public String customFind(String searchField)
throws javax.ejb.FinderException,
RemoteException{
int total=-1;
IntHolder count= new IntHolder();
try{
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
RegistrationHome regRef =
RegistrationHomeHelper.narrow(
nctx.resolve(fullname));
if(regRef == null ) {
System.out.println(
"cannot contact RegistrationHome");
throw new javax.ejb.FinderException();
}
Any sfield=orb.create_any();
Double balance;
try{
balance=Double.valueOf(searchField);
try {
sfield.insert_double(balance.doubleValue());
}catch (Exception e) {
return("Problem with search value"+balance);
}
sfield=regRef.customSearch(sfield,count);
if(sfield != null ) {
total=sfield.extract_long();
}
return(total+"
accounts are below optimal level from" +
count.value+" records");
}catch (NumberFormatException e) {
sfield.insert_string(searchField);
Registration reg;
if((reg=RegistrationHelper.extract(
regRef.customSearch(
sfield,count)))
!= null ) {
return("Found user "+reg.getUser() +"
who has email address "+
reg.getEmailAddress());
}else {
return("No users found who have email address " +
searchField);
}
}
}catch(Exception e){
System.out.println("customFind problem="+e);
throw new javax.ejb.FinderException();
}
}
El valor devuelto desde la llamada a c u s t o m Fin d se extrae dentro de un objeto del tipo An y y se construye un S t rin g con la salida mostrada al usuario. Para los tipos sencillos se
puede usar el mtodo e x t ra c t _ < t y p e > de An y . Sin embargo, para el tipo Re g is t ra t io n , se usa la clase Re g is t ra t io n He lp e r.
Registration reg =
RegistrationHelper.extract(
regRef.customSearch(sfield,count))
El mtodo Re g is t ra t io n S e rv e r. c u s t o m S e a rc h determina el tipo del objeto que est siendo pasado en el parmetro s e a rc h Fie ld chequeando el . t y p e ( ) . k in d ( ) . v a lu e ( ) del objeto
An y .
if(searchField.type().kind().value() ==
TCKind._tk_double)
Finalmente, como el mtodo c u s t o m S e a rc h devuelve un objeto del tipo An y , se requiere una llamada a o rb . c re a t e _ a n y ( ) . Para tipos sencillos como d o u b le , se usa el mtodo
in s e rt _ < t y p e > . Para el tipo Registration , se usa la clase Re g is t ra t io n He lp e r: Re g is t ra t io n He lp e r. in s e rt ( re t u rn Re s u lt s , re g a rra y [ 0 ] ) .
//RegistrationServer.java
public Any customSearch(Any searchField,
IntHolder count){
Any returnResults= orb.create_any();
int tmpcount=count.value;
if(searchField.type().kind().value() ==
TCKind._tk_double){
// return number of balances greater
// than supplied amount
double findBalance=searchField.extract_double();
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
try{
con=getConnection();
ps=con.prepareStatement("select count(*) from
registration where balance < ?");
ps.setDouble(1, findBalance);
ps.executeQuery();
rs = ps.getResultSet();
if(rs.next()) {
tmpcount = rs.getInt(1);
}
count.value=tmpcount;
rs.close();
}catch (Exception e) {
System.out.println("custom search: "+e);
returnResults.insert_long(-1);
return(returnResults);
}
finally {
try{
if(rs != null) { rs.close(); }
if(ps != null) { ps.close(); }
if(con != null) { con.close(); }
} catch (Exception ignore) {}
}
returnResults.insert_long(tmpcount);
return(returnResults);
}else if(searchField.type().kind().value() ==
TCKind._tk_string) {
// return email addresses that match supplied address
String findEmail=searchField.extract_string();
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
ArrayList ar = new ArrayList();
RegistrationImpl reg=null;
try{
con=getConnection();
ps=con.prepareStatement("select theuser,
emailaddress from registration
where emailaddress like ?");
ps.setString(1, findEmail);
ps.executeQuery();
rs = ps.getResultSet();
while (rs.next()) {
reg= new RegistrationImpl();
reg.theuser = rs.getString(1);
reg.emailaddress = rs.getString(2);
ar.add(reg);
}
rs.close();
RegistrationImpl[] regarray =
(RegistrationImpl [])ar.toArray(
new RegistrationImpl[0]);
RegistrationHelper.insert(
returnResults,
regarray[0]);
return(returnResults);
}catch (Exception e) {
System.out.println("custom search: "+e);
return(returnResults);
}
finally {
try{
if(rs != null) { rs.close(); }
if(ps != null) { ps.close(); }
if(con != null) { con.close(); }
} catch (Exception ignore) {}
}
}
return(returnResults);
}
Conclusin
Como hemos podido ver, convertir una aplicacin para que use RMI o CORBA requiere muy pocos cambios en el corazn del programa. La principal diferencia ha sido la inicializacin y
el servicio de nombres. Mediante la abstraccin de estas dos reas en nuestra aplicacin fuera de la lgica del negocio podemos migrar fcilmente entre diferentes arquitecturas de
objetos distribuidos.
_______
1 Cuando se usan en toda esta site, los trminos, "Java virtual machine" o "JVM" significa una mquina virtual de la plataforma Java.
Oz it o
JDBC
La aplicacin de subasta con JavaBeans Enterpise y con sus dos variantes de
"Remote Method Invocation" (RMI) y "Common Object Request Broker" (CORBA)
han usado llamadas sencillas de JDBC JDBCTM para actualizar y consultar
informacin desde una base de datps usando una conexin JDBC. Por defecto, el
acceso a bases de datos JDBC implica abrir una conexin con la base de datos,
ejecutar comandos SQL en un sentencia, procesar los datos devueltos y cerrar la
conexin con la base de datos.
En conjunto, la aproximacin por defecto funciona bien para bajos volmenes de
acceso a la base de datos, pero cmo podemos manejar un gran nmero de
peticiones que actualizan muchas tablas relacionadas a la vez y an as asegurar la
integridad de los datos? Esta seccin explica cmo hacerlo con los siguientes
tpicos:
Drivers JDBC
Drivers JDBC
La conexin con la base de datos est manejada por la clase Driver JDBC. El SDK
de Java contiene slo un driver JDBC, un puente jd b c - o d b c que comunica con un
driver "Open DataBase Conectivity" (ODBC) existente. Otras bases de datos
necesitan un driver JDBC espcifico para esa base de datos.
Para obtener un idea general de lo que hacer un driver JDBC, podemos examinar el
fichero JD CCo n n e c t io n D riv e r. ja v a . La clase JDCConnectionDriver implemta la
clase ja v a . s q l. D riv e r y acta como un driver "pass-through" re-enviando
peticiones JDBC al driver JDBC real de la base de datos. La clase driver JDBC se
carga con un llamada a Cla s s . fo rN a m e ( d riv e rn a m e ) .
Estas lneas de cdigo muestran cmo cargar tres clases diferentes de drivers
JDBC:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Class.forName("postgresql.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");
Cada driver JDBC est configurado para entender una URL especfica, por eso se
pueden cargar varios drivers JDBC a la vez. Cuando especificamos una URL en el
momento de la conexin, se selecciona el primer driver JDBC que corresponda.
El puente jdbc-odbc acepta URLS que empiecen con jd b c :o d b c : y usa el siguiente
campo de esa URL para especificar el nombre de la fuente de los datos. Este
nombre identifica el esquema de la base de datos particular a la que queremos
acceder. La URL tambin puede incluir ms detalles sobre cmo contactyar con la
base de datos e introducir la cuenta.
String url =
"jdbc:mysql://localhost/ejbdemo?user=user;
password=pass";
Los drivers JDBC se dividen en cuatro tipos. Tambin se pueden categorizar como
puro java o drivers pequeos para indicar si son usados por aplicaciones clientes
(drivers puro java) o por applets (drivers pequeos).
Los drivers JDBC del tipo 1 son drivers puente como el puente jdbc.odbc. Estos
drivers utilizan un intermediario como el ODBC para transferir las llamadas SQL a
la base de datos. Los drivers puente cuentan con cdigo nativo, aunque la librera
de cdigo nativo del puente jdbc-odbc forma parte de la Mquina Virtual Java 21.
Los drivers del tipo 2 usan el API existente de la base de datos para comunicarla
con el cliente. Aunque los drivers del tipo 2 son ms rpidos que los del tipo 1, los
del tipo 2 usan cdigo nativo y requieren permisos adicionales para funcionar en un
applet.
Un driver del tipo 2 podra necesitar cdigo de base de datos en el lado del cliente
para conectar a travs de la red.
Los Drivers del tipo 3 llaman al API de la base de datos en el servidor. Las
peticiones JDBC desde el cliente son primero comprobadas por el Driver JDBC en el
servidor para ejecutarse. Los drivers del tipo 3 y 4 pueden usarse en clientes
applets ya que no necesitan cdigo nativo.
DriverManager.setLogStream(System.out);
La seccin Connection Pooling en el captulo 8 muestra cmo podemos mejorar las
conexin JDBC sin cerrrar la conexin una vez completada la sentencia. Cada
conexin JDBC a una base de datos provoca una sobrecarga al abrir un nuevo
socket y usar el nombre de usuario y la password para login en la base de datos.
La reutilizacin de las conexiones reduce la sobrecarga. Las colas de Conexiones
mantienen una lista de conexiones abiertas y limpia cualquier conexin que no
pueda ser reutilizada.
Sentencias
Hay tres tipos bsicos de sentencias SQL usadas en el API JDBC:
Ca lla b e lS t a t e m e n t , S t a t e m e n t , y P re p a re d S t a t e m e n t . Cuando se enva una
sentencias S t a t e m e n t o P re p a re d S t a t e m e n t a la base de datos, el driver la
traduce a un formato que la base de datos pueda reconocer.
Sentencias Callable
Una vez que hemos establecido una conexin con una base de datos, podemos
usar el mtodo Co n n e c t io n . p re p a re Ca ll para crear una sentencia callable. Estas
sentencias nos permite ejecutar prodecimientos almacenados SQL.
El siguiente ejemplo crea un objeto Ca lla b le S t a t e m e n t con tres parmetros para
almacenar informacin de la cuenta de login:
CallableStatement cs =
con.prepareCall("{call accountlogin(?,?,?)}");
cs.setString(1,theuser);
cs.setString(2,password);
cs.registerOutParameter(3,Types.DATE);
cs.executeQuery();
Date lastLogin = cs.getDate(3);
Statements
String updateString =
"INSERT INTO dba VALUES (some text)";
int count = stmt.executeUpdate(updateString);
Setencias Prepared
pstmt.setString(1, anotherEmailAddress);
PreparedStatement ps = con.prepareStatement(
"insert into registration(theuser, password,
emailaddress, creditcard,
balance) values (
?, ?, ?, ?, ?)");
ps.setString(1, theuser);
ps.setString(2, password);
ps.setString(3, emailaddress);
ps.setString(4, creditcard);
ps.setDouble(5, balance);
ps.executeUpdate();
Hoja de Resultados
El interface Re s u lt S e t maneja accesos a datos devueltos por una consulta. Los
datos devueltos son igual a una lnea de la base de la tabla de la base de datos.
Algunas consultas devuelven una lnea, mientras que muchas consultas devuelven
mltiples lneas de datos.
Se utilizan los mtodos g e t Ty p e para recuperar datos desde columnas especficas
para cada fila devuelta en la consulta. Este ejemplo recupera la columna TEXT de
todas las tablas con una columna TEXT en la base de datosd b a . El mtodo
re s u lt s . n e x t mueve hasta la siguiente fila recuperada hasta que se hayan
procesado todas las filas devueltas:
rs.first();
updateDouble("balance",
rs.getDouble("balance") - 5.00);
Insertar una nueva fila usa los mismos mtodos u p d a t e < t y p e > . La nica
diferencia es que se llama al mtodo rs . m o v e To I n s e rt Ro w de que los datos
hayan sido inicializados y despus se llama a rs . in s e rt Ro w ( ) . Podemos borrar la
fila actual con una llamada a rs . d e le t e Ro w ( ) .
Trabajos Batch
Muchas bases de datos pueden almacenar datos binarios como parte de una fila si
el campo es asignado como lo n g ra w , lo n g v a rb in a ry , u otro tipo similar. Esto
campos pueden ocupar hasta 2 Gigabytes de datos. Esto significa que podemos
convertir los datos en un stram binario o un array de bytes, puede ser almacenado
o recuperado desde una base de datos como lo sera un string o un double.
Esta tcnica peude usarse para almacenar y recuperar imgenes y objetos Java.
Alm a c e n a r y re c u p e ra r u n a im a g e n : Es muy fcil almacenar un objeto que
puede ser serializado o convertido en un array de bytes. Desafortunadamente
ja v a . a w t . I m a g e no es S e ria liz a b le . Sin embargo, como se ve en el siguiente
ejemplo de cdigo, podemos almacenar los datos de la imagen en un fichero y
almacenar la informacin del fichero como bytes en un campo binario de la base de
datos.
int itemnumber=400456;
int itemnumber=400456;
byte[] imageBytes;
Image auctionimage =
Toolkit.getDefaultToolkit().createImage(
imageBytes);
Alm a c e n a r y Re c u p e ra r u n Ob je t o : Una clase puede ser serializada a un campo
binario de la base de datos de la misma forma que se hizo con la imagen en el
ejemplo anterior. En este ejemplo, la clase Re g is t ra t io n I m p l se ha modificado
para soportar la serializacin por defecto aadiendole im p le m e n t s S e ria liz a b le a
la declaracin de la clase.
Luego, se crea un array By t e Arra y I n p u t S t re a m para pasarlo como un Stream
Binario a JDBC. Para crear el By t e Arra y I n p u t S t re a m , Re g is t ra t io n I m p l primero
pasa a travs de un Ob je c t Ou t p u t S t re a m hacia el By t e Arra y I n p u t S t re a m con
una llamada a Re g is t ra t io n I m p l. w rit e Ob je c t . Luego el By t e Arra y I n p u t S t re a m
es convertido a un array de bytes, que puede ser utilizado para crear el
By t e Arra y I n p u t S t re a m . El mtodo c re a t e en Re g is t ra t io n S e rv e r. ja v a se ha
modificado de esta forma:
double balance=0;
Connection con = null;
PreparedStatement ps = null;;
try {
con=getConnection();
RegistrationImpl reg= new RegistrationImpl();
reg.theuser = theuser;
reg.password = password;
reg.emailaddress = emailaddress;
reg.creditcard = creditcard;
reg.balance = balance;
ByteArrayOutputStream regStore =
new ByteArrayOutputStream();
ObjectOutputStream regObjectStream =
new ObjectOutputStream(regStore);
regObjectStream.writeObject(reg);
byte[] regBytes=regStore.toByteArray();
regObjectStream.close();
regStore.close();
ByteArrayInputStream regArrayStream =
new ByteArrayInputStream(regBytes);
ps=con.prepareStatement(
"insert into registration (
theuser, theclass) values (?, ?)");
ps.setString(1, theuser);
ps.setBinaryStream(2, regArrayStream,
regBytes.length);
if (ps.executeUpdate() != 1) {
throw new CreateException ();
}
RegistrationPK primaryKey =
new RegistrationPKImpl();
primaryKey.theuser(theuser);
return primaryKey;
} catch (IOException ioe) {
throw new CreateException ();
} catch (CreateException ce) {
throw ce;
} catch (SQLException sqe) {
System.out.println("sqe="+sqe);
throw new CreateException ();
} finally {
try {
ps.close();
con.close();
} catch (Exception ignore) {
}
}
}
El objeto es recuperado y resconstruido extrayendo los bytes desde la base de
datos, creando un By t e Arra y I n p u t S t re a m desde aquellos bytes ledos desde un
Ob je c t I n p u t S t re a m , y llamando a re a d Ob je c t para crear de nuevo el ejemplar.
El siguiente ejemplo muestra los cambios necesarios en el mtodo
Re g is t ra t io n S e rv e r. re fre s h para recuperar el ejemplar Registration desde la
base de datos.
if (pk == null) {
throw new FinderException ();
}
Connection con = null;
PreparedStatement ps = null;
try {
con=getConnection();
ps=con.prepareStatement("
select theclass from
registration where theuser = ?");
ps.setString(1, pk.theuser());
ps.executeQuery();
ResultSet rs = ps.getResultSet();
if(rs.next()){
byte[] regBytes = rs.getBytes(1);
ByteArrayInputStream regArrayStream =
new ByteArrayInputStream(regBytes);
ObjectInputStream regObjectStream =
new ObjectInputStream(
regArrayStream);
RegistrationImpl reg=
(RegistrationImpl)
regObjectStream.readObject();
return reg;
}
else {
throw new FinderException ();
}
} catch (Exception sqe) {
System.out.println("exception "+sqe);
throw new FinderException ();
}
finally {
try {
rs.close();
ps.close();
con.close();
}
catch (Exception ignore) {}
}
}
BLOBs y CLOBs : Almacenar grandes campos en un tabla con otros datos no es
necesariamente el lugar ptimo especialmente si los datos tienen un tamao
variable. una forma de manejar objetos de tamao grande y variable es con el tipo
"Large Objects" (LOBs). Este tipo usa un localizador, esencialmente un puntero, en
el registro de la base de datos que apunta al campo real en la base de datos.
Hay dos tipos de LOBs: "Binary Large Objects" (BLOBs) y "Character Large
Objects" (CLOBs). Cuando accedemos a BLOB o CLOB, los datos no se copian en el
cliente. Para recuperar los datos reales desde una hoja de resultados, tenemos que
recuperar el puntero con una llamada a BLOB b lo b = g e t Blo b ( 1 ) o CLOB
c lo b = g e t Clo b ( 1 ) , y luego recuperar los datos con una llamada a
b lo b . g e t Bin a ry S t re a m ( ) o c lo b . g e t Bin a ry S t re a m ( ) .
Controlar Transaciones
Por defecto, las sentencias JDBC son procesadas en el modo full auto-commit. Este
modo funciona bien para una sola consulta a la base de datos, pero si la operacin
depende de varias sentencias de la base de datos que todas deben completarse
con xito o toda la operacin ser cancelada, se necesita una transacin ms
adecuada.
Una descripcin de los niveles de aislamiento en la transacinse cubre con ms
detalles en el Captulo 3: Manejao de Datos y Transaciones. Para usar control de
transaciones en la plataforma JDBC, primero necesitamos desactivar el moco "full
auto-commit" llamando a:
PreparedStatement ps = null;
try {
con=getConnection();
con.setAutoCommit(false);
stmt= con.createStatement();
stmt.executeQuery(
"select counter from auctionitems");
ResultSet rs = stmt.getResultSet();
if(rs.next()) {
count=rs.getInt(1);
}
Calendar currenttime=Calendar.getInstance();
java.util.Date currentdate=currenttime.getTime();
startdate=new java.sql.Date(
currentdate.getTime());
currenttime.add(Calendar.DATE, auctiondays);
enddate=new java.sql.Date((
currenttime.getTime()).getTime());
ps=con.prepareStatement(
"insert into auctionitems(
id, description, startdate, enddate,
startprice, summary)
values (?,?,?,?,?,?)");
ps.setInt(1, count);
ps.setString(2, description);
ps.setDate(3, startdate);
ps.setDate(4, enddate);
ps.setDouble(5, startprice);
ps.setString(6, summary);
ps.executeUpdate();
ps.close();
ps=con.prepareStatement(
"update registration
set balance=balance -0.50
where theuser= ?");
ps.setString(1, seller);
ps.close();
stmt= con.createStatement();
stmt.executeQuery(
"select balance from registration
where theuser='"+seller+"'");
rs = stmt.getResultSet();
if(rs.next()) {
balance=rs.getDouble(1);
}
stmt.close();
if(balance <0) {
con.rollback();
con.close();
return (-1);
}
stmt= con.createStatement();
stmt.executeUpdate(
"update auctionitems set
counter=counter+1");
stmt.close();
con.commit();
con.close();
return(0);
} catch(SQLException e) {
try {
con.rollback();
con.close();
stmt.close();
ps.close();
}catch (Exception ignore){}
}
return (0);
}
Caracteres de Escape
El API JDBC proporciona la palabr clave e s c a p e para que podamos especificar el
caracter que querramos usar como caracter de escape. Por ejemplo, si queremos
usar el signo de tanto por ciento (% ) como el smbolo de tanto por ciento que que
no se interprete como un comodn SQL usando en consultas SQL LI KE, tenemos
que escaparlo con el caracter de escape que especifiquemos con la palabra clave
e s cape .
La siguiente sentencia muestra cmo podemos usar la palabra clave e s c a p e para
buscar por el valor 1 0 % :
stmt.executeQuery(
"select tax from sales where tax like
'10\%' {escape '\'}");
Si nuestro programa almacena nombres y direcciones en la base de datos
introducidos desde la lnea de comandos o desde un interface de usuario, el
smbolo de comilla simple (') podra aparecer en los datos. Pasar una comilla
simple directamente a un string SQL causa problemas cuando la sentencia es
analizada porque SQL le da a este smbolo otro significado a menos que se le
escape.
Para resolver este problem, el siguiente mtodo escapa cualquier smbolo '
encontrado en la lnea de entrada. Este mtodo puede ser extendido para escapar
cualquier otro caracter como las comas , que la base de datos o su driver podran
interpretar de otra forma:
stmt.executeQuery(
"select tax from sales where tax like
'10\%' {escape '\'}");
Podramos usar esta lnea:
preparedstmt = C.prepareStatement(
"update tax set tax = ?");
int count=0;
Connection con=getConnection();
Statement stmt= con.createStatement();
stmt.executeQuery(
"select counter from auctionitems");
ResultSet rs = stmt.getResultSet();
if(rs.next()) {
if(rs.getMetaData().getColumnType(1) ==
Types.INTEGER) {
Integer i=(Integer)rs.getObject(1);
count=i.intValue();
}
}
rs.close();
Calendar currenttime=Calendar.getInstance();
java.sql.Date startdate=
new java.sql.Date((
currenttime.getTime()).getTime());
Tambin podemo usar la clase ja v a . t e x t . S im p le D a t e Fo rm a t para hacer la
conversin. Este ejemplo usa la clase ja v a . t e x t . S im p le D a t e Fo rm a t para
convertir un objeto ja v a . u t il. D a t e a un objeto ja v a . s q l. D a t e :
SimpleDateFormat template =
new SimpleDateFormat("yyyy-MM-dd");
java.util.Date enddate =
new java.util.Date("10/31/99");
java.sql.Date sqlDate =
java.sql.Date.valueOf(
template.format(enddate));
Si encontramos que una representacin de fecha de una base de datos no puede
ser mapeada a un tipo Java con una llamada a g e t Ob je c t o g e t D a t e ,
recuperamos el valor con una llamada a g e t S t rin g y formateamos el string como
un valor D a t e usando la clase S im p le D a t e Fo rm a t mostrada arriba.
_______
1 Cuando se usan en toda esta site, los trminos, "Java virtual machine" o "JVM"
significa una mquina virtual de la plataforma Java.
Oz it o
Servlets
Un servelt es un programa del lado del servidor escrito en lenguaje Java que
interacta con clientes y que normalmente est unido a unservidor de "HyperText
Transfer Protocol" (HTTP). Uno uso comn para un servlet es ampliar un servidor
web proporcionando contenidos web dinmicos.
Los servelts tienen la ventaja sobre otras tecnologas que de estn compilados,
tienen capacidad de threads interna, y proporcionan un entorno de programacin
seguro. Incluso las sites web que antes no proporcionaban soporte para servlets,
pueden hacerlo ahora usando programas como JRun o el mdulo Java para el
servidor Web Apache.
La aplicacin subastas basada en web usa un servelt para aceptar y procesar
entradas del comprador y vendedor a travs del navegador y devuelve
dinmicamente informacin sobre el tem de la subasta hacia el navegador. El
programa Au c t io n S e rv le t se creo extendiendo la clase Ht t p S e rv le t . Esta clase
proporciona un marco de trabajo para manejar peticiones y respuestas HTTP.
Esta seccin examina el Au c t io n S e rv le t e incluye informacin sobre cmo usar
objetos Co o k ie y S e s s io n en un servlet.
HttpServlet
El mtodo init
El mtodo destroy
El mtodo service
Peticiones HTTP
Usar Cookies en Servlets
Configurar una Cookie
Recuperar una Cookie
Generar Sesiones
Evitar el Cach Redireccionamiento
Cdigos de Error HTTP
Leer valores GET y POST
Threads
HTTPS
HttpServlet
La clase AuctionServlet extiende la clase Ht t p S e rv le t , que es una clase
abastracta.
El mtodo init
El mtodo in it slo se llama una vez por el servidor web cuando se arranca el
servlet por primera vez. A este mtodo se le pasa un objeto S e rv le t Co n fig que
contiene la informacin de inicializacin perteniente al servidor web donde se est
ejecutando la aplicacin.
El objeto S e rv le t Co n fig es usado para acceder a la informacin mantenida por el
servidor web incluyendo valores del parmetro in it Arg s en el fichero de
propiedades del servlet. El cdigo del mtodo in it usa el objeto S e rv le t Co n fig
para recuperar los valores de in it Arg s llamando al mtodo
c o n fig . g e t I n it P a ra m e t e r( "p a ra m e t e r") .
El mtodo Au c t io n S e rv le t . in it tambin contacta con el servidor de JavaBeans
Enterprise para crear un objeto contexto (c t x ). Este objeto e susado en el mtodo
s e rv ic e para establecer una conexin con el servidor de JavaBeans Enterprise.
Context ctx=null;
private String detailsTemplate;
El mtodo destroy
El mtodo d e s t ro y es un mtodo de ciclo de vida implementado por servlets que
necesitan grabar su estado entre cargas y descargas del servlet. Por ejemplo, el
mtodo d e s t ro y podra gabar el estado actual del servlet, y la siguiente vez que el
servlet sea cargado, el estado grabado podra ser recuperado por el mtodo in it .
Deberamos tener cuidado con que no se podra haber llamado al mtodo d e s t ro y
si la mquina servidor se bloquea.
El mtodo service
El Au c t io n S e rv le t es un servlet HTTP que maneja peticiones de clientes y genera
respuestas a travs de su mtodo s e rv ic e . Acepta como parmetros los objetos de
peticin y respuesta Ht t p S e rv le t Re q u e s t y Ht t p S e rv le t Re s p o n s e .
Ht t p S e rv le t Re q u e s t conteine las cabeceras y los streams de entrada desde
el cliente hacia el servidor.
Ht t p S e rv le t Re s p o n s e es el stream de salida que se utiliza para enviar
informacin de vuelta desde el servidor hacia el cliente.
El mtodo s e rv ic e maneja peticiones HTTP estndars del cliente recibidas
mediante su parmetro Ht t p S e rv le t Re q u e s t y delengando la peticin a uno de los
siguientes mtodos designados para manejar peticiones. Los diferentes tipos de
peticiones se describen en la seccin Peticiones HTTP.
doGet para GET, GET condicional, y peticiones HEAD.
doPost para peticiones POST.
doPut para peticiones PUT.
doDelete para peticiones DELETE.
doOptions para peticiones OPTIONS.
listAllNewItems(out)
listClosingItems(out)
insertItem(out, request)
itemDetails(out, request)
itemBid(out, request)
registerUser(out, request)
String cmd;
response.setContentType("text/html");
ServletOutputStream out = response.getOutputStream();
if (ctx == null ) {
try {
ctx = getInitialContext();
}catch (Exception e){
System.err.println(
"failed to contact EJB server"+e);
}
}
cmd=request.getParameter("action");
if(cmd !=null) {
if(cmd.equals("list")) {
listAllItems(out);
}else
if(cmd.equals("newlist")) {
listAllNewItems(out);
}else if(cmd.equals("search")) {
searchItems(out, request);
}else if(cmd.equals("close")) {
listClosingItems(out);
}else if(cmd.equals("insert")) {
insertItem(out, request);
}else if (cmd.equals("details")) {
itemDetails(out, request );
}else if (cmd.equals("bid")) {
itemBid(out, request) ;
}else if (cmd.equals("register")) {
registerUser(out, request);
}
}else{
// no command set
setTitle(out, "error");
}
setFooter(out);
out.flush();
}
Peticiones HTTP
Una peticin es un mensaje enviado desde un programa cliente como un
navegador a un programa servidor. La primera lnea del mensaje de peticin
contiene un mtodo que indica la accin a realizar sobre la URL que viene despus.
Los dos mecanismos ms comunes para enviar informacin al servidor son P OS T y
GET.
Las peticiones GET podran pasar parmetros a una URL aadindolas a la
URL. Estas peticiones pueden ser guardadas en el bookmark o enviadas por
correro e incluyen la informacin de la URL de respuesta.
Las peticiones POST podran pasar datos adicionales a la URL envindolas
directamente al servidor de forma separada a la URL. Estas peticiones no
pueden ser almacenadas en el bookmark ni enviadas por email y no cambiar
la URL de la respuesta.
Las peticiones PUT son la inversa de la peticiones GET. En lugar de leer la pgina,
las peticiones PUT escriben (o almacenan) la pgina.
Las peticiones DELETE son para eliminar pginas Web.
Las peticiones OPTIONS son para obtener informacin sobre las opciones de
comunicacin disponibles en la cadena peticin/respuesta.
Las peticiones TRACE son para realizar pruebas de diagnstico porque permite que
el cliente vea lo que se est recibiendo al orto final de la cadena de peticin.
Usar Cookies en servlets
LAs cookies HTTP son exencialmente cabeceras HTTP personalizadas que son
pasadas entre el cliente y el servidor. Aunque las cookies no son muy populares,
permiten que el estado sea compartido entre dos mquinas. Por ejemplo, cuando
un usuario hace login en una site, una cookie puede mantener una referencia
verificando que el usuario ha pasado el chequeo de password y puede usar esta
referencia para identificar al mismo usuario en futuras visitas.
Las cookies normalmente estn asociadas con un servidor. Si configuramos el
dominio a . ja v a . s u n . c o m , entonces la cookies est asociada con ese dominio. Si
no se configura nignn dominio, la cookie slo est asociada con el servidor que
cre la cookie.
El API Servlet de Java incluye una clase Co o k ie que podemos usar para configurar
o recuperar la cookie desde la cabecera HTTP. Las cookies HTTP incluyen un
nombre y una pareja de valores.
El mtodo s t a rt S e s s io n mostrado aqu est en el programa LoginServlet. En este
mtodo, el nombre en la pareja nombre valor usado para crea el Co o k ie es
JD CAUCTI ON , y un identificador nico generado por el servidor es el valor.
Recuperar un Cookie
El cookie es recuperado desde las cabeceras HTTP con una llamada al mtodo
g e t Co o k ie s para solicitarlo:
Generar Sesiones
http://localhost:7001/LoginServlet?action=logout
El cach de sesin implementado en el programa SessionCache.java incluye un
thread para eliminar sesiones ms viejas que el tiempo preseleccionado. Este
tiempo podra medise en horas o das, dependiendo del trfico de la web site.
FileServlet fileServlet=(FileServlet)
config.getServletContext().getServlet("file");
El mtodo v a lid a t e S e s s io n evita que los usuarios sin login de sesin accedan a
los directorios restringidos.
package auction;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if(request.getMethod().equals("POST")
&& request.getContentType().equals(
"application/x-www-form-urlencoded")) {
parameters=parsePostData(
request.getContentLength(),
request.getInputStream());
}
for(int i=0;i<paramOrder.size();i++) {
String name=(String)paramOrder.elementAt(i);
String value=getParameter((
String)paramOrder.elementAt(i));
out.println("name="+name+" value="+value);
}
out.println("</body></html>");
out.close();
}
if (length <=0) {
return null;
}
postedBytes = new byte[length];
try {
offset = 0;
while(dataRemaining) {
inputLen = instream.read (postedBytes,
offset,
length - offset);
if (inputLen <= 0) {
throw new IOException ("read error");
}
offset += inputLen;
if((length-offset) ==0) {
dataRemaining=false;
}
}
} catch (IOException e) {
System.out.println("Exception ="+e);
return null;
}
while (st.hasMoreTokens()) {
String pair = (String)st.nextToken();
int pos = pair.indexOf('=');
if (pos == -1) {
throw new IllegalArgumentException();
}
try {
key = java.net.URLDecoder.decode(
pair.substring(0, pos));
val = java.net.URLDecoder.decode(
pair.substring(pos+1,
pair.length()));
} catch (Exception e) {
throw new IllegalArgumentException();
}
if (ht.containsKey(key)) {
String oldVals[] = (String []) ht.get(key);
valArray = new String[oldVals.length + 1];
for (int i = 0; i < oldVals.length; i++) {
valArray[i] = oldVals[i];
}
valArray[oldVals.length] = val;
} else {
valArray = new String[1];
valArray[0] = val;
}
ht.put(key, valArray);
paramOrder.addElement(key);
}
return ht;
}
<FORM ACTION="/PostMultiServlet"
METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="TEXT" NAME="desc" value="">
<INPUT TYPE="FILE" NAME="filecontents" value="">
<INPUT TYPE="SUBMIT" VALUE="Submit" NAME="Submit">
</FORM>
El siguiente ejemplo extrae una descripcin y un fichero desde los navegadores del
cliente. Lee el stream de entrada buscando una lnea que corresponda con un
string de lmite, lee el contenido de la lnea y lueo lee los datos asociados con esa
parte. El fichero suvido se muestra simplemente, pero tambin puede ser escrito
en disco:
package auction;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if (request.getMethod().equals("POST")
&& request.getContentType().startsWith(
"multipart/form-data")) {
String boundary =
request.getContentType().substring(
index+9);
ServletInputStream instream =
request.getInputStream();
byte[] tmpbuffer = new byte[8192];
int length=0;
String inputLine=null;
boolean moreData=true;
while(inputLine.indexOf(boundary)
>0 && moreData) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
if(inputLine !=null)
System.out.println("input="+inputLine);
if(length<0) {
moreData=false;
}
}
if(moreData) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
if(inputLine.indexOf("desc") >=0) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
System.out.println("desc="+inputLine);
}
}
while(inputLine.indexOf(boundary)
>0 && moreData) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
}
if(moreData) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
if(inputLine.indexOf("filename") >=0) {
int startindex=inputLine.indexOf(
"filename");
System.out.println("file name="+
inputLine.substring(
startindex+10,
inputLine.indexOf("\"",
startindex+10)));
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0,
length);
}
}
byte fileBytes[]=new byte[50000];
int offset=0;
if (moreData) {
while(inputLine.indexOf(boundary)
>0 && moreData) {
length = instream.readLine(
tmpbuffer,
0,
tmpbuffer.length);
inputLine = new String (tmpbuffer, 0, 0, length);
if(length>0 && (
inputLine.indexOf(boundary) <0)) {
System.arraycopy(
tmpbuffer,
0,
fileBytes,
offset,
length);
offset+=length;
} else {
moreData=false;
}
}
}
// trim last two newline/return characters
// before using data
for(int i=0;i<offset-2;i++) {
System.out.print((char)fileBytes[i]);
}
}
out.println("</body></html>");
out.close();
}
}
Threads
Un servlet debe ser capaz de manejar mltipels peticiones concurrentes. Cualquier
nmero de usuarios puede en un momento dado invocar al servlet, y mientras que
el mtodo in it ejecuta siempre un nico trehad, el mtodo s e rv ic e es multi-thread
para manejar mltiples peticiones.
Esto significa que cualquier campo esttico o pblico accedido por el mtodo
s e rv ic e deberan estr restringidos a accesos de un thread. el ejemplo de abajo
usa la palabra clave s y n c h ro n iz e d para restringir el acceso a un contador para
que slo pueda ser actualizado por un thread a la vez:
int counter
Boolean lock = new Boolean(true);
synchronized(lock){
counter++;
}
HTTPS
Muchos servidores, navegadores, y el java Plug-In tiene la posibilidad de soportar
el protocolo HTTP seguro llamado HTTPS. Este similar al HTTP excepto en que los
datos on tramitidos a travs de una capa de socket seguro (SSL) en lugar de una
conexin de socket normal. Los navegadores web escuchan peticiones HTTP en un
puerto mientras escuchan las peticiones HTTPS en otro puerto.
Los datos encriptados que son enviados a travs de la red incluyen chequeos para
verificar si los dato se han modificado en el trnsito. SSL tambin autentifica el
servidor web a sus clientes proporcionando un certificado de clave pblica. en el
SSL 3.0 el cliente tambin puede autentificarse a s mismo con el servidor,
usxando de nuevo un certificado de clave pblica.
La clave pblica criptogrfica (tambin llamada clave de encriptacin asimtrerica)
usa una pareja de claves pblica y privada. Cualquier mensaje encriptado (hecho
ininteligible) con la clave privada de la pareja slo puede ser desencriptado con la
correspondiente clave pblica. Los certificados son sentencias firmadas
digitalmente generadas por un tercera parte conocidad como "Autoridad de
Certificacin" Certificate Authority. Esta Autorizar necesita asegurarse de que
nosotros somos quien decimos ser porque los clientes se creeran el certificado que
reciban. Si es as, este certificado puede contener la clave pblica de la pareja de
clave pblica/privada. El certificado est firmado por la clave privada de la
Autoridad de Certificacin, y muchos navegadores conocen las claves pblicas la
mayora de las Autoridades de Certificacin.
Mientras que la encriptacinde clavepblica es buena para propsitos de
autentificacin, no es tan rpida como la encriptacin asimtrica y por eso el
protocolo SSL usa ambos tipos de claves en el ciclo de vida de una conexin SSL.
El cliente y el servidor empiezan una transacin HTTPS con una inicializacin de
conexin o fase de estrechamiento de manos.
Es en ese momento en el que el servidor es autentificado usando el certificado que
el cliente ha recibido. El cliente usa la clave pblica del servidor para encriptar los
mensajes enviados al servidor. Despus de que el cliente haya sido autentificado y
el algoritmo de encriptacin se ha puesto de acuerdo entre las dos partes, se usan
unas nuevas claves de sesin simtrica para encriptar y desencriptar las
comunicaciones posteriores.
El algoritmo de encriptacin puede ser uno de los ms populares algoritmos como
"Rivest Shamir and Adleman" (RSA) o "Data Encryption Standard" (DES). Cuando
mayor sea el nmero de bits usados para crear la clave, mayores dificultades para
poder romper las claves mediante la fuerza bruta.
HTTPS usando criptografa de clave pblica y certificados nos permite proporcionar
una gran privacidad a las aplicacioens que necesitan transaciones seguras. Los
servidores, navegadores y Java Plug-In tienen sus propias configuraciones para
permitir usar Comunicaciones SSL. En general, estos pasos requieren:
Obtener una clave privada y un certificado firmado digitalmente con la clave
pblica correspondente.
Instalar el certificado en una localizacin especificada por el software que
estamos usando (servidor, navegador o Java Plug-In).
Activar las caractersticas SSL y especificar nuestros ficheros de certificado y
de clave privada como se explica en nuestra documentacin.
Siempre que activemos las caractersticas SSL de acuerdo con los requerimientos
de la aplicacin dependiendo del nivel de seguridad de necesitemos. Por ejemplo
no necesitamos verificar la autenticidad de los clientes para navegar por los tems
de la subasta, pero s querremos ecriptar la informacin de la tarjeta de crdido y
otras informaciones suministradas cuando los compradores y vendedores se
registran para participar.
HTTPS puede ser usado para cualquier dato, no slo ara pginas web HTTP. Los
programas escritos en lenguaje Java pueden ser descaradoa a trravs de
conexiones HTTPS, y podemos abrir una conexin con un servidor HTTPS en el
Java Plug-In. Para escribir un programa en Java que use SSL, este necesita una
librera SSL y un conecimiento detallado del proceso de negociacin HTTPS.
Nuestra librera SSL podra cubir los pasos necesarios ya que est informacin es
restringida por el control de exportacin de seguridad.
Oz it o
Tecnologa JNI
La plataforma Java es relativamente nueva, lo que significa qie algunas veces
podramos necesitar integrar programas escritos en Java con servicios, programas
o APIs existentes escritos en lenguajes distintos en Java. La plataforma Java
proporciona el Interfa Nativo Java (JNI) para ayudarnos con este tipo de
integracin.
El JNI define una convencin de nombres y llamadas para que la Mquina Virtual
Java1 pueda localizar e invocar a los mtodos nativos. De hecho, JNI est
construido dentro de la mquina virtual Java, por lo que sta puede llamar a
sistemas locales para realizar entrada/salida, graficos, trabajos de red y
operaciones de threads sobre el host del sistema operativo.
Este captulo explica como usar JNI en programas escritos en Java para llamar a
cualquier librera de la mquina local, llamar a mtodos del lenguaje Java desde
dentro del cdigo nativo, y cmo crear y ejecutar un ejemplar de la JVM. Para
mostrar cmo podemos hacer funcionar el JNI, los ejemplos de este captulo
incluyen integracin de JNI con el API de bases de datos Xbase de C++. y cmo
podemos llamar a una funcin matemtica. Xbase tiene fuentes que podemos
descargar.
Ejemplo JNI
Strings y Arrays
Otros Problemas de Programacin
Tienes Prisa?
Esta tabla cotiene enlaces a los tpicos especficos.
T p ic o S e c c i n
Ejemplo JNI Sobre el Ejemplo
Generar el Fichero de Cabecera
Firma del Mtodo
Implementar el Mtodo Nativo
Compilar las Libreras Dinmicas o de Objetos
Compartidos
Ejecutar el Ejemplo
Strings, Arrays, y Fields Pasar Strings
Pasar Arrays
Pinning Array
Arrays de Objetos
Arrays Multi-Dimensionales
Acceder a Campos
Otros Problemas de Problemas de Lenguaje
Programacin Mtodos Llamantes
Acceder a Campos
Threads y Sincronizacin
Problemas de Memoria
Invocacin
Adjuntar Threads
_______
1 Cuando se usan en toda esta site, los trminos, "Java virtual machine" o "JVM"
significa una mquina virtual de la plataforma Java.
Oz it o
Ejemplos JNI
Esta seccin presenta el programa de ejemplo Re a d File . Este ejemplo muestra
cmo podemos usar JNI para invocar un mtodo nativo que hace llamadas a
funciones C para mapear en fichero en la memoria.
Sobre el Ejemplo
Sobre el Ejemplo
Podemos llamar a cdigo escrito en cualquier lenguaje de programacin desde un
pograma escrito en leguaje Java declarando un mtodo nativo Java, cargando la
librera que contiene el cdigo nativo, y luego llamando al mtodo nativo. El cdigo
fuente de Re a d File que hay ms abajo hace exactamente esto.
Sin embargo, el exto en la ejecucin del programa requiere uno pocos pasos
adicionales ms all de la compilacin del fichero fuente Java. Despus de
compilar, pero antes de ejecutar el ejemplo, tenemos que generar un fichero de
cabecera. El cdigo nativo implementa las definiciones de funciones contenidas en
el fichero de cabecera generado y tambin implementa la lgica de negocio. Las
siguientes seccin pasan a travs de estos pasos:
import java.util.*;
class ReadFile {
//Native method declaration
native byte[] loadFile(String name);
//Load the library
static {
System.loadLibrary("nativelib");
}
Cargar la Librera
La librera que contiene la implementacin del cdigo nativo se carga con una
llamada a S y s t e m . lo a d Lib ra ry ( ) . Situando esta llamada en un inicializador
esttico nos aseguramos de que la librera slo se cargar una vez por cada clase.
La librera puede cargarse desde fuera del bloque esttico si la aplicacin as lo
requiere. Podramos necesitar configurar nuestro entorno para que el mtodo
lo a d Lib ra ry pueda encontrar nuesta librera de cdigo nativo:
static {
System.loadLibrary("nativelib");
}
Compilar el Programa
javac ReadFile.java
Luego, necesitamos generar un fichero de cabecera con la declaracin del mtodo
nativo y la implementacin del mtodo nativo para llamar a funciones para la carga
y lectura de un fichero.
Generar el Fichero de Cabecera
Para generar un fichero de cabecera, ejecutamos el comando ja v a h sobre la clase
Re a d File . En este ejemplo, el fichero de cabecera generadp se llama Re a d File . h .
Proporciona una firma de mtodo que debemos utilizar cuando implementemos la
funcin nativa lo a d file .
/*
* Class: ReadFile
* Method: loadFile
* Signature: (Ljava/lang/String;)[B
*/
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile
(JNIEnv *, jobject, jstring);
Los parmetros de la firma de la funcin son los siguientes:
JN I En v * : Un puntero al entorno JNI. Este puntero es un manejador del
thread actual en la mquina virtual Java y contiene mapeos y otra informacin
til.
jo b je c t : Una referencia a un mtodo que llama a este cdigo nativo. Si el
mtodo llamante es esttico, esta parmetro podra ser del tipo jc la s s en
lugar de jo b je c t .
js t rin g : El parmetro suministrado al mtodo nativo. En este ejemplo, es el
nombre del fichero a leer.
if (fd == -1) {
printf("Could not open %s\n", mfile);
}
lstat(mfile, &finfo);
m = mmap((caddr_t) 0, finfo.st_size,
PROT_READ, MAP_PRIVATE, fd, 0);
if (m == (caddr_t)-1) {
printf("Could not mmap %s\n", mfile);
return(0);
}
jb=(*env)->NewByteArray(env, finfo.st_size);
(*env)->SetByteArrayRegion(env, jb, 0,
finfo.st_size, (jbyte *)m);
close(fd);
(*env)->ReleaseStringUTFChars(env, name, mfile);
return (jb);
}
Podemos aproximarnos a llamar a un funcin C existente enlugar de implementar
una, de alguna de estas formas:
1. Mapear el nombre generado por JNI a un nombre de funcin C ya existente.
La seccin Problemas de Lenguaje muestra como mapear entre funciones de
base de datos Xbase y cdigo Java.
2. Usar el cdigo Stub compartido disponible desde la pgina JNI en la site de
java.sun.com.
Gnu C/Linux:
Win32/WinNT/Win2000
cl -Ic:/jdk1.2/include
-Ic:/jdk1.2/include/win32
-LD nativelib.c -Felibnative.dll
Ejecutar el Ejemplo
Para ejecutar el ejemplo, la mquina virtual Java necesita poder encontrar la
librera nativa. Para hacer esto, configurarmos el path de libreras al path actual de
esta forma:
Unix or Linux:
LD_LIBRARY_PATH=`pwd`
export LD_LIBRARY_PATH
Windows NT/2000/95:
set PATH=%path%;.
Con el path de libreras especificado de forma apropiada a nuestra plataforma,
llamamos al programa como lo haramos normalmente con el intrprete de
comandos:
java ReadFile
_______
1 Cuando se usan en toda esta site, los trminos, "Java virtual machine" o "JVM"
significa una mquina virtual de la plataforma Java.
Oz it o
Strings y Arrays
Esta seccin explica cmo pasar datos string y array entre un programa escrito en
Java y otros lenguajes.
Pasar Strings
Pasar Arrays
Pinning Array
Arrays de Objetos
Arrays Multi-Dimensionales
Pasar Strings
El objeto S t rin g en el lenguaje Java, que est representado como js t rin g en JNI,
es string unicode de 16 bits. En C un string por defecto est construido con
caracteres de 8 bits. Por eso, para acceder a objetos S t rin g Java pasados a un
funcin C C++ o devolver objetos un string C C++ a un mtodo Java,
necesitamos utilizar las funciones de conversin JNI en nuestra implementacin del
mtodo nativo.
La funcin Ge t S t rin g UTFCh a r recupera caracteres de bits desde un js t rin g de 16
bits usando el Formato de Transformacin Unicode (UTF). UTF representa los
caracteres Unicode como un string de 8 16 bits sin perder ninguna informacin.
El terpcer parmetro Ge t S t rin g UTFCh a r es el resultado JN I _ TRUE si se hace una
copia olcar de js t rin g o JN I _ FALS E si no se hace.
C Version:
(*env)->GetStringUTFChars(env, name, iscopy)
C++ Version:
env->GetStringUTFChars(name, iscopy)
La siguiente funcin C de JNI convierte un array de caracteres C en un js t rin g :
(*env)->NewStringUTF(env, lastfile)
El siguiente ejemplo convierte el array de caracteres C la s t file [ 8 0 ] en un js t rin g ,
que es devuelto al mtodo Java que lo llam:
Pasar Arrays
En el ejemplo presentado en la ltima seccin, el mtodo nativo lo a d File devuelve
el contenido de un fichero en un array de bytes, que es un tipo primitivo del
lenguaje Java. Podemos recuperar y crear tipos primitivos java llamando a la
funcin Ty p e Array apropiada.
Por ejemplo, para crear un nuevo array de floats, llamamos a N e w Flo a t Arra y , o
para crear un nuevo array de bytes, llamamos a N e w By t e Arra y . Este esquema de
nombres se extiende para la recuperacin de elementos, para aadir elementos, y
para modificar elementos del array. Para obtener un nuevo array de bytes,
llamamos a Ge t By t e Arra y Ele m e n t s . Para aadir o modificar elementos en el
array, llamamos a S e t < t y p e > Arra y Ele m e n t s .
La funcin Ge t By t e Arra y Ele m e n t s afecta a todo el array. Para trabajar con un
procin del array, llamamos a Ge t By t e Arra y Re g io n . Slo hay una funcin
S e t < t y p e > Arra y Re g io n para modificar elementos de un array. Sin embargo la
regin podra tener un tamao 1, lo que sera equivalente a la no-existente
S e t e < t y p e > Arra y Ele m e n t s .
Tip o d e
Fu n c io n e s u s a d a s
C d ig o N a t iv o
jboolean NewBooleanArray
GetBooleanArrayElements
GetBooleanArrayRegion/SetBooleanArrayRegion
ReleaseBooleanArrayRegion
jbyte NewByteArray
GetByteArrayElements
GetByteArrayRegion/SetByteArrayRegion
ReleaseByteArrayRegion
jchar NewCharArray
GetCharArrayElements
GetCharArrayRegion/SetCharArrayRegion
ReleaseCharArrayRegion
jdouble NewDoubleArray
GetDoubleArrayElements
GetDoubleArrayRegion/SetDoubleArrayRegion
ReleaseDoubleArrayRegion
jfloat NewFloatArray
GetFloatArrayElements
GetFloatArrayRegion/SetFloatArrayRegion
ReleaseFloatArrayRegion
jint NewIntArray
GetIntArrayElements
GetIntArrayRegion/SetIntArrayRegion
ReleaseIntArrayRegion
jlong NewLongArray
GetLongArrayElements
GetLongArrayRegion/SetLongArrayRegion
ReleaseLongArrayRegion
jobject NewObjectArray
GetObjectArrayElement/SetObjectArrayElement
jshort NewShortArray
GetShortArrayElements
GetShortArrayRegion/SetShortArrayRegion
ReleaseShortArrayRegion
jb=(*env)->NewByteArray(env, finfo.st_size);
(*env)->SetByteArrayRegion(env, jb, 0,
finfo.st_size, (jbyte *)m);
close(fd);
El array es devuelto al mtodo Java llamandte, que luego, enva al recolector de
basura la referencia del array cuando ya no es utilizado. El array puede ser
liberado explcitamente con la siguiente llamada:
Pinning Array
Cuando recuperamos un array, podemos especificar si es una copia (JN I _ TRUE) o
una referecia del array que reside en el programa Java (JN I _ FALS E). Si usamos
una referencia al array, querremos que el array permanezca en la pila java y que
no sea eliminado por el recolector de basura cuando compacte la pila de memoria.
Para evitar que las referencias al array sean eliminadas, la Mquina Virtual Java
"clava" el array en la memoria. Clavar el array nos asegura que cuando el array
sea liberado, los elementos correctos sern actualziados en la JVM.
En el mtodo nativo lo a d file del ejemplo de la pgina anterior, el array no se
liber explcitamente. Una forma de asegurarnos de que el array es recolectado por
el recolector de basura cuando ya no lo necesitamos, es llamar al mtodo Java,
pasarle el array de bytes y luego liberar la copia local del array. Esta tcnica se
muestra en la seccin Arrays Multi-Dimensionales.
Arrays de Objetos
Podemos almacenar cualquier objeto Java enun array con llamadas a las funciones
N e w Ob je c t Arra y y S e t Ob je c t Arra y Ele m e n t . La principal diferencia entre un
array de objetos y un array de tipos primitivos es que cuando se construyen se usa
una clase jo b je c t a rra y Java, como un parmetro.
El siguiente ejemplo C++ muestra cmo llamar a N e w Ob je c t Arra y para crear un
array deobjetos S t rin g . El tamao del array se configurar a cinco. la definicin de
la clase es devuelta desde una llamada a Fin d Cla s s , y los elementos del array
sern inicializados con un cadena vaca. Los elementos del array se actualizarn
llamando a S e t Ob je c t Arra y Ele m e n t con la posici y el valor a poner en el array.
#include <jni.h>
#include "ArrayHandler.h"
jobjectArray ret;
int i;
ret= (jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
for(i=0;i<5;i++) {
env->SetObjectArrayElement(
ret,i,env->NewStringUTF(message[i]));
}
return(ret);
}
La clase java que llama a este mtodo nativo es la siguiente:
Arrays Multi-Dimensionales
Podramos necesitar llamar a liberas numricas y matemticas existentes como la
librera de lgebra lineal CLAPACK/LAPACK u otros programas de clculo de
matrices desde nuestro programa Java. Muchas de estas libreras y programas
usando arrays de dos o ms dimensiones.
En el lenguaje java, cualquier array que tenga ms de una dimensin es tratado
como un array de arrys. Por ejemplo, un array de enteros de dos dimensiones es
manejado como un array de arrays de enteros. El array se lee horizontalmente, o
tambin conocido como rden de fila.
Otros lenguajes como FORTRAN usan la ordenacin por columnas, por eso es
necesario un cuidado extra su nuestro programa maneja un array Java a una
funcin FORTRAN. Tambin, los elementos de un array de una aplicacin Java no
est garantizado que sean contiguos en la memoria. Algunas libreras usan el
conocimiento de que los elementos de un array se almacenan uno junto al otro en
la memoria para realizar optimizaciones de velocidad, por eso podramos necesitar
hacer una copia local del array para pasarselo a estas funciones.
El siguiente ejemplo pasad un array de dos dimensiones a un mtodo nativo que
extrae los elementos, realiza un clculo, y llama al mtodo Java para devolver los
resultados.
El array es pasado como un objeto array que contiene un array de jin t s . Los
elementos individuales se extraen primero recuperando un ejemplar de jin t Arra y
desde el objeto array llamando a Ge t Ob je c t Arra y Ele m e n t , y luego se extraen los
elementos desde la fila jin t Arra y .
El ejemplo usa una matriz de tamao fijo. Su no conocemos el tamao del array
que se est utilizando, la funcin Ge t Arra y Le n g t h ( a rra y ) devuelve el tamao del
array ms exterior. Necesitaremos llamar a la funcin Ge t Arra y Le n g t h ( a rra y )
sobre cada dimensin del array para descubrir su tamao total.
El nuevo array enviado de vuelta al programa Java est construido a la inversa.
Primero, se crea un ejemplar de jin t Arra y y este ejemplar se pone en el objeto
array llamando a S e t Ob je c t Arra y Ele m e n t .
static{
System.loadLibrary("nativelib");
}
#include <jni.h>
#include <iostream.h>
#include "ArrayManipulation.h"
JNIEXPORT void
JNICALL Java_ArrayManipulation_manipulateArray
(JNIEnv *env, jobject jobj, jobjectArray elements,
jobject lock){
jobjectArray ret;
int i,j;
jint arraysize;
int asize;
jclass cls;
jmethodID mid;
jfieldID fid;
long localArrayCopy[3][3];
long localMatrix[3]={4,4,4};
for (i=0;i<3;i++) {
for (j=0; j<3 ; j++) {
localArrayCopy[i][j]=
localArrayCopy[i][j]*localMatrix[i];
}
}
for(i=0;i<3;i++) {
row= (jintArray)env->NewIntArray(3);
env->SetIntArrayRegion((jintArray)row,(
jsize)0,3,(jint *)localArrayCopy[i]);
env->SetObjectArrayElement(ret,i,row);
}
cls=env->GetObjectClass(jobj);
mid=env->GetMethodID(cls, "sendArrayResults",
"([[I)V");
if (mid == 0) {
cout <<"Can't find method sendArrayResults";
return;
}
env->ExceptionClear();
env->MonitorEnter(lock);
env->CallVoidMethod(jobj, mid, ret);
env->MonitorExit(lock);
if(env->ExceptionOccurred()) {
cout << "error occured copying array back" << endl;
env->ExceptionDescribe();
env->ExceptionClear();
}
fid=env->GetFieldID(cls, "arraySize", "I");
if (fid == 0) {
cout <<"Can't find field arraySize";
return;
}
asize=env->GetIntField(jobj,fid);
if(!env->ExceptionOccurred()) {
cout<< "Java array size=" << asize << endl;
} else {
env->ExceptionClear();
}
return;
}
_______
1 Cuando se usan en toda esta site, los trminos, "Java virtual machine" o "JVM"
significa una mquina virtual de la plataforma Java.
Oz it o
Otros Problemas de Programacin
Esta seccin presenta informacin sobre acceso a clases, mtodos y campos, y cubre
los threads, la memoria y la JVM1.
Problemas de Lenguaje
Llamar a Mtodos
Acceder a Campos
Threads y Sincronizacin
Problemas de Memoria
Invocacin
Adjuntar Threads
Problemas de Lenguaje
Hasta ahora, los ejemplos de mtodos nativos han cuvierto llamadas solitarias a
funciones C y c++ que o devuelven un resultado o modifican los parmetro pasados a
la funcin. Sin embargo, C++ al igual que utiliza ejemplares de clases. si creamos una
clase en un mtodo nativo, la referencia a esta clase no tiene una clase equivalente en
el lenguaje Java, lo que hace dficil llamar a funciones de la clase C++ que se cre
primero.
Una forma de manejar esta situacin es mantener un registtro de las clases C++
referencias y pasadas de vuelta a un proxy o al programa llamante. Para asegurarnos
de que una clase C++ persiste a travs de llamadas a mtodo nativos, usamos el
operador n e w de C++ para crear una referencia al objeto C++ en la pila.
El siguiente cdigo proporciona un mapeo entre la base de datos Xbase y cdigo en
lenguaje Java. La base de datos Xbase tiene un API C++ y usa inicializacinde clases
para realizar operaciones subsecuentes en la base de datos. Cuando se crea el objeto
clase, se devuelve un puntero a este objeto como una valor in t al lenguaje Java.
Podemos usar un valor lo n g o mayor para mquinas mayores de 32 bits.
static {
System.loadLibrary("dbmaplib");
}
#include <jni.h>
#include <xbase/xbase.h>
#include "CallDB.h"
Es primer paso es recuperar una referencia a una clase que contenga los mtodos a
los que queremos acceder. Para recuperar una referencia, podemos usar el mtodo
Fin d Cla s s o aceder a los argumentos jo b je c t p jc la s s para el mtodo nativo:
Una vez que hemos obtenido la clase, el segundo paso es llamar a la funcin
Ge t Me t h o d I D para recuperar un identificador para un mtodo que seleccionemos de
la clase. El identificador es necesario cuando llamamos al mtodo de este ejemplar de
la clase. Como el lenguaje Java soporta sobrecarga de mtodo, tambin necesitamos
especficar la firma particular del mtodo al que queremos llamar. Para encontar qu
firma usa nuestro mtodo Java, ejecutamos el comando ja v a p de esta forma:
javap -s Class
La firma del mtodo usasa se muestra como un comentario despus de cada
declaracin de mtodo como se ve aqu:
Llamar a Mtodos
// ArrayHandler.java
public class ArrayHandler {
private String arrayResults[];
int arraySize=-1;
static{
System.loadLibrary("nativelib");
}
#include <jni.h>
#include <iostream.h>
#include "ArrayHandler.h"
jobjectArray ret;
int i;
jclass cls;
jmethodID mid;
ret=(jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
for(i=0;i<5;i++) {
env->SetObjectArrayElement(
ret,i,env->NewStringUTF(message[i]));
}
cls=env->GetObjectClass(jobj);
mid=env->GetMethodID(cls,
"sendArrayResults",
"([Ljava/lang/String;)V");
if (mid == 0) {
cout "<<Can't find method sendArrayResults";
return;
}
env->ExceptionClear();
env->CallVoidMethod(jobj, mid, ret);
if(env->ExceptionOccurred()) {
cout << "error occured copying array back" <<endl;
env->ExceptionDescribe();
env->ExceptionClear();
}
return;
}
Para construir esto sobre Linux, ejecutamos los siguientes comandos:
javac ArrayHandler.java
javah -jni ArrayHandler
g++ -o libnativelib.so
-shared -Wl,-soname,libnative.so
-I/export/home/jdk1.2/include
-I/export/home/jdk1.2/include/linux nativelib.cc
-lc
Si queremos especificar un mtodo de superclase, por ejemplo para llamar al
constructor de padre, podemos hacerlo llamando a las funciones
Ca llN o n v irt u a l< t y p e > Me t h o d .
Un punto importante cuando llamamos a mtodos Java o a campos desde dentro del
cdigo nativo es que necesitamos capturar las excepciones lanzadas. La funcin
Ex c e p t io n Cle a r limpia cualquier excepcin pendiente miesntras que la funcin
Ex c e p t io n Oc c u re d chequea para ver si se ha lanzado alguna excepcin en la sesin
actual JNI.
Acceder a Campos
Acceder a campos Java desde dentro de cdigo nativo es similar a llamar a mtodos
Java. Sin emnargo, el campo es recuperado con un ID de campo en lugar de un ID de
mtodo.
Lo primero que necesitamos es recuperar el ID de un campo. Podemos usar la funcin
Ge t Fie ld I D , especificando el nombre del campo y la firma en lugar del nombre y la
firma del mtodo. Una vez que tenemos el ID del campo, llamamos a una funcin
Ge t < t y p e > Fie ld . El < t y p e > es el mismo tipo nativo que est siendo devuelto
excepto que se quita la j y la primera letra se pone en maysculas. Por ejemplo el
valor < t y p e > es I n t para el tipo nativo jin t , y By t e para el tipo nativo jb y t e .
El resultado de la funcin Ge t < t y p e > Fie ld es devuelto como el tipo nativo. Por
ejemplo, para recuperar el campo a rra y S iz e de la clase Arra y Ha n d le r, llamamos a
Ge t I n t Fie ld como se ve en el siguiente ejemplo.
El campo puede ser seleccionado llamando a las funciones e n v - > S e t I n t Fie ld ( jo b j,
fid , a rra y s iz e ) . Los campos estticos pueden ser configurados llamando a
S e t S t a t ic I n t Fie ld ( jc la s s , fid , a rra y s iz e ) y recuperados llamando a
Ge t S t a t ic I n t Fie ld ( jo b j, fid ) .
#include <jni.h>
#include <iostream.h>
#include "ArrayHandler.h"
jobjectArray ret;
int i;
jint arraysize;
jclass cls;
jmethodID mid;
jfieldID fid;
ret=(jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
for(i=0;i<5;i++) {
env->SetObjectArrayElement(
ret,i,env->NewStringUTF(message[i]));
}
cls=env->GetObjectClass(jobj);
mid=env->GetMethodID(cls,
"sendArrayResults",
"([Ljava/lang/String;)V");
if (mid == 0) {
cout <<Can't find method sendArrayResults";
return;
}
env->ExceptionClear();
env->CallVoidMethod(jobj, mid, ret);
if(env->ExceptionOccurred()) {
cout << "error occured copying
array back" << endl;
env->ExceptionDescribe();
env->ExceptionClear();
}
fid=env->GetFieldID(cls, "arraySize", "I");
if (fid == 0) {
cout <<Can't find field arraySize";
return;
}
arraysize=env->GetIntField(jobj, fid);
if(!env->ExceptionOccurred()) {
cout<< "size=" << arraysize << endl;
} else {
env->ExceptionClear();
}
return;
}
Threads y Sincronizacin
Aunque la librera nativa se carga una vez por cada clase, los threads individuales de
una aplicacin escrita en Java usan su propio puntero interface cuando llaman a un
mtodo nativo. Si necesitamos restringir el acceso a un objeto Java desde dentro del
cdigo nativo, podemos asegurarnos de los mtodos Java a los que llamamos tienen
sincronizacin explcita o podemos usar las funciones Mo n it o rEn t e r y Mo n it o rEx it .
En el lenguaje Java, el cdigo est protegido por un monitor siempre que
especifiquemos la palabra clave s y n c h ro n iz e d . En Java el monitor que entra y sale de
las rutinas normalmente est oculto para el desarrollador de la aplicacin. En JNI,
necesitamos delinear explcitamente los puntos de la entrada y de salida del cdigo de
seguridad del thread.
El siguiente ejemplo usa un objeto Bo o le a n para reestringir el acceso a la funcin
Ca llVo id Me t h o d .
env->ExceptionClear();
env->MonitorEnter(lock);
env->CallVoidMethod(jobj, mid, ret);
env->MonitorExit(lock);
if(env->ExceptionOccurred()) {
cout << "error occured copying array back" << endl;
env->ExceptionDescribe();
env->ExceptionClear();
}
Podramos encontrar que en caso donde queremos accder a recursos locales del
sistema como un manejador MFC windows o una cola de mensajes, es mejor usar un
Th re a d Java y acceder a la cola de eventos nativa o al sistema de mensajes dentro
del cdigo nativo.
Problemas de Memoria
Por defecto, JNI usa referencias locales cuando crea objetos dentro de un mtodo
nativo. Esto significa que cuando el mtodo retorna, las referencias estn disponibles
para el recolector de basura. Si queremos que un objeto persista a travs de las
llamadas a un mtodo nativo, debemos usar una referencia golbal. Una referencia
global se crea desde una referencia local llamando a N e w Glo b a lRe fe re n c e sobre la
referencia local.
Podemos marcar explctamente para el recolector de basura llamando a
D e le t e Glo b a lRe f sobre la referencia. Tambin podemos crear una referencia global al
estilo weak que sea accesible desde fuera del mtodo, pero puede ser recolectado por
el recolector de basura. Para crear una de estas referencias, llamamos a
N e w W e a k Glo b a lRe f y D e le t e W e a k Glo b a lRe f para marcar la referencia para la
recoleccin de basura.
Incluso podemos marcar explcitamente una referencia local para la recoleccin de
basura llamando al mtodo e n v - > D e le t e Lo c a lRe f( lo c a lo b je c t ) . Esto es til si
estamo usando una gran cantidad de datos temporales:
jobjectArray ret;
int i;
jint arraysize;
int asize;
jclass cls, tmpcls;
jmethodID mid;
jfieldID fid;
ret=(jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
//Process array
// ...
Invocaciones
La seccin sobre llamadas a mtodos nos mostraba como llamar a un mtodo o campo
Java usando el interface JNI y una clase cargada usando la funcin Fin d Cla s s . Con un
poco ms de cdigo, podemos crear un programa que invoque a la mquina virtual
Java e incluya su propio puntero al interface JNI que puede ser usado para crear
ejemplares de clases Java. En Java 2, el programa de ejecucin llamando ja v a es una
pequea aplicacin JNI que hace exactamente esto.
Podemos crear una mquina virtual Java con una llamada a JN I _ Cre a t e Ja v a VM, y
desconectar la mquina virtual Java creada con una llamada a JN I _ D e s t ro y Ja v a VM.
Una JVM tambin podra necesitar algunas propiedades adicionales de entorno. Estas
propiedades podran pasarse a la funcin JN I _ Cre a t e Ja v a VM en un estructura
Ja v a VMI n it Arg s .
La estructura Ja v a VMI n it Arg s contiene un puntero a un valor Ja v a VMOp t io n usado
para almacenar informacin del entorno como el classpath y la versin de la mquina
virtual Java, o propiedades del sistema que podran pasarse normalmente en la lnea
de comandos del programa.
Cuando retorna la funcin JN I _ Cre a t e Ja v a VM, podemos llamar a mtodo y crear
ejemplares de clases usando las funciones Fin d Cla s s y N e w Ob je c t de la misma
forma que lo haramos con cdigo nativo embebido.
N o t a : La invocacin de la mquina virtual Java slo se usa para threads
nativos en mquinas virtuales Java. Algunas antiguas mquinas virtuales
Java tienen una opcin de threads verdes que es estable para el uso de
invocaciones, Sobre una plataforma Unix, podramos necesitar enlazar
explcitamente con - lt h re a d o - lp t h re a d .
El siguiente programa invoca una mquina virtual Java, carga la clase Arra y Ha n d le r
y recupera el campo a rra y S iz e que debera tener el valor menos uno. Las opciones de
la mquina virtual Java incluyen el path actual en el classpath y desactivar del
compilador Just-In_Time (JIT) - D ja v a . c o m p ile r= N ON E.
#include <jni.h>
options[0].optionString = ".";
options[1].optionString = "-Djava.compiler=NONE";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 2;
vm_args.ignoreUnrecognized = JNI_FALSE;
result = JNI_CreateJavaVM(
&jvm,(void **)&env, &vm_args);
if(result == JNI_ERR ) {
printf("Error invoking the JVM");
exit (-1);
}
cls = (*env)->FindClass(env,"ArrayHandler");
if( cls == NULL ) {
printf("can't find class ArrayHandler\n");
exit (-1);
}
(*env)->ExceptionClear(env);
mid=(*env)->GetMethodID(env, cls, "<init>", "()V");
jobj=(*env)->NewObject(env, cls, mid);
fid=(*env)->GetFieldID(env, cls, "arraySize", "I");
asize=(*env)->GetIntField(env, jobj, fid);
Adjuntar Threads
Despus de invocar la mquina virtual Java, hay un thread local ejecutndose en ella.
Podemos crear ms threads en el sistema operativo local y adjuntar threads en la
mquina virtual Java para estos nuevos threads. Podriamos querer hacer esto su
nuestra aplicacin nativa es multi-threads.
Adjuntamos el thread local a la mquina virtual Java con una llamada a
At t a c h Cu rre n t Th re a d . Necesitamos suministrar punteros al ejemplar de la mquina
virtual Java y al entorno JNI. En la plataforma Java 2, podemos especficar en el tercer
parmetro el nombre del thread y/o el grupo bajo el que queremos que viva nuestro
thread. Es importante eliminar cualquier thread que haya sido prviamente adjuntado;
de otra forma, el programa no saldr cuando llamemos a D e s t ro y Ja v a VM.
#include <jni.h>
#include <pthread.h>
JavaVM *jvm;
args.version= JNI_VERSION_1_2;
args.name="user";
args.group=NULL;
result=(*jvm)->AttachCurrentThread(
jvm, (void **)&env, &args);
cls = (*env)->FindClass(env,"ArrayHandler");
if( cls == NULL ) {
printf("can't find class ArrayHandler\n");
exit (-1);
}
(*env)->ExceptionClear(env);
mid=(*env)->GetMethodID(env, cls, "<init>", "()V");
jobj=(*env)->NewObject(env, cls, mid);
fid=(*env)->GetFieldID(env, cls, "arraySize", "I");
asize=(*env)->GetIntField(env, jobj, fid);
printf("size of array is %d\n",asize);
(*jvm)->DetachCurrentThread(jvm);
}
options[0].optionString = "-Djava.class.path=.";
options[1].optionString = "-Djava.compiler=NONE";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 2;
vm_args.ignoreUnrecognized = JNI_FALSE;
Oz it o
Proyecto Swing: Construir un Interface
de Usuario
Las arquitecturas Java Foundation Classes (JFC) y JavaBeans Enterprise comparten
un elemento de diseo clave: la separacin de los datos de su aspecto en pantalla
o la manipulacin de los datos. En las aplicaciones JavaBeans Enterprise, el beande
entidad proporciona una vista de los datos. El mecanismo de los datos oculto
puede ser solapado y modificado sin modificar la vista del bean de entidad o
recompilar cualquier cdigo que use la vista.
El proyecto Swing separa la vista y control de un componente visual de sus
contenidos, o medelo de datos. Sin embargo, aqunque el Proyecto Swing tiene los
componentes que crean la arquitectura Modelo-Vista-Controlador (MVC), es ms
seguro describirlo como una arquitectura de modelo-delegado. Esteo eso por la
parte controlador de un interface Swing, frecuentemente usa el eventos del ratn y
de teclado para responder al componente, es combinada con la vista fsica en un
objeto "User Interface delegate" (UI delegate).
Cada componente, por ejemplo un JBu t t o n o un JS c ro llBa r, tiene una clase UI
delegate separada que desciende desde la clase Co m p o n e n t UI y est bajo el
control de un controlador UI separado. Mientras que cada componente tiene un UI
delgate bsico, no est ms unido con los datos ocultos por lo que se pueden
intercambiar mientras que la aplicacin todava se est ejecutando. La posibilidad
de cambiar el aspecto y comportamiento refleja la caracterstica del aspecto y
comportamiento conectable (PLAF) disponible en Swing.
Este captulo describe componentes de usuario Swing en trminos de la aplicacin
Au c t io n Clie n t .
Componentes y Modelo de Datos
El API de Impresin
Impresin Avanzada
Tienes Prisa?
Esta tabla contiene enlaces directos a los tpicos especficos.
T p ic o s S e c c i n
Componentes y Modelos de Datos Componentes de Peso Ligero
Ordenacin de Componentes
Modelos de Datos
Dibujado Personalizado de Celdas
Edicin de Celdas Personalizadas
Manejo de Eventos Especializado
Direcciones del Proyecto Swing
Oz it o
Componentes y Modelos de Datos
El programa AuctionClient es una sencilla aplicacion GUI que permite a los administradores de la casa de subastas listar y navegar por los tems de la subasta, e imprime informes sobre
estos tems. Esta seccin describe el cdigo Swing de la aplicacin que utiliza componentes de peso ligero y otras caractersticas Swing:
Ordenar Componente
Cada aplicacin o applet Swing necesita al menos un componente contenedor de peso pesado (un JFra m e , JW in d o w , JAp p le t , o JD ia lo g ). Cada uno de estos componentes con la
contraparte de JFra m e : JI n t e rn a lFra m e , contiene un componente llamado Ro o t P a n e . El JRo o t P a n e controla la adicin de capas adicionales usadas en dicho contenedor como
JLa y e re d P a n e , JCo n t e n t P a n e , Gla s s P a n e y la opcionalJMe n u Ba r. Tambin les permite a todos los componentes emulados (de peso ligero) interactuar con la cola de eventos AWT para
enviar y recibir eventos. Al interactuar con la cola de eventos, todos los componentes emulados obteinen una interaccin indirecta con el controlador de ventanas local.
JLayeredPane
El JLa y e re d P a n e se sita sobre el JRo o t P a n e , y como su nombre indica, controla las capas del componente contenidas dentro de los lmites del contenedor de peso pesado. Los
componentes no son aadidos al JLa y e re d P a n e , sino al JCo n t e n t P a n e . El JLa y e re d P a n e determina el orden Z de los componentes del JRo o t P a n e . Se puede pensar en el orden Z
como el orden de solapamiento de varios componentes. Si arrastramos y soltamos un componente o solicitamos un dilogo desplegable, queremos que el componente aparezca encima de
todas las otras ventana de la aplicacin. El JLa y e re d P a n e nos permite poner los componentes en capas.
El JLa y e re d P a n e divide la profundidad del contenedor en diferentes bandas que pueden usarsr para asignarle a un componente un tipo de nivel apropiado. La banda D RAG_ LAYER ,
valor 400, aparece sobre todas las dems capas. El nivel ms ingerior de JLa y e re d p a n e , la banda D EFAULT_ FRAME_ LAYER, tiene valor -3000 y y es el nivel de los contenedores de
peso pesado, incluyendo el Me n u Ba r. Las bandas son las siguientes:
Va lo r N o m b re d e Ba n d a Tip o s d e Co m p o n e n t e s
-3000 D EFAULT_ FRAME_ LAYER JMe n u b a r
0 D EFAULT_ LAYER JBu t t o n , JTa b le , . .
Componentes flotantes
P ALETTE_ LAYER
como un JTo o lBa r
MOD AL_ LAYER Dilogos Modales
FONT FACE="Verdana, Arial, Helvetica, sans-serif">Arrastrar y Soltar
400 D RAG_ LAYER
sobre todas las capas
Den
de estas bandas de profundidad generales, los componentes peuden estr organizados con un sistema de ordenacin para ordenar los componentes dentro de una banda particular, pero
este sistema invierte la prioridad de los nmeros. Por ejemplo, en una banda especificada como D EFAULT_ LAYER, los componentes con un valor, aparecen delante de los otros
componentes de la banda; mientras, componentes con un nmero mayor o -1 aparecen por detrs de l. El nmero ms alto en es esque de numeracin es .1, por eso una forma de
visualizarlo es un vector de componentes que pasa a travs de dibujar primero los componentes con un nmero mayor terminando con el componente en la posicin 0.
Por ejemplo, el siguiente cdigo aade un JBu t t o n a la capa por defecto y especifica que aparezca encima de los otros componentes de esa misma capa:
JContentPane
El JCo n t e n t P a n e controla la adicin de componentes a los contenedores de peso pesado. Por eso, tenemos que llamar al mtodo g e t Co n t e n t P a n e para aadir un componente al
Co n t e n t P a n e del Ro o t P a n e . Por defecto, un Co n t e n t P a n e se inicializa con un controlador de distribucin Bo rd e rLa y o u t . Hay dos formas de cambiar el controlador de distribucin.
Podemos llamar al mtodo s e t La y o u t de esta forma:
getContentPane()).setLayout(new BoxLayout())
O podemos reemplazar el Co n t e n t P a n e por defecto con nuestro propio Co n t e n t P a n e , como un JP a n e l, como este:
GlassPane
El Gla s s P a n e normalmente es completamente transparente y solo acta como una hoja de cristal delante de los componentes. Podemos implementar nuestro propio Gla s s P a n e usando
un componente como JP a n e l e instalndolo como el Gla s s P a n e llamando al mtodo s e t Gla s s P a n e . El Ro o t P a n e se configura con un Gla s s P a n e que puede ser recuperado llamando a
g e t Gla s s P a n e .
Una forma de usar un Gla s s P a n e es para implementar un componente que de forma invisble maneje todos los eventos de teclado y de ratn, bloqueando efectivamente la entrada del
usuario hasta que se complete un evento. El Gla s s P a n e puede bloquear los eventos, pero realmente el cursor no volver a su estado por defecto si tenermos seleccionar el cursor para
que sea un cursor ocupado en el Gla s s P a n e . Se requiere un evento de ratn adicional para el refresco:
public MyGlassPane() {
addKeyListener(new KeyAdapter() { });
addMouseListener(new MouseAdapter() { });
super.setCursor(
Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
}
Modelos de Datos
Se han combinado numerosos modelos de capas para formar las tablas del GUI Au c t io n Clie n t . A un nivel fundacional, el interface Ta b le Mo d e l y sus dos implementaciones
Ab s t ra c t Ta b le Mo d e l y D e fa u lt Ta b le Mo d e l propocionan las opciones ms bsicas para almacenar, recupear y modificar los datos bsicos.
El Ta b le Mo d e l es responsable de definir y categorizar los datos por sus clases. Tambin determina si el dato puede ser editado y cmo se agrupan los datos en columnas y filas. Sin
embargo, es importante observar que mientras el interface Ta b le Mo d e l se usa ms frecuentemente en la construccin de un JTa b le , no est unido fundamentalmente a su apariencia en
pantalla. Las implementaciones podra fcilmente formar la parte bsica de la hoja de clculo, o incluiso una clase no-GUI que pida la organizacin de los datos de una forma tabular.
La clase Re s u lt s Mo d e l es el corazn de las tablas Au c t io n Clie n t . Define una hoja de datos dimmica, dicta qu usuarios de la clase pueden editar los datos a travs del mtodo
Re s u lt s Mo d e l. is Ce llEd it a b le , y proporciona el mtodo u p d a t e para mantener los datos actualizados. El modelo es la base de la tablas fijas y escrollables, y deja que las modificaciones
se reflejen en cada vista.
A un alto nivel, y representado unca capa intermedia entre los datos y su representacin grfica esta el Ta b le Co lu m n Mo d e l. En este nivel los datos son agrupados por columnas en
anticipacin de su aparicin grfica en la tabla. La visibilidad y tamao de las columnas, sus cabeceras, y los tipos de componentes de sus renderizadores de celdas y editores son todos
manejados por la clase Ta b le Co lu m n Mo d e l.
Por ejemplo, congelar la columna ms ala izquierda del GUI Au c t io n Clie n t es posible porque los datos de la columna sin fcilmente intercambiables entre mltiples objetos
Ta b le Co lu m n Mo d e l y JTa b le . Esto traduce los objetos fix e d Ta b le y s c ro llTa b le del programa Au c t io n Clie n t .
Ms alto tadava se unen los distintos rederizadores, editores y componentes de cabecera cuya combinacin define el aspecto y organizacin del componente JTa b le . Este nivel es onde se
tomas las decisiones fundamentales sobre la distribucin del JTa b le .
La creaccin de las clases internas Cu s t o m Re n d e re r y Cu s t o m Bu t t o n Re n d e re r dentro de la aplicacin Au c t io n Clie n t permite a los usuarios de esas clases redefinir los componentes
sobre los que se basa la apariencia de las celdas de la tabla. De igual forma, la clase Cu s t o m Bu t t o n Ed it o r toma el lugar del editor por defecto de la tabla. De una forma verdaderamente
orientada a ojetos, los editores por defecto y renderizadores son fcilmente reemplazados si afectar a los datos que ellos representan ni la funcin del componente en el que residen.
Finalmente, los distintos interfaces de los componente de usuario son responsavles de la apariencia ltima de la JTa b le . Esta es la representacin especfica del aspecto y comportamiento
de las tablas Au c t io n Clie n t y sus datos de una forma final. El resultado final es que aadir una parte final Swing a unos servicios existentes requiere muy cdigo adicional. De hecho, la
codificacin del modelo es una de las tareas ms sencillas al construir una aplicacin Swing.
Modelo de la Tabla
La clase JTa b le tiene asociada una clase D e fa u lt Ta b le Mo d e l que internamente usa un vector para almacenar datos. Los datos de cada fila son almacenados en un objeto Vector s in g l
mientras que otro objeto Ve c t o r almacena cada una de esas columnas y los elementos que las constituyen. El objeto D e fa u lt Ta b le Mo d e l puede ser inicializado con datos de varias
formas diferentes. Este cdigo muesta el D e fa u lt Ta b le Mo d e l creado con un array de dos dimensiones y un segundo array que representa las cabeceras de columnas. El
D e fa u lt Ta b le Mo d e l convierte el array de Ob je c t en los objetos Ve c t o r apropidos:
Ms Modelos de Tablas
Un requerimiento comn para mostrar datos tabulares es la inclusin de un columna no desplazable. Este columna proporcina una conjunto de datos anclados que permanecen
estacionarios y visibles mientras que sus columnas vecinas son desplazadas horizontalmente (y frecuentemente fuera de la vista). Esto es importante en casos donde la fila de datos
puede ser identificada por un nico valor en la columna fijada, como un nombre o nmero identificador. el siguiente cdigo de ejemplo usa una columna de tabla fijada para mostrar una
lista de tems de la subasta.
El modelo de tabla base de este ejemplo implementa la clase Ab s t ra c t Ta b le Mo d e l. Su mtodo u p d a t e rellena dinmicamente los datos de la tabla desde una llamada a la base de datos.
Envan un evento de la tabla ha sido actualizada llamando al mtodo fire Ta b le S t ru c t u re Ch a n g e d para indicar el nmero de filas o columnas de la tabla que se han modificado.
package auction;
import javax.swing.table.AbstractTableModel;
import javax.swing.event.TableModelEvent;
import java.text.NumberFormat;
import java.util.*;
import java.awt.*;
fireTableStructureChanged();
} catch (Exception e) {
System.out.println("Exception e"+e);
}
}
}
La tabla es creada desde el modelo Re s u lt s Mo d e l, Luego se elimina la primera columna de la tabla y se aade a una nueva tabla. Como ahora tenemos dos tablas, la nica forma de que
las selecciones estn sincronizadas es usar un objeto Lis t S e le c t io n Mo d e l para configurar la seleccin sobre la fila de la tabla en la sotras tablas que no fueron seleccionadas llamando al
mtodo s e t Ro w S e le c t io n I n t e rv a l.
El ejemplo completo lo podemos encontrar en el ficheo fuente AuctionClient.java:
ListSelectionModel fixedSelection =
fixedTable.getSelectionModel();
fixedSelection.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (
ListSelectionModel)e.getSource();
if (!lsm.isSelectionEmpty()) {
setScrollableRow();
}
}
});
ListSelectionModel scrollSelection =
scrollTable.getSelectionModel();
scrollSelection.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm =
(ListSelectionModel)e.getSource();
if (!lsm.isSelectionEmpty()) {
setFixedRow();
}
}
});
CustomButtonEditor customEdit=new
CustomButtonEditor(frame);
scrollColumnModel.getColumn(3).setCellEditor(
customEdit);
headers.add(scrollTable.getTableHeader());
JTableHeader fixedHeader=
fixedTable.getTableHeader();
fixedHeader.setAlignmentY(Component.TOP_ALIGNMENT);
topPanel.add(fixedHeader);
topPanel.add(Box.createRigidArea(
new Dimension(2, 0)));
topPanel.setPreferredSize(new Dimension(400, 40));
headerPanel.add(headers, "North");
headerPanel.add(scrollBar, "South");
topPanel.add(headerPanel);
scrollTable.setPreferredScrollableViewportSize(
new Dimension(300,180));
fixedTable.setPreferredScrollableViewportSize(
new Dimension(100,180));
fixedTable.setPreferredSize(
new Dimension(100,180));
scrollBar.getModel().addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Point q = headers.getViewPosition();
Point p = innerPort.getViewPosition();
int val = scrollBar.getModel().getValue();
p.x = val;
q.x = val;
headers.setViewPosition(p);
headers.repaint(headers.getViewRect());
innerPort.setViewPosition(p);
innerPort.repaint(innerPort.getViewRect());
}
});
scrollTable.getTableHeader(
).setUpdateTableInRealTime(
false);
scrollTable.setAutoResizeMode(
JTable.AUTO_RESIZE_OFF);
frame.getContentPane().add(scrollPane);
scrollTable.validate();
frame.setSize(450,200);
}
void setFixedRow() {
int index=scrollTable.getSelectedRow();
fixedTable.setRowSelectionInterval(index, index);
}
void setScrollableRow() {
int index=fixedTable.getSelectedRow();
scrollTable.setRowSelectionInterval(index, index);
}
Modelo JList
El componente JLis t muestra una lista verticla de datos y usa un Lis t Mo d e l para contener y manipular los datos. Tambin usa un objeto Lis t S e le c t io n Mo d e l para permitir la seleccin y
subsecuente recuperacin de elementos de la lista.
Las implementaciones por defecto de las clases Ab s t ra c t Lis t Mo d e l y Ab s t ra c t Lis t S e le c t io n Mo d e l las proporciona el API Swing desde las clases D e fa u lt Lis t Mo d e l y
D e fa u lt Lis t S e le c t io n Mo d e l. Si usamos estos dos modelos por defecto y el renderizador de celdas por defecto, obtendremos una lista que muestra elementos modelo llamado al mtodo
t o S t rin g sobre cada objeto. La lista usa el modelo MULTI P LE_ I N TERVAL_ S ELECTI ON de seleccin de lista para seleccionar cada elemento de la lista.
Hay disponibles tres modos de seleccin para D e fa u lt Lis t S e le c t io n Mo d e l: S I N GLE_ S ELECTI ON , donde slo se puede seleccionar un tem a la vez; S I N GLE_ I N TERVAL_ S ELECTI ON
en el que se puede seleccionar un rango de items secuenciales; y MULTI P LE_ I N TERVAL_ S ELECTI ON , en el que se permite que cualquir o todos los elementos sean seleccionados. El
modo de seleccin puede cambiarse llamando al mtodo s e t S e le c t io n Mo d e de clase JLis t .
public SimpleList() {
JList list;
DefaultListModel deflist;
deflist= new DefaultListModel();
deflist.addElement("element 1");
deflist.addElement("element 2");
list = new JList(deflist);
Modelo JTree
La clase JTre e modela y muestra una lista vertical de elementos o nodos ordenados en una forma de rbol de herencia.
Un objeto JTre e teine un nodo raz y uno o ms nodos hijos, que pueden contener ms nodos hijos. Cada nodo padre puede expandirse para mostrar
sus hijos de forma similar a los familiares rboles de directorios de los usuarios de Windows.
Como los componentes JLis t y JTa b le , el JTre e consta de ms de un modelo. El modo de seleccin es similar al detallado para el modelo JLis t . El
modo de seleccin tiene ests ligeras diferencias en los nombres: S I N GLE_ TREE_ S ELECTI ON , D I S CON TI GUOUS _ TREE_ S ELECTI ON , y
CON TI GUOUS _ TREE_ S ELECTI ON .
Mientras que D e fa u lt Tre e Mo d e l mantiene los datos en un rbol y es responsable de aadir y eliminar nodos, es la clase
D e fa u lt Tre e Mu t a b le Tre e N o d e la que define los mtodos usados para moverse por los nodos. El D e fa u lt Tre e Mo d e l se usa frecuentemente para
implementar modelos personaloizados porque no hay un Ab s t ra c t Tre e Mo d e l en el paquete JTre e . Sin embargo, si usamos objetos personalizados,
debemos implementar Tre e Mo d e l. Este cdigo de ejemplo crea un JTre e usando el D e fa u lt Tre e Mo d e l.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
public SimpleSearchTree() {
String[] treelabels = { "All Auctions",
"Closed Auction",
"Open Auctions" };
Integer[] closedItems = { new Integer(500144),
new Integer(500146),
new Integer(500147) };
nodes = new
DefaultMutableTreeNode[treelabels.length];
DefaultMutableTreeNode[] closednodes = new
DefaultMutableTreeNode[closedItems.length];
DefaultMutableTreeNode[] opennodes = new
DefaultMutableTreeNode[openItems.length];
for (int i=0; i < treelabels.length; i++) {
nodes[i] = new
DefaultMutableTreeNode(treelabels[i]);
}
nodes[0].add(nodes[1]);
nodes[0].add(nodes[2]);
DefaultTreeModel model=new
DefaultTreeModel(nodes[0]);
tree = new JTree(model);
Component comp =
super.getTableCellRendererComponent(
table,value,isSelected,hasFocus,
row,column);
return label;
}
}
El renderizador se selecciona sobre una columna de esta forma:
if (isSelected) {
((JButton)value).setForeground(
table.getSelectionForeground());
((JButton)value).setBackground(
table.getSelectionBackground());
} else {
((JButton)value).setForeground(table.getForeground());
((JButton)value).setBackground(table.getBackground());
}
return (JButton)value;
}
}
Al igual que el renderizador de celdas por defecto JLa b e l, esta clase trata con el componente principal (en este caso JBu t t o n ) para hacer el dibujado. La seleccin de la celda cambia los
colores del botn. Como antes, el renderizador de celdas est seguro sobre la columna apropiada de la tabla de subastas con el mtodo s e t Ce llRe n d e re r:
scrollColumnModel.getColumn(3).setCellRenderer(
new CustomButtonRenderer());
De forma alternativa, todos los componentes JBu t t o n pueden configurarse para usar el Cu s t o m Bu t t o n Re n d e re r en la tabla con una llamada a s e t D e fa u lt Re n d e re r de esta forma:
table.setDefaultRenderer(
JButton.class, new CustomButtonRenderer());
CustomButtonEditor(JFrame frame) {
super(new JCheckBox());
mybutton = new JButton();
this.editorComponent = mybutton;
this.clickCountToStart = 2;
this.frame=frame;
mybutton.setOpaque(true);
mybutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
((JButton) editorComponent).setText(((
JButton)value).getText());
if (isSelected) {
((JButton) editorComponent).setForeground(
table.getSelectionForeground());
((JButton) editorComponent).setBackground(
table.getSelectionBackground());
} else {
((JButton) editorComponent).setForeground(
table.getForeground());
((JButton) editorComponent).setBackground(
table.getBackground());
}
return editorComponent;
}
}
Direcciones Swing
Mientras que la arquitectura bsica Swing ha permanecido estable a su diseo original, se han realizado muchas mejoras y optimizaciones sobre componentes como JTa b le y en reas
desplazables.
Sin embargo, como veremos en la seccin Analizar un Programa, una simple tabla de 700x300 requiere casi medio megabyte de memoria cuando se usa doble buffer. La creaccin de 10
tablas probablemente necesitara el intercambio de memoria a disco, afectando severamenta al rendimiento en mquinas de bajo nivel.
Oz it o
El API de Impresin
El paquete ja v a . a w t . p rin t de la plataforma Java 2 nos permite imprimir cualquier
cosa que pueda ser renderizada a un contexto Gra p h ic s o Gra p h ic s 2 D
incluyendo componentes AWT, componentes Swing y grficos 2D. El API de
impresin es fcil de usar. Nuestra aplicacin le dice al sistema de impresin qu
imprimir, y el sistema de impresin determina cuando se renderiza cada pgina.
Este m o d e lo d e im p re s i n p o r re t ro lla m a d a permite soporte de impresin en un
amplio rango de impresoras y sistemas. El modelo de retrollamada tambin
permite al usuario imprimir a una impresora de mapa de bits desde un ordenador
que no tiene suficiente memoria o espacio en disc para contener el bitmap de una
pgina completa.
Un contexto grfico permite a un programa dibujar en un dispositivo de
renderizacin como una pantalla, una impresora o una imagen fuera de pantalla.
Como los componentes Swing se renderizan a travs de un objeto Gra p h ic s
usando el soporte de grficos AWT, es fcil imprimir componentes Swing con el
nuevo API de impresin. Sin embargo, los componentes AWT no se renderizan a un
dispositivo grfico, debemos extender la clase del componente AWT e implementar
el mtodo de dibujo del componente AWT.
Qu hay en el Paquete?
Qu hay en el Paquete?
El ja v a . a w t . p rin t contiene los siguientes interfaces, clases y excepciones. Aqu
podrs encontrar la Especificacin del API.
Interfaces
Pageable
Printable
PrinterGraphics
Clases
Book
PageFormat
Paper
PrinterJob
Excepciones
PrinterAbortException
PrinterException
PrinterIOException
int X = (int)this.getLocation().getX();
int Y = (int)this.getLocation().getY();
Y aqu est el cdigo de la clase My Bu t t o n :
public MyButton() {
super("MyButton");
}
Graphics2D g2 = (Graphics2D) g;
public MyButton() {
super("MyButton");
}
Graphics2D g2 = (Graphics2D) g;
g2.translate(pf.getImageableX(),
pf.getImageableY());
Font f = new Font("Monospaced", Font.PLAIN,12);
g2.setFont (f);
paint(g2);
return Printable.PAGE_EXISTS;
}
Si extendemos un JP a n e l e implementamos P rin t a b le , podemos imprimir un
componente panel y todos sus componentes.
Dilogo de Impresin
Es fcil mostrar el Dilogo de Impresin para que el usuario final pueda
intercambiar las propiedades del rabajo de impresin. El mtodo
a c t io n P e rfo rm e d del ejemplo Swing anterior modificado aqu hace justo esto:
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable((MyButton) e.getSource());
if(printJob.printDialog()){
try { printJob.print(); }
catch (Exception PrinterExeption) { }
}
}
N o t a : En Swing, la sentencia p rin t Jo b . s e t P a g e a b le ( ( My Bu t t o n )
e . g e t S o u rc e ( ) ) ; puede escribirse como
p rin t Jo b . s e t P rin t a b le ( ( My Bu t t o n ) e . g e t S o u rc e ( ) ) ;. La diferencia es
que s e t P rin t a b le es para aplicaciones que no conocen el nmero de
pginas que estn imprimiendo. Si usamos s e t P rin t a b le , necesitamos
aadir if( p i > = 1 ) { re t u rn P rin t a b le . N O_ S UCH_ P AGE: } al principio
del mtodo p rin t .
/* Set up Book */
PageFormat landscape = printJob.defaultPage();
PageFormat portrait = printJob.defaultPage();
landscape.setOrientation(PageFormat.LANDSCAPE);
portrait.setOrientation(PageFormat.PORTRAIT);
Book bk = new Book();
bk.append((Printable)b, landscape);
bk.append((Printable)b2, portrait, 2);
printJob.setPageable(bk);
try { printJob.print(); } catch (Exception ex) { }
}
Oz it o
Impresin Avanzada
La seccin anterior explic cmo imprimir componentes sencillos y cubra las tcnicas que se pueden usar para imprimir capturas de pantalla. Sin embargo, si queremos imprimir
ms que un componente por cada pgina, o su nuestro componentes es mayor que el tamao de una pgina, necesitamos hacer algn trabajo adicional dentro del mtodo p rin t .
Esta seccin explica qu necesitamos hacer y concluye con un ejemplo de cmo imprimir los contenidos de un componente JTa b le .
Varios Componentes por Pgina
Ejemplo
Podemos reemplazar el mtodo p rin t de los ejemplos p rin t b u t t o n . ja v a Abstract Window Toolkit (AWT) y Swing con el siguiente cdigo para aadir un mensaje en el pie de pgina
de Co m p a n y Co n fid e n t ia l.
if (pi >= 1) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
Font f= Font.getFont("Courier");
double height=pf.getImageableHeight();
double width=pf.getImageableWidth();
g2.translate(pf.getImageableX(),
pf.getImageableY());
g2.setColor(Color.black);
g2.drawString("Company Confidential", (int)width/2,
(int)height-g2.getFontMetrics().getHeight());
g2.translate(0f,0f);
g2.setClip(0,0,(int)width,
(int)(height-g2.getFontMetrics().getHeight()*2));
paint (g2);
return Printable.PAGE_EXISTS;
}
En el nuevo mtodo p rin t , el contexto Gra p h ic s 2 D es recortado antes de llamar al mtodo p a in t del padre JBu t t o n . Esto evita que el mtodo JBu t t o n p a in t sobreescriba el
botn de la pgina. El mtodo t ra n s la t e se usa para apuntan el mtodo JBu t t o n p a in t a que empieza el p a in t con un desplazamiento de 0,0 desde la parte visible de la pgina. el
rea visible ya est calculada mediante una llamada anterior a t ra n s la t e :
g2.translate(pf.getImageableX(), pf.getImageableY());
Para ms componentes, podramos necesitar configurar el color de fondo para ver los resultados. En este ejemplo el color de texto se imprimi en negro.
Los siguientes mtodos son tiles para calcular el nmero de pginas requeridas y para hacer que un componente se reduzca hasta entrar en una pgina:
M t o d o s P a g e Fo rm a t :
g e t I m a g e a b le He ig h t ( )
devuelve la altura de la pgina que podemos usar para imprimir la salida.
g e t I m a g e a b le W id t h ( )
devuelve la anchura de la pgina que podemos usar para imprimir la salida.
M t o d o Gra p h ic s 2 D :
s c a le ( x ra t io , y ra t io )
escala el conexto grfico 2D a este tamao. Un rato de uno mantiene el tamao, menos de uno reduce el tamao del contexto grfico.
if (pageIndex >=TotalPages) {
return NO_SUCH_PAGE;
}
El marco de trabajo de impresin llama al mtodo p rin t multiples veces hasta que p a g e I n d e x sea menor o igual que To t a lP a g e s . Todo lo que necesitamos hacer es crear una
nueva pgina para del mismo componente encada bucle p rin t . Esto se puede hacer tratando la pgina impresa como una ventana deslizante sobre el componente. La parte del
componente que se est imprimiendo es seleccionada por una llamada a t ra n s la t e para marcar la parte superior de la pgina y una llama a s e t Clip para marcar la parte inferior de
la pgina. el siguiente diagrama ilustra este proceso.
El lado izquierdo del diagrama representa la pgina enviada a la impresora. El lado LEFT contiene la longitud del componente que est siendo imprimido en el mtodo p rin t . La
primera pgina puede ser representada de esta forma:
Luego la ventana de la pgina impresa se desliza a lo largo del componente para imprimir la segunda pgina, con el ndice uno.
Este proceso contina hasta que se alcanza la ltima pgina.
Imprimir un Componente JTable
La clase Report.java usa muchos de tcnicas avanzadas cubiertas en esta seccin para imprimir los datos y la cabecera de un componente JTa b le que expande muchas pginas. La
salida de impresin tambin inlcuye un pi de pgina con el nmero de sta.
public Report() {
frame = new JFrame("Sales Report");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);}});
printButton.setText("print me!");
frame.getContentPane().add(
BorderLayout.SOUTH,printButton);
RepaintManager.currentManager(
frame).setDoubleBufferingEnabled(false);
frame.setVisible(true);
}
double headerHeightOnPage=
tableView.getTableHeader(
).getHeight()*scale;
double tableWidthOnPage=tableWidth*scale;
double oneRowHeight=(tableView.getRowHeight()+
tableView.getRowMargin())*scale;
int numRowsOnAPage=
(int)((pageHeight-headerHeightOnPage)/
oneRowHeight);
double pageHeightForTable=oneRowHeight*
numRowsOnAPage;
int totalNumPages=
(int)Math.ceil((
(double)tableView.getRowCount())/
numRowsOnAPage);
if(pageIndex>=totalNumPages) {
return NO_SUCH_PAGE;
}
g2.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
//bottom center
g2.drawString("Page: "+(pageIndex+1),
(int)pageWidth/2-35, (int)(pageHeight
+fontHeight-fontDesent));
g2.translate(0f,headerHeightOnPage);
g2.translate(0f,-pageIndex*pageHeightForTable);
g2.scale(scale,scale);
tableView.paint(g2);
g2.scale(1/scale,1/scale);
g2.translate(0f,pageIndex*pageHeightForTable);
g2.translate(0f, -headerHeightOnPage);
g2.setClip(0, 0,
(int) Math.ceil(tableWidthOnPage),
(int)Math.ceil(headerHeightOnPage));
g2.scale(scale,scale);
tableView.getTableHeader().paint(g2);
//paint header at top
return Printable.PAGE_EXISTS;
}
grant {
permission java.lang.RuntimePermission
"queuePrintJob";
};
Para lanzar el applet asumiendo un fichero de polica llamado p rin t p o l y una pgina HTML llamada S a le s Re p o rt . h t m l, teclearemos:
appletviewer -J-Djava.security.policy=
printpol SalesReport.html
El diagrama muestra cmo se ver la impresin del informe:
Oz it o
Depurar Applets, Aplicaciones y Servlets
Una ley no escrita de la programacin sentencia que gastatemos el 10 por cien de
nuestro tiempo en el primer 90 por ciento de un proyecto, y el otro 90 por ciento
de nuestro tiempo en el 10 por cierto restante. Esto suena igual que cualquiera de
nuestros proyectos, probablemente estamosgastando el ltimo 10 por ciento en
depuracin e integracin. Mientras que hay cantidad de libros y de gente
ayudndonos a empezar un progyecto, hay muy pocos recursor disponibles para
ayudarnos a finalizarlo.
La buena noticia es que este captulo se enfoca completamente en la depuracin, y
en evitar que nuestro proyecto se pase de tiempo. Usa ejemplos del mundo real
para pasear a travs de pasos sencillos para depurar y fijar nuestros programas.
Cuando terminemos, deberemos ser unos expertos en el seguimiento de problemas
en programas escritos en Java -- applets, aplicaciones y servlets -- de todas las
formas y tamaos.
Recolectar Evidencias
Tienes Prisa?
Si tienes un problema que te presiona y necesitas una respuesta ahora mismo,
esta tabla podra ayudarte. Nos dice dnde encontrar las respuestas a los
problemas ms comunes a las que podemos acudir directamente.
P ro b le m a S e c c i n
El programa se cuelga o bloquea Anlisis y Seguimiento de Pila
Problemas en la ejecucin del programa Ir detrs de la silla con jdb
Problemas con Java Web ServerTM Depurador de Servlets y
Analizar y seguir Pistas
Oz it o
Recoleccin de Evidencias
El primer paso para intentar resolver cualquier problema es obtener tanta
informacin como sea posible. Si podemos imagninarnos la escena de un
crimen,sabemos que todo est chequeado, catalogado y analizado antes de
alcanzar cualquier conclusin. Cuando se depura un programa, no tenemos armas,
muestras de pelo, ni huellas dactilares, pero existen cantidad de evidencias que
podemos obtener y que podran contener o apuntar a la solucin ltima. Esta
seccin explca como recoger esas evidencias.
Instalacin y Entorno
El Path de Clases
Carga de Clases
Incluir Cdigo de Depurado
Instalacin y Entorno
La plataforma Java TM es una tecnologa cambiante y de rpido movimiento.
Podramos tener ms de una versin instalada en nuestro sistema, y esas
versiones podran haber sido instaladas como parte de la instalacin de otros
productos. En un entorno con versiones mezcladas, un programa puede
experimentar problemas debido a los cambios de la plataforma en las nuevas
versiones.
Por ejemplo, si las clases, las libreras, o las entradas de registro de Window de
instalaciones anteriores permanecen en nuenstro sistema despus de una
actualizacin, hay una oportunidad de que la mezcla del nuevl software sea la
causante de nuestros problemas y necesita ser investigada y eliminada. Las
oportunidades para los problemas relacionados con la mezcla de versiones de
software se ha incrementado con el uso de diferentes versiones de herramientas
para desarrollar software de la plataforma Java.
La seccin sobre Problemas con Versiones al final de este captulo proporciona una
lista completa de las principales versiones de la plataforma Java para ayudarnos a
resolver nuestros problemas con versiones de software.
Path de Clases
En la plataforma Java 2, la variable de entorno CLAS S P ATH es necesaria para
especificar a la propia aplicacin dnde estn sus clases, y no las clases de la
plataforma Java como en versiones anteriores. Por eso es posible que nuestro
CLAS S P ATH apunte a las clases de la plataforma Java desde versiones anteriores
y nos cause problemas.
Para examinar el CLAS S P ATH, tecleamos esto en la lnea de comando:
W in d o w s 9 5 / 9 8 / N T:
echo %CLASSPATH%
Un ix :
echo $CLASSPATH
Las clases Java se cargan en primer lugar, primera forma bsica de la lista
CLAS S P ATH. Si la variable CLAS S P ATH contiene una referencia a un fichero
lib / c la s s e s . z ip , que apunta a una instalacin diferente de la plataforma Java, esto
peude causar que se cargen clases incomplatibles.
N o t a : En la plataforma Java 2, las clases del sistema se eligen antes de
cualquier clases de la lista CLAS S P ATH para minimizar de que se
caeguen clases Java anteriores a la clase Java 2 del mismo nombre.
javac -J-Xbootclasspath:c\java\lib\tools.jar;c:
\java\jre\lib\rt.jar;c:\java\jre\lib\i18n.jar;.
Myapp.java
No necesitamos la bandera - J para ejecutar el programa My a p p compilado, slo
tecleamos esto en una sla lnea:
java -Xbootclasspath:c:\java\jre\lib\rt.jar;c:
\java\jre\lib\i18n.jar;. Myapp
S is t e m a s Un ix :
En este ejemplo, la plataforma Java est instalada en el directorio
/ u s r/ lo c a l/ ja v a . Tecleamos todo en una sla lnea:
javac -J-Xbootclasspath:/usr/local/java/lib/tools.jar:
/usr/local/java/jre/lib/rt.jar:
/usr/local/java/jre/lib/i18n.jar:. Myapp.java
No necesitamos la bandera - J para ejecutar el programa My a p p compilado, slo
tecleamos esto en un sla lnea:
java -Xbootclasspath:/usr/local/java/jre/lib/rt.jar:
/usr/local/java/jre/lib/i18n.jar:. Myapp
Carga de Clases
Otra forma de analizar problemas con el CLAS S P ATH es localizar desde dnde
est cargando las clases nuestra aplicacin. La opcin - v e rb o s e del comando ja v a
muestra de donde vienen los ficheros . z ip o . ja r cuando se carga. De esta forma,
podremos decir si vienen del fichero zip de la plataforma Java o desde algn
fichero JAR de la aplicacin.
Por ejemplo, una aplicacin podra estar usando la clase P a s s w o rd que escribimos
para ella o podra estar cargando la clase P a s s w o rd desde la herramienta IDE
instalado.
Deberasmos ver cada nombre de fichero zip o Jar como se v aqu:
public TestRuntime () {
String dprop=System.getProperty("debug");
if (debugmode) {
System.err.println("debug mode!");
}
}
}
Crear Versiones de Depuracin y Produccin en Tiempo de
Compilacin
Como se mencion antes, un problem con la adicin de sentencias
S y s t e m . o u t . p rin t ln para depurar nuesto cdigo es que debemos eliminarlas antes
de liberar nuestro producto. Adems de aadir cdigo innecesario, las sentecias de
depuracin p rin t ln pueden contener informacin que no queremos que vea el
cliente.
Una forma de eliminar las sentencias de depuracin S y s t e m . o u t . p rin t ln de
nuestro cdigo es usar la siguiente optimizacin del compilador para eleminar los
corchetes pre-determinados de nuestos cdigo en el momento de la compilazin y
activar alguna algo similar a un depurador pre-procesador.
Este ejemplo usa una bandera booleana esttica d m o d e que cuando se selecciona
a fa ls e resulta en la eliminacin el cdigo de depuracin y de las sentencias de
depuracin. Cuando el valor de d m o d e se selecciona a t ru e , el cdigo es incluido
en el fichero class compilado y est disponible en la aplicacin para propsitos de
depuracin.
class Debug {
if (Debug.dmode) { // These
System.err.println("Debug message"); // are
} // removed
}
Thread.currentThread().dumpStack();
main[1] locals
No local variables: try compiling with -g
Para obtener acceso a la informacin de variables lcoales, tenemos que obtener el
fuente (s rc . z ip o s rc . ja r) y recompilarlo con una bandera d e b u g . Podemos
obtener el fuente de la mayora de las clases java.* classes con la descarga de los
binarios desde java.sun.com.
javac -g src/java/lang/String.java
Para ejecutar la aplicacin con las nuevas clases compiladas, necesitamos usar la
opcion b o o t c la s s p a t h para que esas clases se utilicen en primer lugar.
Tecleamos lo siguiente en una sla lnea con espacio antes de m y a p p .
P la t a fo rm a Ja v a 2 W in 9 5 / N T:
Este ejemplo asume que la plataforma Java est instalada en c :\ ja v a , y los
ficheros fuente estn en c :\ ja v a \ s rc :
jdb -Xbootclasspath:c:\java\src;c:\java\jre\lib\rt.jar;c:
\java\jre\i18n.jar;. myapp
S is t e m a s Un ix :
Este ejemplo asume que la plataforma Java est instalada en / u s r/ lo c a l/ ja v a , y
los ficheros fuente estn en / u s r/ lo c a l/ ja v a / s rc .
jdb -Xbootclasspath:/usr/java/src;
/usr/java/jre/lib/rt.jar;
/usr/java/jre/i18n.jar;. myapp
La siguiente vez que ejecutemos el comando lo c a ls veremos los campos internos
de la clase que deseamos analizar.
Oz it o
Ejecutar Tests y Analizar
Si todava tenemos problemas incluso despus de haber revisado los problemas de
instalacin y de entorno y haber incluido cdigo de depuracin, es el momento de
usar herramientas para probar y analizar nuestro programa.
Trabajar Detrs de la Silla con jdb
Arrancar la Sesin
Para empezar una sesin de depurado, compilamos el programa
SimpleJdbTest.java con informacin completa de depurado usando ja v a c y la
bandera -g. En este ejemplo, el programa S im p le Jd b Te s t . ja v a es una aplicacin
pero tambin podra ser un applet. Los procedimientos para depurar aplicaciones
son iguales que para depurar applets una que se ha empezado la sesin de
depurado.
javac -g SimpleJdbTest.java
Luego arrancamos la herramienta jd b con el nombre de la clase del programa
como parmetro:
jdb SimpleJdbTest
Initializing jdb...
0xad:class(SimpleJdbTest)
Para depurar un applet en el a p p le t v ie w e r usamos el parmetro - d e b u g como en
este ejemplo:
stop in SimpleJdbTest.<init>
Breakpoint set in SimpleJdbTest.<init>
run
run SimpleJdbTest
running ...
main[1]
Breakpoint hit: SimpleJdbTest.<init>
(SimpleJdbTest:10)
La herramienta jd b se para en la primera lnea del constructor. Para listar los
mtodo que fueron llamados hasta llegar a este punto de ruptura, introducimos el
comando w h e re :
main[1] where
[1] SimpleJdbTest.<init> (SimpleJdbTest:10)
[2] SimpleJdbTest.main (SimpleJdbTest:29)
Los mtodos numerados de la lista es el ltimo marco de pila que ha alcanzado la
JVM. En este caso el ltimo marco de pula es el constructor S im p le Jd b Te s t que
fue llamado desde el S im p le Jd b Te s t main.
Siempre que se llama a un nuevo mtodo, se sita en esta lista de pila. La
tecnologa Hotspot consigue alguna de sus ganancias de velocidad elimando un
nuevo marco de pila cuando se llama a un nuevo mtodo. Para obtener una
apreciacin general de dnde se par el cdigo, introducimos el comando lis t .
main[1] list
6 Panel p;
7 Button b;
8 int counter=0;
9
10 SimpleJdbTest() {
11 setSize(100,200);
12 setup();
13 }
14 void setup (){
Localizar la Fuente
Si el fuente del fichero class parado no est disponible en el path actual, podemos
decirle a jd b donde encontrar el fuente con el comando u s e dndole el directorio
fuente como un parmetro. En el siguiente ejemplo el fuente est un subdirectorio
o carpeta llamado b o o k .
main[1] list
Unable to find SimpleJdbTest.java
main[1] use book
main[1] list
6 Panel p;
7 Button b[];
8 int counter=0;
9
10 => SimpleJdbTest() {
Buscar un Mtodo
main[1] step
main[1]
Breakpoint hit: java.awt.Frame.<init> (Frame:222)
Pero espera un minuto! Este es ahora el constructor de la clase Fra m e ! Si lo
seguimos pasaremos a travs del constructor de la clase Fra m e y no el de la clase
S im p le Jd b Te x t . Porque S im p le Jd b Te s t desciende de la clase Fra m e , el
constructor padre, que en este caso es Fra m e , es llamado sin avisarnos.
El comando step up
main[1] step up
main[1]
Breakpoint hit: SimpleJdbTest.<init>
(SimpleJdbTest:8)
El comando next
main[1] step
Breakpoint hit: SimpleJdbTest.<init>
(SimpleJdbTest:11)
main[1] list
7 Button b[]=new Button[2];
8 int counter=0;
9
10 SimpleJdbTest() {
11 setSize(100,200);<
12 setup();
13 }
14 void setup (){
15 p=new Panel();
16 }
main[1] next
Breakpoint hit: SimpleJdbTest.<init>
(SimpleJdbTest:12)
main[1] step
Breakpoint hit: SimpleJdbTest.setup (SimpleJdbTest:15)
El comando stop in
main[1] list
11 setSize(100,200);
12 setup();
13 }
14 void setup (){
15 => p=new Panel();
16 b[0]= new Button("press");
17 p.add(b[0]);
18 add(p);
19
El comando print
main[1] print p
p = null
Esto ocurre porque la lnea an no se ha ejecutado y por lo tanto al campo p no se
le ha asignado ningn valor. Necesitamos pasar sobre la sentencia de asignacin
con el comando n e x t y luego usar de nuevo el comando p rin t p .
main[1] next
El comando cont
main[1] cont
main[1]
Breakpoint hit: java.awt.Button.<init>
(Button:130)
Si la clase Bu t t o n no ha sido compilada con informacin de depurado como se
describi antes, no veremos los campos internos desde el comando p rin t .
Para limpiar este punto de ruptura y que no pare cada vez que se cree un Bu t t o n
se usa el comando c le a r. Este ejemplo usa el comando c le a r sin argumentos para
mostrar la lista de puntos de ruptura actuales, y el comando c le a r con el
argumento ja v a . a w t . Bu t t o n :1 3 0 . para borrar el punto de ruptura
ja v a . a w t . Bu t t o n :1 3 0 . .
main[1] clear
Current breakpoints set:
SimpleJdbTest:10
java.awt.Button:130
main[1] clear java.awt.Button:130
Breakpoint cleared at java.awt.Button: 130
Para mostrar los detalles de un objeto, usamos el comando p rin t para llamar al
mtodo t o S t rin g del objeto, o usar el comando d u m p para mostrar los campos y
valores del objeto.
Este ejemplo pone un punto de ruptura en la lnea 17 y usa los comandos p rin t y
d u m p para imprimir y volcar el primer objeto Bu t t o n del array de objetos Bu t t o n .
La salica del comando The d u m p ha sido abreviada.
Finalizar la Sesin
0xee2f9820:class(SimpleJdbTest)
> quit
Depuracin Remota
El jd b es un proceso de depuracin externo, lo que significa que depura el
programa envindole mensajes hacia y desde el ayudante de la mquina virtual
Java. Esto hacer muy fcil la depuracin de un programa en ejecucin, y nos ayuda
a depurar un programa que interactua con el usuario final. Una sesin de
depuracin remota desde la lnea de comandos no interfiere con la operacin
normal de la aplicacin.
Arrancar la Sesin
Antes de la versin Java 2, lo nico que se requera para permitir la depuracin
remota era arrancar el programa con la bandera - d e b u g como primer argumento,
y si la aplicacin usa libreras nativas, terminanos el nombre de la librera con una
_ g . Por ejemplo, necesitaramos una copia de la librera n a t iv e lib . d ll como
n a t iv e lib _ g . d ll para depurar con esta librera.
En Java 2, las cosas son un poco ms complicada. Necesitamos decirla a la JVM
dnde est el ficheo t o o ls . ja r usando la variable CLAS S P ATH. El fichero t o o ls . ja r
normalmente se encuentra en el directorio lib de la instalacin de la plataforma
Java.
Tambin necesitamos desactivar el compilador "Just In Time" (JIT) si existe. Este
compilador se desactiva seleccionado la propiedad ja v a . c o m p ile r a N ON E o a una
cadena vaca. Finalmente, como la opcin - c la s s p a t h sobreescribe cualquier
classpath seleccionado por el usuario, tambin necesitamos aadir el CLAS S P ATH
necesario para nuestra aplicacin.
Ponindo todo esto junto, aqu est lnea de comandos necesaria para arrancar un
programa en modo de depuracin remoto. Se pone todo en una sla lnea e
incluimos todas las clases necesarias en la lnea de comandos.
Windows:
Unix:
Listar Threads
Una vez dentro de la sesin jd b , podemos listar los threads activos actualmente,
con el comando t h re a d s , y usar el comando t h re a d < t h re a d n u m b e r> , por
ejemplo, t h re a d 7 para seleccionar un thread para analizarlo. Una vez
seleccionado un thread, usamos el comando w h e re para ver los mtodos que han
sido llamados por este thread.
Listar el Fuente
AWT-EventQueue-0[1] suspend 7
AWT-EventQueue-0[1] list
Current method is native
AWT-EventQueue-0[1] where
[1] java.lang.Object.wait (native method)
[2] java.lang.Object.wait (Object:424)
[3] java.awt.EventQueue.getNextEvent
(EventQueue:179)
[4] java.awt.EventDispatchThread.run
(EventDispatchThread:67)
AWT-EventQueue-0[1] resume 7
Finalizar la Sesin
main[1] clear
Current breakpoints set:
SimpleJdbTest:10
jdb -J-Duser.home=.
El fichero jd b . in i nos permite seleccionar los comandos de configuracin de jd b ,
como u s e , sin tener que introducir los detalles cada vez que ejecutamos jd b . El
siguiente fichero de ejemplo jd b . in i empieza una sesin jd b para la clase Fa c Te s t .
Incluye los fuentes de la plataforma Java en el path de fuentes y le pasa el
parmetro nmero 6 al programa. Se ejecuta y para en la lnea 13, muestra la
memoria libre, y espera una entrada posterior.
load FacTest
stop at FacTest:13
use /home/calvin/java:/home/calvin/jdk/src/
run FacTest 6
memory
Aqu est salida de la ejecucin del fichero jd b . in i:
$ jdb -J-Duser.home=/home/calvin/java
Initializing jdb...
0xad:class(FacTest)
Breakpoint set at FacTest:13
running ...
Free: 662384, total: 1048568
main[1]
Breakpoint hit: FacTest.compute (FacTest:13)
main[1]
Podramos peguntarnos si los ficheros jd b . in i pueden usarse para controlar una
sesin jd b completa. Desafortunadamente, los comandos en un fichero jd b . in i se
ejecutan de forma sncrona, y jd b no espera hasta que se llegue a un punto de
ruptuira para ejecutar el siguiente comando. Podemos aadir retardos artificiales
con comandos h e lp repetidos, pero no hay garanta de que el thread se suspenda
cuando necesitamos que lo haga.
jdblog
Cuando luego ejecutamos jd b o ja v a - d e b u g , veremos que la informacin de
sesin jd b se muestra de esta forma. Podemos usar esta informacin para
recuperar los puntos de ruptura y los comandos introducidos por si necesitamos
reproducir esta sesin de depuracin.
---- debug agent message log ----
[debug agent: adding Debugger agent to
system thread list]
[debug agent: adding Breakpoint handler
to system thread list]
[debug agent: adding Step handler to
system thread list]
[debug agent: adding Finalizer to
system thread list]
[debug agent: adding Reference Handler to
system thread list]
[debug agent: adding Signal dispatcher to
system thread list]
[debug agent: Awaiting new step request]
[debug agent: cmd socket:
Socket[addr=localhost/127.0.0.1,
port=38986,localport=3 8985]]
[debug agent: connection accepted]
[debug agent: dumpClasses()]
[debug agent: no such class: HelloWorldApp.main]
[debug agent: Adding breakpoint bkpt:main(0)]
[debug agent: no last suspended to resume]
[debug agent: Getting threads for HelloWorldApp.main]
Oz it o
Depurar Servlets
Podemo depurar servlets con los mismos comandos jd b usados para depurar un
applet o una aplicacin. JSDK "JavaTM Servlet Development Kit" proporciona una
programa llamado s e rv le t ru n n e r que nos permite ejecutar un servlet sin un
navegador web. En la mayora de los sistemas, este programa simplemente
ejecuta el comando ja v a s u n . s e rv le t . h t t p . Ht t p S e rv e r. Por lo tanto, podemos
arrancar la sesin jd b con la clase Ht t p S e rv e r.
Un punto importante a recordar cuando depuramos servlets es que el servidor Web
Java y s e rv le t ru n n e r realizan la carga y descargas de servlets, pero no incluyen
el directorio s e rv le t s en el CLAS S P ATH. Esto significa que los servlets se cargan
usando un cargador de clases personalizado y no por el cargador de clases por
defecto del sistema.
Ejecutar servletrunner en Modo Depuracin
Unix
$ export CLASSPATH=./lib/jsdk.jar:./examples:$CLASSPATH
Windows
$ set CLASSPATH=lib\jsdk.jar;examples;%classpath%
Para arrancar el programa servletrunner, podemos ejecutar el script de arranque
suministrado llamado s e rv le t ru n n e r o simplemente suministramos las clases
servletrunner como parmetros de jd b . Este ejemplo usa el parmetro
servletrunner.
$ jdb sun.servlet.http.HttpServer
Initializing jdb...
0xee2fa2f8:class(sun.servlet.http.HttpServer)
> stop in SnoopServlet.doGet
Breakpoint set in SnoopServlet.doGet
> run
run sun.servlet.http.HttpServer
running ...
main[1] servletrunner starting with settings:
port = 8080
backlog = 50
max handlers = 100
timeout = 5000
servlet dir = ./examples
document dir = ./examples
servlet propfile = ./examples/servlet.properties
Para ejecutar S n o o p S e rv le t en modo depuracin, introducimos la siguiente URL
donde y o u rm a c h in e es la mquina donde arrancamos el servletrunner y 8 0 8 0 es
el nmero d puerto mostrado en las selecciones de salida.
http://yourmachine:8080/servlet/SnoopServlet
En este ejemplo jd b para en la primera lnea del mtodo d o Ge t del servlet. El
navegador espera una respuesta de nuestro servlet hasta que se pase el timeout.
Thread-105[1] list
41 throws ServletException, IOException
42 {
43 PrintWriter out;
44
45 => res.setContentType("text/html");
46 out = res.getWriter ();
47
48 out.println("<html>");
49 out.println("<head>
<title>Snoop Servlet
</title></head>");
Thread-105[1]
El servlet puede continuar usando el comando c o n t .
Thread-105[1] cont
Antes:
Depus:
Aqu est como conectar remotamente con el Java Web Server. La password de
agente es generada sobre la slaida estandard desde el Java Web Server pero
puede ser redirigida a un fichero en cualquier lugar. Podemos encontrar dnde
chequeando los scripts de arranque del Java Web Server.
Agent password=3yg23k
Oz it o
Depurar Eventos AWT
Antes del nuevo mecanismo de eventos del SWT presentado en el JDK 1.1 los
eventos eran recibidos por un componente como un Te x t Fie ld , y propagado hacia
arriba a sus componentes padre. Esto significa que podra simplemente aadir
algn cdigo de diagnstico a los mtodo h a n d le Ev e n t o a c t io n del componente
para monitorizar los eventos que le han llegado.
Con la presentacin del JDK 1.1 y el nuevo sistema de la cola de eventos, los
eventos son enviados a una cola de eventos en lugar de al propio componente. Los
eventos son despachados desde la cola de Eventos del Sistema a los oyentes de
eventos que se han registrado para ser notificados cuando se despache un evento
para ese objeto.
Usar AWTEventListener
Podemo suar un AW TEv e n t Lis t e n e r para monitorizar los eventos AWT desde la
cola de eventos del sistema. Este oyente toma una mscada de evento construida
desde una operacin OR de los AW TEv e n t que queremos monitorizar. Para
obtener una simple lista de los eventos AW TEv e n t , usamos el comando ja v a p
- p u b lic ja v a . a w t . AW TEv e n t . Este ejemplo sigue la pista a los eventos de foco y
del ratn.
//EventTest.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public EventTest() {
JButton jb1=new JButton("hello");
getContentPane().add(jb1);
//AWTEventListener
getToolkit().addAWTEventListener(
new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
System.out.println(e+"\n");
}
}, AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.FOCUS_EVENT_MASK
);
}
Oz it o
Analizar la Pila
Los desarrolladores siempre han considerado un misterio el seguimiento de pila.
Hay muy poca o ninguna documentacin disponible, y cuando obtenenos una, o
necesitamos generar una, el tiempo lo prohibe. La siguiente seccin descubre los
secretos de la depuracin con seguimiento de la pila, y al final, podremos
considerar el seguimiento de pila como una herramienta til para analizar otros
programas -- no slo los que no funcionan!
Qu es un seguimiento de pila producido por la plataforma TM? Es una imagen
amigable para el usuario de los threads y monitores en la mquina virtual Java.
Dependiendo de lo compleja que sea nuestra aplicacin o applet, un seguimiento
de pila puede tener un rango desde las cincuenta lneas hasta los cientos de lneas
de diagnstico.
Sin importar el tamao del seguimiento de pila, hay unas pocas cosas importantes
que nos pueden ayudar a diagnosticar la mayora de los problemas de software sin
importar si somos expertos o nuevos en la plataforma Java.
Hay tres formas populares para generar un seguimiento de pila: enviar una seal a
la Mquina Virtual Java (JVM); la mquina virtual java genera un seguimiento de
pila por nosotros; o usar herramientas de depuracin o llamadas al API.
Enviar una Seal a la JVM
synchronized(t1) {
try {
t1.wait(); //line 33
}catch (InterruptedException e){}
}
En la versin Java 2 las operaciones de monitores, incluyendo nuestra espera aqu,
son manejadas por la mquina virtual Java a travs de una llamada JNI a
sysMonitor. La condicin de espera de un thread se mantiene en una cola de
espera de monitor especial del objeto que est esperando. Esto explica porqu
aunque seamos los nicos esperando por un objeto el cdigo todava necesita estar
sincronizado con el objeto como si estuviera utilizano de hecho el monitor de ese
objeto.
Examinar Monitores
Esto nos trae la otra parte del seguimiento de pila: el volcado de monitores. Si
consideramos que la seccin de threads de un seguimiento de pila identifica la
parte multi-thread de nuestra aplicacin, entonces la seccin de monitores
representa las partes de nuestra aplicacin que usan un slo thread.
Podra ser sencillo imaginar un monitor como un lavadero de coches. En muchos
lavaderos de coches, slo se puede lavar un coche a la vez. En nuestro cdigo Java
slo un thread a la vez puede tener el bloqueo sobre una pieza sincronizada de
cdigo. Todos los dems threads esperan en la cola para entrar al cdigo
sincronizado como lo hacen los coches para entrar en el lavadero de coches.
Se puede pensar en un monitor como un bloqueo para un objeto, y cada objeto
tiene un monitor. Cuando generamos un seguimiento de pila, los monitores se
listan como registrados o no registrados. En la mayora de los casos estos
monitores registrados, o monitores del sistema, no deberan ser la causa de
nuestro problema de software, pero nos ayudarn a entenderlos y reconocerlos. La
siguiente tabla describe los monitores registrados mas comunes:
Mo n it o r D e s c rip c i n
Bloquea el hashtable de Strings i18N
utf8 hash table definidos que fueron cargados desde la clase
constant pool.
Protege las copias de bloques de array a cdigo
JNI pinning lock
de mtodos nativos.
Bloquea la tabla de referencias globales que
contiene los valores que necesitan ser liberado
JNI global reference lock
explcitamete, y sobrevivir al tiempo de vida de
la llamada del mtodo nativo.
Bloquea el acceso a la lista de clases cargadas y
BinClass lock
resueltas. La tabla global de lista de clases.
Protege datos de clases cuando se cargan
Class linking lock libreras nativas para resolver referencias
simblicas
Asegura que slo un thread se carga en una
System class loader lock
clase del sistema a la vez.
Protege el cdigo cuando se intenta una
Code rewrite lock
optimizacin.
Protege la pila Java durante el manejo de
Heap lock
memoria de la pila.
Slo un thread puede tener acceso al monitor
Monitor cache lock cache a la vez este bloqueo asegura la
integridad del monitor cache.
Protege los threads verdes de la JVM Unix de la
Dynamic loading lock carga de librera compartida stub libdl.so ms de
uno a la vez.
Monitor IO lock Protege I/O fsica por ejemplo, abrir y leer.
Controla el acceso al controlador de seal si hay
User signal monitor una seal de usuario en un thread verde de la
JVM.
Controla accesos al proceso de informacin de
espera cuando usamos llamadas al sistema de
Child death monitor
ejecucin para ejecutar comandos locales en un
thread verde de la JVM.
Controla accesos al fichero descriptor de
I/O Monitor
threadas para eventos poll/select.
Controla accesos a un controlador de reloj usado
Alarm Monitor en threads verdes de la JVM para manejar
timeouts
Thread queue lock Protege la cola de threads activos.
Slo un thread puede tener acceso al registro de
Monitor registry monitores al mismo tiempo que este bloqueo
asegura la integridad de este registro.
Protege la lista de objetos bloqueados que han
sido recolectadas para la basura, y considera la
Has finalization queue lock *
finalizacin necesaria. Son copiados a la cola
Finalize.
Protege una lista de objetos que pueden ser
Finalize me queue lock *
finalizados por desocupados.
Protege las tablas de constantes de las JVMs y
Name and type hash table lock *
sus tipos.
Bloquea la hashtable de Strings definidos que
String intern lock *
fueron cargadas desde la clase constant pool
Asegura que slo un thread carga una clase a la
Class loading lock *
vez.
Java stack lock * Protege la lista de segmentos libres de la pila
El propio registro de monitores est protegido por un monitor. Esto significa que el
thread al que pertenece un bloqueo es el ltimo thread en usar un monitor. Es
como decir que este thread es el thread actual. Como slo un thread pueden entrar
en un bloque sincronizado a la vez, otros threads se ponen a la cola para entrar en
el cdigo sincronizado y aparecen con el estado MW . En el volcado del cach de
monitores, se denotan como threads "esperando para entrar". En el cdigo de
usuario un monitor es llamado a accin siempre que se usa un bloque o mtodo
sincronizado.
Cualquier cdigo que espere un objeto o un evento (mtodo que espera) tambin
tiene que estar dentro de un bloque sincronizado. Sin emabrgo, una vez que se
llama a este mtodo, se entrega el bloqueo sobre el objeto sincronizado.
Cuando el thread en estado de espera es notificado de un evento hacia el objeto,
teine la competencia del acceso exclusivo a ese objeto, y tiene que obtener el
monitor. Incluso cuando un thread a enviado un "notify event" a los threads que
estn esperando, ninguno de estos threads puede obtener realmente le control del
monitor bloqueado hasta que el thread notificado haya abandonado el bloque de
cdigo sincronizado
"AWT-Windows" (TID:0xf54b70,
sys_thread_t:0x875a80,Win32ID:0x67,
state:MW) prio=5
java.awt.Choice.select(Choice.java:293)
sun.awt.windows.WChoicePeer.handleAction(
WChoicePeer.java:86)
"AWT-EventQueue-0" (TID:0xf54a98,sys_thread_t:0x875c20,
Win32ID:0x8f, state:R) prio=5
java.awt.Choice.remove(Choice.java:228)
java.awt.Choice.removeAll(Choice.java:246)
El thread AW T- Ev e n t Qu e u e - 0 est en estado ejecutable dentro del mtodo
re m o v e . Re m o v e est sincronizado, lo que explca por qu el thread
AW T- W in d o w s no puede entrar al mtodo s e le c t . El thread AW T- W in d o w s est
en estado MW (monitor wait); sin embargo, sin embargo si seguimos el
seguimiento de pila, esta situacin no cambia aunque el interface grfico de
usuario (GUI) parezca estr congelado.
Esto indica que la llamada a re m o v e nunca retorn. Siguiendo el camino del
cdigo hacia la clase Ch o ic e P e e r, podemos ver que se est haciendo a un llamada
al MFC nativo que no retorna, Es aqu donde est el problema real y es un bug de
las clases corazn Java. El cdigo del usuario esta bien.
Eje m p lo 2
En este segundo ejemplo investigaremos un bug que al principio parece ser un fallo
de Swing pero descubriremos que es debido al hecho que Swing no es seguro ante
los threads.
El informa de bug tambin est disponible en la site JDCm el nmero del bug es
4098525.
Aqu tenemos un ejemplo del cdigo usado para reproducir este problem. El
dalogo modal se crea desde dentro del mtodo JP a n e l p a in t .
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
MyDialog(Frame parent) {
super(parent, "My Dialog", true);
Button okButton = new Button("OK");
okButton.addActionListener(this);
add(okButton);
pack();
}
MyDialog myDialog;
boolean firstTime = true;
void showDialogs() {
myDialog.show();
}
"AWT-EventQueue-1" (
TID:0xebca8c20, sys_thread_t:0x376660,
state:MW) prio=6
at java.awt.Component.invalidate(Component.java:1664)
at java.awt.Container.invalidate(Container.java:507)
t java.awt.Window.dispatchEventImpl(Window.java:696)
at java.awt.Component.dispatchEvent(
Component.java:2289)
at java.awt.EventQueue.dispatchEvent(
EventQueue.java:258)
at java.awt.EventDispatchThread.run(
EventDispatchThread.java:68)
Si buscamos est lnea en el fichero ja v a / a w t / Co m p o n e n t . ja v a que est
contenido en el archivo s rc . ja r, veremos esto:
at Tester.paint(Tester.java:39)
at javax.swing.JComponent.paintChildren(
JComponent.java:388)
El resto del puzzle se coloca junto analizando el mtodo MD ia lo g P e e r s h o w . El
cdigo del dilogo crea un nuevo ModalThread que es por lo que hemos visto un
thread AW T- Mo d a l en la salida del seguimiento de pila, este thread es usado para
postear el dilogo. Es cuando el evento de despacha usando AW T- Ev e n t Qu e u e - 1
que es usado para ser el proxy de despacho de eventos de AWT y es necesario un
acceso al monitor g e t Tre e Lo c k y es aqu donde tenemos el bloqueo.
Desafortunadamente el cdigo Swing no est diseado para ser seguro con los
threads por eso la solucin en este ejemplo es no crear dilogos modales desde
dentro de mtodo paint de Swing. Ya que Swing tiene que hacer cantidad de
bloqueos y clculos; que las partes de un componente ligero que necesitan ser
dibujadas deben estar fuertemente advertidas de que no incluyan cdigo
sincronizado o cdigo que puede resultar en una llamada sincronizadac como en un
dilogo modal, dentro del mtodo p a in t .
Esto completa la teoria del seguimiento de pila Java, y ahora deberamos saber qu
busar la siguiente vez que veamos un seguimiento de pila. Para ahorrar tiempo,
deberamos hacer uso de la bsqueda de Bugs del JDC para ver si nuestro
problema ha sido reportado por alguien ms.
Oz it o
Problemas de Versiones
Esta seccin proporciona una tabla que sumariza los problemas y soluciones
relacionados con la tenencia de distintas versiones de la plataforma JavaTM
instalados en nuesto sistema.
P ro d u c t o D e s a rro llo
JDK 1.0.2 Utiliza CLAS S P ATH para encontrar y cargar las clases corazn del
sistema.
En Windows 95:
CLAS S P ATH= / u s r/ ja v a / lib / c la s s e s . z ip :.
En Unix:
CLAS S P ATH= c :\ ja v a \ lib \ c la s s e s . z ip
Las libreras dinmicas Unix, los ficheros . d ll, los objetos
compartidos y fichero . s o estn localizados en la variable PATH.
Efe c t o s la t e ra le s :
El fichero Au t o e x e c . b a t de Win95 contiene una variable
CLAS S P ATH caducada seleccionad por el usuario o la instalacinde
otras aplicaciones.
El Entorno de usuario de WinNt contiene un vieja variable
CLAS S P ATH.
Los scripts Unix . c s h rc , . p ro file , o . lo g in contiene un
CLAS S P ATH errneo.
La varible de entorno JAVA_ HOME tambin es usada por
programas para comprobar si no est seleccionada. Podemos
borrar este campo en el shel Bourne (sh) de esta forma: u n s e t
JAVA_ HOME
D ia g n s t ic o s :
Usamos la opcin - c la s s p a t h para forzar a la mquina virtual Java
a que use slo la lnea de comandos. Slo CLAS S P ATH: ja v a
- c la s s p a t h c :\ ja v a \ lib \ c la s s e s . z ip ;. m y a p p
P ro d u c t o D e s a rro llo
JDK 1.1 Usa paths relativos para encontrar el fichero c la s s e s . z ip desde la
instalacin de la plataforma Java. La variable de entorno
CLAS S P ATH se usa para cargar las clases de la aplicacin.
Efe c t o s la t e ra le s :
Otras versiones Java encontradad en el path de la aplicacin
podran ser cargadas si el directorio b in del JDK no se selecciona
expltamente delante de la variable de entorno P ATH.
D ia g n s t ic o s :
Usamos la opcin - c la s s p a t h para forzar a la mquina virtual Java
a que use slo la lnea de comandos. Slo CLAS S P ATH: ja v a
- c la s s p a t h c :\ ja v a \ lib \ c la s s e s . z ip ;. m y a p p
P ro d u c t o D e s a rro llo
P ro d u c t o D e s a rro llo
Java Sobre Windows 95 y Windows NT usamos el registro para
Plug-In encontrar plug-in de la plataforma Java instalados.
Efe c t o s La t e ra le s :
El registro podra estar corrompido, o el plug-in eliminado
fsicamente pero no del registro.
D ia g n s t ic o s :
Mostrar las propiedades ja v a . v e rs io n y ja v a . c la s s . p a t h en
nuesto cdigo y verlo en la Consola del Java Plug-in Console
System.out.println("version="+System.getProperty(
"java.version"
));
System.out.println("class path="+System.getProperty(
"java.class.path"
));
Si hay un conflicto, chequeamos el registro con el comando
re g e d it , buscamos la palabra VM, y si existe la borramos y
reinstalamos el plug-in.
P ro d u c t o D e s a rro llo
P ro d u c t o D e s a rro llo
Internet Usa ficheros . c a b para contener las clases del sistema. Tambin
Explorer usa el registro del sistema sobre Windows 95/NT.
Efe c t o s La t e ra le s :
Usamos el comando re g e d it para buscar la palabra VM. Esa es la
entrada CLAS S P ATH donde podemos aadir nuestras propias
clases.
D ia g n s t ic o s :
El registro puede corromperse. Buscamos CLASSPATH usando el
programa regedit y editamos el valor al que apunta CLASSPATH.
Oz it o
Mejorar el Rendimiento por Diseo
Las restricciones del ancho de banda en las redes alrededor del mundo hacen de
las operaciones basadas en red potenciales cuellos de botella que pueden tener un
importante impacto en el rendimiento de las aplicaciones. Muchas aplicaciones de
red estn disaadas para usar almacenes de conexiones y por ello pueden
reutilizar conexiones de red existentes y ahorrar el tiempo y la sobrecarga que
conllevan el abrir y cerrar conexiones de red.
Junto con el almacen de conexiones, hay otras caractersticas que podemos disear
dentro de nuestros programas para mejorar el rendimiento. Este captulo explica
cmo podemos disear un applet para que descargue ficheros y recursos de forma
ms eficiente, o disear un programa basado en threads para usar un almacen de
threads para ahorrarnos el costoso proceso de arrancar threads.
Mejorar la Descarga de un Applet
Almacen de Threads
Image image;
image = getImage ("reply.gif");
image = getImage ("post.gif");
image = getImage ("reload.gif");
image = getImage ("catchup.gif");
image = getImage ("back10.gif");
image = getImage ("reset.gif");
image = getImage ("faq.gif");
Esta tcnica reduce el trafico de la red porque todas las imgenes estn disponibles
en un slo fichero class.
Usar imgenes XPM codificadas hace ms grande el fichero de la clase, pero el
nmero de peticiones de red es menor.
Al hacer que las definiciones de imgenes XPM formen parte del fichero class,
hacemos que el proceso de carga de imgenes sea parte de la carga normal
del fichero class del applet sin clases extras.
Una vez cargado, podemos usar las imgenes para crear botones u otros
componentes del interface de usuario. El siguiente segmento de cdigo muestra
cmo usar la imgenes con la clase ja v a x . s w in g . JBu t t o n .
Almacen de Threads
El servidor de applets Java Developer ConnectionSM (JDC) y el Java Web ServerTM
hacen un uso extensivo del almacen de threads para mejorar el rendimiento. El
almacen de threads es crear un suministro de threads durmientes al principio de la
ejecucin. Como el proceso de arranque de un thread es muy caro en trminos de
recursos del sistema, el almacen de threads hace el proceso de arrancada un poco
ms lento, pero aumenta el rendimiento en tiempo de ejecucin porque los threads
durmientes (o suspendidos) slo se despiertan cuando cuando son necesarios para
realizar nuevas tareas.
Este cdigo de ejemplo tomado de la clase Pool.java muestra una forma de
implementar la fusin de threads, En el constructor de la fusin (mostrado abajo),
se inicializan y arrancan los W o rk e rTh re a d s . La llamada al mtodo s t a rt ejecuta
el mtodo ru n del W o rk e rTh re a d , y la llamada a w a it suspende el Th re a d
mientras el Th re a d espera a que llegue un trabajo. La ltima lnea del constructor
empuja el Th re a d durmiente hacia la pila.
_max = max;
_waiting = new Stack();
_workerClass = workerClass;
Worker worker;
WorkerThread w;
for ( int i = 0; i < _max; i++ ) {
worker = (Worker)_workerClass.newInstance();
w = new WorkerThread ("Worker#"+i, worker);
w.start();
_waiting.push (w);
}
}
Junto al mtodo ru n , la clase W o rk e rTh re a d tiene un mtodo w a k e . Cuando
viene el trabajo, se llama al mtodo w a k e , que asigna los datos y notifica al
W o rk e rTh re a d durmiente (el inicializado por el P o o l) para recuperar la ejecucin.
El mtodo w a k e llama a n o t ify hace que el W o rk e rTh re a d bloqueado salga del
estado de espera, y se ejecuta el mtodo ru n de la clase HttpServerWorker. Una
vez realizado el trabajo, el W o rk e rTh re a d se pone de nuevo en el S t a c k
(asumiento que el P o o l de threads no est lleno) o termina.
if ( _data != null ){
_worker.run(_data);
}
_data = null;
stop = !(_push (this));
}
}
En este alto nivel, el trabajo entrante es manejado por el mtodo p e rfo rm W o rk
en la clase P o o l. Cuando viene el trabajo, se saca de la pila un W o rk e rTh re a d
existente (o se crea uno nuevo si el P o o l est vaco). El W o rk e rTh re a d durmiente
es activado mendiate una llamada a su mtodo w a k e .
try{
_pool = new Pool (poolSize,
HttpServerWorker.class);
}catch (Exception e){
e.printStackTrace();
throw new InternalError (e.getMessage());
}
Este cdigo est en el mtodo ru n de la clase HttpServer.java. Cada vec que viene
una peticin, el dato es inicializado y el Th re a d empieza el trabajo.
try{
Socket s = _serverSocket.accept();
Hashtable data = new Hashtable();
data.put ("Socket", s);
data.put ("HttpServer", this);
_pool.performWork (data);
}catch (Exception e){
e.printStackTrace();
}
El almacen de threads es una tcnica efectiva de ajuste de rendimiento que coloca
el caro proceso de arranque de threads en la arrancada de la aplicacin. De esta
forma, el impacto negativo en el rendimiento ocurre slo una vez durante el
arrancada del programa donde se nota menos.
Oz it o
Almacen de Conexiones
Si hemos usado SQL u otra herramienta similar para conectarnos con una base de
datos y actar sobre los datos, probablemente habremos notado que la obtenecin
de la conexin y el login es la parte que tarda ms tiempo. Una aplicacin puede
fcilmente tardar varios segundos cada vez que necesita establecer una conexin.
El varsiones anteriores a JDBCTM 2.0 cada sesin de base de datos requera una
nueva conexin y un login incluso si la conexin anterior usaba la misma tabla y
cuenta de usuario. Si estmos usando versioens anteriores al JDBC 2.0 y queremos
mejorar el rendimiento, podemos cachear las conexiones JDBC.
Las conexiones cacheadas se mantienen un objeto pool en tiempo de ejecucin y
pueden ser utilizadas y reutilizadas cuando las necesite la aplicacin. Una forma de
implementar un objeto pool es hacer una una simple hashtable de objetos
conection. Sin embargo, una forma ms sencilla de hacerlo es escribir un d riv e r
JDBC envuelto que es un intermediario entre la aplicacin y la base de datos.
La envoltura trabaja particulamente en los Beans de Enterprise que san
persistencia manejada por el Bean por dos razones: 1) Slo se carga una clase
D riv e r por cada Bean, y 2) los detalles especficos de la conexin se manejan
fuera del Bea.
Esta seccin explica cmo escribir una clase D riv e r JDBC envuelta
Clases Wrapper
Driver de Conexin
Almacen de Conexiones
Bloqueos y Cuelgues
Cerrar Conexiones
Aplicacin de Ejemplo
Clases Wrapper
El D riv e r JDBC envuelto creado para estos ejemplos consta de las siguientes
clases:
JD CCo n n e c t io n D riv e r
JD CCo n n e c t io n P o o l
JD CCo n n e c t io n
Driver de Conexin
La clase JDCConnectionDriver.java implementa el interface ja v a . s q l. D riv e r, que
proporciona mtodo para cargar drivers y crear nuevas conexiones a bases de
datos.
Un objeto JD CCo n n e c t io n Ma n a g e r es creado por una aplicacin que pretende
una conexin con una base de datos. La aplicacin proprociona el ULR para la base
de datos, el ID del usuario y la password.
El constructor JD CCo n n e c t io n Ma n a g e r hace esto:
Registra el objeto JD CCo n n e c t io n Ma n a g e r con D riv e rMa n a g e r.
DriverManager.registerDriver(this);
Class.forName(driver).newInstance();
pool = new JDCConnectionPool(url, user, password);
}
Cuando el programa llamante necesita una conexin con la base de datos, llama al
mtodo JD CCo n n e c t io n D riv e r. c o n n e c t , que a su vez, llama al mtodo
JD CCo n n e c t io n P o o l. g e t Co n n e c t io n .
Almacen de Conexiones
La clase JDCConnectionPool.java tiene conexiones disponibles para el programa
llamando en su mtodo g e t Co n n e c t io n . Este mtodo busca una conexin
disponible en el almacen de conexiones. Si no hay ninguna disponible, crea una
nueva conexin. Si hay una conexin disponible en el almacen, el mtodo
g e t Co n n e c t io n alquila la conexin y la devuelve al programa llamante.
Bloqueos y Cuelgues
Mientras que muchos clientes y servidores de bases de datos tiene formas de
manejar los bloqueos y los cuelgues y no tenemos que preocuparnos de escribir
cdigo para manejar estas situaciones, muchos de los nuevos modelos de base de
datos ligeros distribuidos no estn tan bien equipados. La clase conection pool
proporciona una cosechador de conexiones muerta para manejar dichas
situacciones.
La clase ConnectionReaper decide que una clase est muerta cuando se cumplen
las siguientes condiciones:
La conexin est marcada como que est en uso.
El chequeo de validacin ejecuta una simple consulta SQL sobre la conexin para
ver si lanza una excepcin. En este ejemplo, el mtodo de validacin solicita una
descripcin de alto nivel de las tablas de la base de datos. Si una conexin falla el
test de validacin, se cierra, se inicia una nueva conexin con la base de datos y se
aade al almacen de conexiones.
Cerrar Conexiones
La conexines devuelta al almacen de conexiones cuando el programa llamante
llama al mtodo JD CCo n n e c t io n . c lo s e en su clasulafin a lly .
Aplicacin de Ejemplo
Usamos un almacen de conexiones en una aplicacin de forma similar a como
usaramos cualquiere otro driver JDBC. Aqu est el cdigo de un RegistrationBean
controlado por el Bean. Este Re g is t ra t io n Be a n se ha adaptado desde la casa de
subastas de JavaBeans enterprise descrito en los coatulo 1 -3.
Cuando se crea el primer objeto Re g is t ra t io n Be a n , crea un ejemplar esttico de
la clase JD CCo n n e c t io n D riv e r. Este objeto driver esttico se registra a s mismo
con el D riv e rMa n a g e r en el constructor JD CCo n n e c t io n D riv e r poniendo
disponibles la solicitudes de conexiones para todos los objetos Re g is t ra t io n Be a n
creados por la aplicacin cliente.
Pasar la URL como jd b c :jd c :jd c p o o l en el mtodo g e t Co n n e c t io n permite que el
D riv e rMa n a g e r corresponda la g e t Co n n e c t io n solicitada al driver registrado. El
D riv e rMa n a g e r usa un sencillo S t rin g para encontrar un driver disponible que
pueda manejar URLs en ese formato.
Oz it o
Caractersticas y Herramientas de Rendimiento
La nueva Mquina Virtual JavaTM (JVM) tiene caractersticas para mejorar el
rendimiento, y podemos usar un nmero de herramientas para incrementar el
rendimiento de la aplicacin o reducir el tamao de los ficheros Class generados.
Por eso las caractersticas y herramientas mejoran el rendimiento de nuestra
aplicacin con muy pocos o casi ningn cambio en en nuestra aplicacin.
Caractersticas de la Mquina Virtual Java
Compiladores Just-In-Time
Herramientas de Terceras Partes
Mtodos en Lnea
int counter=0;
public void method1() {
for(int i=0;i<1000;i++)
addCount();
System.out.println("counter="+counter);
}
Sincronizacin
class MyLock {
for(int i=0;i<5000;i++ ) {
ml.letslock();
}
System.out.println("Time taken="+
(System.currentTimeMillis()-time));
}
}
Java Hotspot
Compiladores Just-In-Time
La herramienta ms sencilla para mejorar el rendimiento de nuestra aplicacin el
compilador Just-In-Time (JIT). Un JIT es un generador de cdigo que convierte los
bytecodes Java en cdigo nativo de la mquina. Los programas Java invocados con
un JIT generalmente se ejecutan ms rpidos que cuando se ejecutan en
bytecodes por el intrprete. La Java Hotspot VM elimina la necesidad de un
compilador JIT en muchos casos, sin embargo podran utilizar el compilador JIT en
versiones anteriores.
El compilador JIT se puso disponible como una actualizacin de rendimiento en la
versin Java Development Kit (JDKTM) 1.1.6 y ahora es una herramienta estndard
invocada siempre qu eusamos el intrprete ja v a en la versin de la plataforma
Java 2. Podemos desactivar el uso del compilador JIT usando la opcin
- D ja v a . c o m p ile r= N ON E en la JVM.
Cuando se llama a un mtodo por primera vez el compilador JIT compilad el bloque
del mtodo a cdigo nativo y lo almacena en un bloque de cdigo.
Una vez que el cdigo ha sido compilado se activa el bit
ACC_ MACHI N E_ COMP I LED , que es usado en la plataforma Sun.
Unix:
export JIT_ARGS="trace exclude(InlineMe.addCount
InlineMe.method1)"
$ java InlineMe
Initializing the JIT library ...
DYNAMICALLY COMPILING java/lang/System.getProperty
mb=0x63e74
DYNAMICALLY COMPILING java/util/Properties.getProperty
mb=0x6de74
DYNAMICALLY COMPILING java/util/Hashtable.get
mb=0x714ec
DYNAMICALLY COMPILING java/lang/String.hashCode
mb=0x44aec
DYNAMICALLY COMPILING java/lang/String.equals
mb=0x447f8
DYNAMICALLY COMPILING java/lang/String.valueOf
mb=0x454c4
DYNAMICALLY COMPILING java/lang/String.toString
mb=0x451d0
DYNAMICALLY COMPILING java/lang/StringBuffer.<init>
mb=0x7d690
<<<< Inlined java/lang/String.length (4)
Observa que los mtodos en lnea como S t rin g . le n g t h est exentos. El metodo
S t rin g . le n g t h tambin es un mtodo especial y es normalmente compilado en un
atajo de bytecodes interno para el intrprete java. Cuando usamos el compilador
JIT ests optimizaciones proporcionadas por el intrprete Java son desactivadas
para activar el compilador JIT para entender qu mtodo est siendo llamado.
javac MyClass.java
java -Djava.compiler=NONE MyClass
o
javac MyClass.java
java -Djava.compiler="" MyClass
Oz it o
Anlisis de Rendimiento
Otra forma de aumentar el rendimiento es con nalisis de rendimiento. Los anlisis
de rendimientos buscan las ejecucin del programa apuntar donde podran estar
los cuellos de botella y otros problemas de rendimiento como los picos de
memoria. Una vez que sables donde estn los puntos de problemas potenciales
podemos cambiar nuestro cdigo para eliminar o reducir su impacto.
Perfilado
Analizar un Programa
Herramientas de Rendimiento del Sistema Operativo
Perfiles
Las Mquinas Vituales JavaTM (JVMs) han tenido la habilidad de proporcionar
sencillos informes de perfiles desde Java Development Kit (JDKTM) 1.0.2. Sin
embargo, la informacin que ellos proporcionaban estaban limitadas a una lista de
los mtodos que un programa haba llamado.
La plataforma Java 2 proporciona muchas ms capacidades de perfilado que las
anteriormente disponibles y el anlisis de estos datos generado se ha hecho ms
fcil por la emergencia de un "Heap Analysis Tool" (HAT). Esta herramienta, como
implica su nombre, nos permite analizar los informes de perfiles del heap. El heap
es un bloque de memoria que la JVM usa cuando se est ejecutando. La
herramienta de anlisis de heap nos permite generar informes de objetos que
fueron usado al ejecutar nuestra aplicacin. No slo podemos obtener un listado de
los mtodos llamados ms frecuentemente y la memoria usada en llamar a esos
mtodos, pero tambin podemos seguir los picos de memeoria. Los picos de
memoria pueden tener un significante impacto en el rendimiento.
Analizar un Programa
Para analizar el programa Ta b le Ex a m p le 3 incluido en el directorio
d e m o / jfc / Ta b le de la plataforma Java 2, necesitamos generar un informe de
perfil. El informa ms sencillo de generar es un perfil de texto. Para generarlo,
ejecutamos la aplicacin el parmetro - Xh p ro f. En la versin final de la plataforma
Java 2, esta opcin fue renombrada como - Xru n h p ro f. Para ver una lista de
opciones actualmente disponibles ejecutamos el comando:
java -Xrunhprof:help
Hprof usage: -Xrunhprof[:help]|[<option>=<value>, ...]
N o m b re d e Op c i n y Va lo r D e s c rip c i n P o r D e fe c t o
-------------------------- --------------- ---------------
h e a p = d u m p | s it e s | a ll h e a p p ro filin g a ll
c p u = s a m p le s | t im e s | o ld CP U u s a g e o ff
m o n it o r= y | n m o n it o r c o n t e n t io n n
fo rm a t = a | b a s c ii o r b in a ry o u t p u t a
file = < file > w rit e d a t a t o file ja v a . h p ro f( . t x t fo r a s c ii)
s e nd da ta o ve r a
n e t = < h o s t > :< p o rt > w rit e t o file
s o cke t
d e p t h = < s iz e > s t a c k t ra c e d e p t h 4
c u t o ff= < v a lu e > o u t p u t c u t o ff p o in t 0 .0 0 0 1
lin e n o = y | n lin e n u m b e r in t ra c e s y
t h re a d = y | n t h re a d in t ra c e s ? n
do e = y| n d u m p o n e x it ? y
La siguiente invocacin crea una fichero de texto que podemos ver sin la
herramienta de anlisis de heap llamado ja v a . h p ro f. t x t cuando el programa
genera un seguimiento de pila o sale. Se utiliza una invocacin diferente para crear
un fichero binario para usarlo con la herramienta de anlisis de heap:
Elegimos un fichero que pueda manejar grandes ficheros y vamos hasta el final del
fichero. Podra haber cientos o miles de lneas, por eso un atajo es buscar las
palabras S I TES BEGI N . Veramos una lista de lnea que empezaran un tango
creciente de nmeros seguido por dos nmeros de porcentaje. La primera entrada
en la lista sera similar a este ejemplo:
SITES BEGIN (ordered by live bytes)
Sun Dec 20 16:33:28 1998
p e rc e n t liv e alloc'ed s t a c k c la s s
ra n k s e lf a ccum byte s o b js b y t e s o b js t ra c e n a m e
1 5 5 .8 6 % 5 5 .8 6 % 8 2 6 5 1 6 5 826516 5 3981 [S
La notacin [ S al final de la ltima lnea indica que es la primera entrada de un
array de s h o rt , un tipo primitivo. Esto es lo esperado con aplicaciones (AWT). Los
primeros cinco contadores bajo la cabecera o b js significa que actualmente hay
cinco de esos arrays, y slo ha habido cinco durante el tiempo de vida de esta
aplicacin, y han ocupado 826516 bytes. La referencia clase de este objeto es el
valor listado bajp s t a c k t ra c e . Para encontrar donde se creo est objeto en este
ejmplo, buscamos TRACE 3 9 8 1 . Veremos esto:
TRACE 3981:
java/awt/image/DataBufferUShort.<init>(
DataBufferUShort.java:50)
java/awt/image/Raster.createPackedRaster(
Raster.java:400)
java/awt/image/DirectColorModel.
createCompatibleWritableRaster(
DirectColorModel.java:641)
sun/awt/windows/WComponentPeer.createImage(
WComponentPeer.java:186)
El cdigo Ta b le Ex a m p le 3 selecciona un s c ro llp a n e de 700 por 300. Cuando
miramos el fuente de Ra s t e r. ja v a , qu est en el fichero s rc . ja r, encontraremos
estas sentencias en la lnea 400:
case DataBuffer.TYPE_USHORT:
d = new DataBufferUShort(w*h);
break;
Los valores w y h son la anchura y altura de la llamada a c re a t e I m a g e que
arranca en TRACE 3 9 8 1 . El constructor D a t a Bu ffe rUS h o rt crea un array de
s h o rt s :
Esta herramienta puede analizar los mismos datos que nosotros, pero requere un
fichero de informe binario como entrada. Podemos generar un fichero de informa
binario de esta forma:
java -Xrunhprof:file=TableExample3.hprof,format=b
TableExample3
Para generar el informe binario, cerramos la ventana Ta b le Ex a m p le 3 . El fichero
de informe binario Ta b le Ex a m p le 3 . h p ro f se crea al salir del programa. La
Herramienta de Anlisis de Heap arranca un servidor HTTP que analiza el fichero de
perfil binario y muestra el resultado en un HTML que podemos ver en un
navegador.
Podemos obtener una copia de la Herramienta de Anlisis de Heap de la site
java.sun.com. Una vez instalado, ejecutamos los scripts shell y batch en el
directorio b in instalado para poder ejecutar el servidor de la Herramienta de
Anlisis de Heap de esta forma:
>hat TableExample3.hprof
Started HCODEP server on port 7000
Reading from /tmp/TableExample3.hprof...
Dump file created Tue Jan 05 13:28:59 PST 1999
Snapshot read, resolving...
Resolving 17854 objects...
Chasing references,
expect 35 dots.......................
Eliminating duplicate
references.........................
Snapshot resolved.
Server is ready.
La salida de arriba nos dice que nuestro servidor HTTP se ha arrancado en el
puerto 7000. Para ver este informe introducimos la URL http://localhost:7000 o
http://your_machine_name:7000 en nuestro navegador Web. Si tenemos
problema en arrancar el servidor usando el script, podemos alternativamente
ejecutar la aplicacin incluyendo el fichero de clases h a t . z ip en nuestro
CLAS S P ATH y usar el siguiente comando:
Instances of java.util.SimpleTimeZone
class java.util.SimpleTimeZone
java.util.TimeZoneData.<clinit>(()V) :
TimeZone.java line 1222
java.util.TimeZone.getTimeZone((Ljava/lang/String;)
Ljava/util/TimeZone;) :
TimeZone.java line (compiled method)
java.util.TimeZone.getDefault(
()Ljava/util/TimeZone;) :
TimeZone.java line (compiled method)
java.text.SimpleDateFormat.initialize(
(Ljava/util/Locale;)V) :
SimpleDateFormat.java line (compiled method)
En este ejemplo el objeto fue asignado desde Tim e Zo n e . ja v a . El fichero fuente de
este fichero estn el fichero estndard s rc . ja r, y examinando este fichero,
podemos ver que de hehco hay cerca de 300 de estos objetos en memoria.
Plataforma Solaris
developer$ sar 1 10
15573: execve("/usr/local/java/jdk1.2/solaris/
bin/java", 0xEFFFF2DC,
0xEFFFF2E8) argc = 4
15573: open("/dev/zero", O_RDONLY) = 3
15573: mmap(0x00000000, 8192,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE, 3, 0) = 0xEF7C0000
15573: open("/home/calvin/java/native4/libsocket.so.1",
O_RDONLY) Err#2 ENOENT
15573: open("/usr/lib/libsocket.so.1",
O_RDONLY) = 4
15573: fstat(4, 0xEFFFEF6C) = 0
15573: mmap(0x00000000, 8192, PROT_READ|PROT_EXEC,
MAP_SHARED, 4, 0) = 0xEF7B00 00
15573: mmap(0x00000000, 122880, PROT_READ|PROT_EXEC,
MAP_PRIVATE, 4, 0) = 0xEF7 80000
15573: munmap(0xEF78E000, 57344) = 0
15573: mmap(0xEF79C000, 5393,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED, 4, 49152)
= 0xEF79C000
15573: close(4) = 0
En la salida de t ru s s , buscamos los ficheros que fallaran al abrirlos debido a
problemas de acceso, como un error EN OP ERM, o un error de fichero
desaparecido EN OEN T. Tambin podemos seguir los datos leidos o escrito con los
parmetros de t ru s s : - ra ll para seguir todos los datos ledos, o - w a ll para seguir
todos los datos escritos por el programa. Con estos parmetros, es posible analizar
datos enviados a travs de la red o a un disco local.
Plataforma Linux
Linux tiene un comando trace llamado s t ra c e . Sigue las llamadas del sistema al
kernel Linux. Este ejemplo sigue el ejemplo S p re a d S h e e t del directorio demo del
JDK:
$ strace -f -o /tmp/output
java sun.applet.AppletViewer
example1.html
$ cat /tmp/output
639 execve("/root/java/jdk117_v1at/java/
jdk117_v1a/bin/java", ["java",
"sun.applet.AppletViewer ",
"example1.html"], [/* 21 vars */]) = 0
639 brk(0) = 0x809355c
639 open("/etc/ld.so.preload", O_RDONLY) = -1
ENOENT (No such file or directory)
639 open("/etc/ld.so.cache", O_RDONLY) = 4
639 fstat(4, {st_mode=0, st_size=0, ...}) = 0
639 mmap(0, 14773, PROT_READ, MAP_PRIVATE,
4, 0) = 0x4000b000
639 close(4) = 0
639 open("/lib/libtermcap.so.2", O_RDONLY) = 4
639 mmap(0, 4096, PROT_READ, MAP_PRIVATE,
4, 0) = 0x4000f000
Para obtener informacin del sistema similar al comando s a r de Solaris, lee los
contenidos del fichero / p ro c / s t a t . El formato de este fichero se describe en las
pginas del manual p ro c . Miramos la lnea c p u para obtener la hora del sistema de
usuario:
Plataforma Windows95/98/NT
Oz it o
Cach en Aplicaciones Cliente/Servidor
El cach es una de las primera tcnicas usadas para aumetnar el rendimiento de navegadores y servidores web. El cach del navegador hace innecesarios los bloqueos de red
porque una copia reciente del fichero se mantiene en el cach local, y el cach del servidor reduce el coste de la carga de ficheros desde disco para cada peticin. Esta seccin
explica cmo podes usar el cach de forma similar para mejorar el rendimiento en muchas aplicaciones cliente/servidor escritas en lenguaje JavaTM.
El API ja v a . u t il. Co lle c t io n s disponible en el SDK Java 2 hace sencilla la implementacin del cach. Este API proporciona la clase Ha s h Ma p , que funciona bien para cachear un
objeto, y la clase Lin k e d Lis t , que funciona bien en combinaciones con la clase Ha s h Ma p para cachear muchos objetos.
Cach de un Objeto
Cach de un Objeto
Un objeto Ha s h Ma p almacena objetos en una pareja clave valor. cuando ponemos un datp en un Ha s h Ma p , le asignamos una clave y luego usamos esa clave para recuperar el
dato.
Un objeto Ha s h Ma p es muy similar a un Ha s h t a b le y puede ser usado para mantener una copia temporal de resultados generados prviamente. Los objetos mantenidos en el
cach Ha s h Ma p podra, por ejemplo, ser una lista de subastas completadas.
En este caso, los resultados de una consulta JDBC podran solicitarse cientos de veces en un segundo por personas que estn esperando conocer la puja ms alta, pero la lista de
resultados completa slo cambia una vez por minuto cuando se ompleta una subasta. Podemos escribir nuestro programa para recuperar los objetos que no han cambiado desde el
cach de resultados en vez de solicitar a la base de datos cada vez y obtener un significante aumento de rendimiento.
Este ejemplo de cdigo ejecuta una consulta a la base de datos por cada minuto, y devuelve copias cacheadas para las solicitudes que vienen entre consultas.
import java.util.*;
import java.io.*;
class DBCacheRecord {
Object data;
long time;
public DBCache() {
cache = new HashMap();
}
Si el cach no est lleno y el objeto a inserta ya est en el cach, se mueve a la parte superior del cach.
Si el cach est lleno y se inserta un nuevo objeto, el ltimo objeto del cach es eliminado y el nuevo objeto se pone en la parte superior de la lista.
Este diagrama muestra cmo trabajan juntos Lin k e d Lis t y Ha s h Ma p para implementar las operaciones descritas arriba.
Ca c h MRU c o n Lin k e d Lis t y Ha s h Ma p
El Lin k e d Lis t proporciona el mecanismo de cola, y las entradas de la Lin k e d Lis t contienen la clave de los datos en el Ha s h Ma p . Para aadir una nueva entrada en la parte
superior de la lista, se llama al mtodo a d d Firs t .
Si la lista ya est llena, se llama al mtodo re m o v e La s t y a entrada de datos tambin se elimina del Ha s h Ma p .
Si una entrada ya existe en la lista, se elimina con una llamada al mtodo re m o v e y se inserta en la parte superior de la lista con una llamada al mtodo a d d Firs t .
El API Collectios no implementa bloqueos, por eso si eliminados o aadimos entradas a objetos Lin k e d Lis t o Ha s h Ma p , necesitamos bloquear los accesos a esos objetos. Tambin
podemos usar un Ve c t o r o Arra y Lis t para obtener el mismo resultado mostrado en el cdido de abajo del Lin k e d Lis t .
Este ejemplo de cdigo usa un cach MRU para mantener un cach de ficheros cargados desde disco. Cuando se solicita un fichero, el programa chequea para ver si el fichero est
en el cach. Si el fichero no est en el cach, el programa lee el fichero desde el disco y sita una copia en el cach al principio de la lista.
Si el fichero est en el cach, el programa compara la fecha de modificacin del fichero y la entrada del cach.
Si la entrada del cach es ms vieja, el programa lee el fichero del disco, elimina la copia del cach, y sita una nueva copia en el cach en la parte superior del Lin k e d Lis t .
Si el fichero es ms viejo que el cach, el programa obtiene el fichero del cach y mueve la copia del cach a la parte superior de la lista.
import java.util.*;
import java.io.*;
class myFile {
long lastmodified;
String contents;
Map cache;
LinkedList mrulist;
int cachesize;
try {
BufferedReader br=new BufferedReader(
new FileReader(f));
String line;
Oz it o
Desplegar la Aplicacin Subasta
Con la aplicacin subasta testeada, depurada y ajustada, estamos listos para
desplegarla. Desplegarla implica unir todos los ficheros de la aplicacin, moverlos a
sus localizaciones, instalar el Java Plug-In para que los administradores de la
subasta puedan ejecutar el applet Administration desde sus navegadores, e instalar
el fichero de polica del applet Administration. El Java Plug-In es necesario porque
el applet Administration est escrito con el Java Development Kit (JDKTM) 1.2, pero
los navegadores de los administradores podran ejecutar versiones anteriores del
software Java Runtime EnvironmentTM (JRE).
Este captulo explica como usar el formato de ficheros Java Archive (JAR) para unir
los ficheros de la aplicacin, y cmo instalar el Java Plug-In y un fichero de policia
de seguridad para las plataformas SolarisTM y Win32 para ejecutar el applet
Administration.
Formato de Ficheros Java Archive (JAR)
Plataforma Solaris
Plataforma Win32
Tienes Prisa?
Esta tabla contiene enlaces directos a los tpicos especficos.
T p ic o S e c c i n
Formato de Ficheros JAR Unir y Desplegar Ficheros HTML
Unir y Desplegar los Beans Enterprise
Unir y Desplegar el Applet Administration
Plataforma Solaris Obtener las Descargas
Extraer los Ficheros Descargados
Instalar Java Plug-In
Instalar las Mejoras del Java Plug-In
Instalar Netscape Communicator
Chequear la Instalacin
Convertir Ficheros HTML
Fichero de Polica de Seguridad
Ejecutar el Applet Administration
Plataforma Win32 Descargar e Instalar
Convertir Ficheros HTML
Ficheros de Polica de Seguridad
Ejecutar el Applet Administration
Oz it o
Formato de Ficheros JAR
El formato de ficheros Java JAR es un formato de compresin y empaquetado de
ficheros y una herramienta para unir ficheros ejecutables con otros ficheros
relacionados con la aplicacin por eso pueden desplegarse en una sla unidad. La
aplicacin de subasta, tiene tres unidades o ficheros para desplegar en tres
diferentes localizaciones.
1. Los ficheros HTML que crean el interface de usuario de la aplilcacin
desplegado en una localizacin accesible bajo el servidor web.
2. Los Beans Enterprise desplegado en una localizacin interna accesible a
nuestro servidor de JavaBeans EnterpriseTM.
3. El Applet Administration desplegado a una localizacin interna accesible para
los administradores de la subasta donde es ejecutado por sus navegadores
Esta seccin nos muestra cmo usar la herramienta ja r unir y desplegar los
ficheros de la aplicacin.bundle and deploy the application files.
Unir y Desplegar los Ficheros HTML
close.html
details.html
index.html
juggler.med.gif
new.html
registration.html
search.html
sell.html
Aqu est el comando ja r que los une. Todo va en un slo fichero. Este comando se
ejecuta en el mismo directorio que los ficheros. Si lo ejecutamos desde otro
directorio distinto tenemos que especificar el path completo o relativo segn
corresponda.
kq6py% jar
Usage: jar {ctxu}[vfm0M] [jar-file] [manifest-file]
[-C dir] files ...
Options:
-c create new archive
-t list table of contents for archive
-x extract named (or all) files from archive
-u update existing archive
-v generate verbose output on standard output
-f specify archive file name
-m include manifest information from specified
manifest file
-0 store only; use no ZIP compression
-M Do not create a manifest file for the entries
-C change to the specified directory and include
the following file
If any file is a directory then it is processed
recursively. The manifest file name and the archive
file name needs to be specified in the same order
the 'm' and 'f' flags are specified.
jar xf HTML.jar
Paquete auction
Aqu estn los ficheros de aplicacin del paquete a u c t io n que crean el servlet
Au c t io n S e rv le t y el Bean Enterprise Au c t io n I t e m Be a n . Como todos ellos van a
ser instalados en un directorio a u c t io n accesible del servidor de produccin
JavaBeans Enterprise, los unimos todos juntos para que puedanser
desempaquetados en un paso en el directorio destino y situados en el subdirectorio
a c u t io n .
auction.AuctionServlet.class
auction.AuctionItem.class
auction.AuctionItemBean.class
auction.AuctionItemHome.class
auction.AuctionItemPK.class
auction.DeploymentDescriptor.txt
AuctionItemBeanHomeImpl_ServiceStub.class
WLStub1h1153e3h2r4x3t5w6e82e6jd412c.class
WLStub364c363d622h2j1j422a4oo2gm5o.class
WLSkel1h1153e3h2r4x3t5w6e82e6jd412c.class
WLSkel364c363d622h2j1j422a4oo2gm5o.class
Aqu est cmo unirlos. Toda va en una lnea lnea, y el comando se ejecuta un
directorio por encima de donde se encuentran los ficheros class.
Unix:
jar cvf auction.jar auction/*.class
Win32:
jar cvf auction.jar auction\*.class
Una vez que el fichero JAR se ha copiado en el directorio de destino para los Beans
Enterprise, lo desempaquetamos de esta forma. La extraccincrea un directorio
a u c t io n con los ficheros class denrtro.
jar xv auction.jar
Paquete registration
registration.RegistrationBean.class
registration.RegistrationHome.class
registration.RegistrationPK.class
auction.DeploymentDescriptor.txt
RegistrationBeanHomeImpl_ServiceStub.class
WLStub183w4u1f4e70p6j1r4k6z1x3f6yc21.class
WLStub4z67s6n4k3sx131y4fi6w4x616p28.class
WLSkel183w4u1f4e70p6j1r4k6z1x3f6yc21.class
WLSkel4z67s6n4k3sx131y4fi6w4x616p28.class
Aqu est como unirlo. Todo va en una lnea y el comando se ejecuta un directorio
por encima de donde se encuentran los ficheros class.
Unix:
jar cvf registration.jar registration/*.class
Win32:
jar cvf registration.jar registration\*.class
Una vez que el fichero JAR seha copiado al directorio de destino para los Beans
Enterprise, los desempaquetamos de esta forma. La extraccin crea un directorio
re g is t ra t io n con los fichero class dentro de l.
jar xv registration.jar
Paquete bidder
bidder.BidderHome.class
bidder.BidderBean.class
auction.DeploymentDescriptor.txt
BidderBeanEOImpl_ServiceStub.class
BidderBeanHomeImpl_ServiceStub.class
WLStub1z35502726376oa1m4m395m4w5j1j5t.class
WLStub5g4v1dm3m271tr4i5s4b4k6p376d5x.class
WLSkel1z35502726376oa1m4m395m4w5j1j5t.class
WLSkel5g4v1dm3m271tr4i5s4b4k6p376d5x.class
Unix:
jar cvf bidder.jar bidder/*.class
Win32:
jar cvf bidder.jar bidder\*.class
Una vez que el fichero JAR se ha copiado en el directorio de destino para los Beans
Enterprise, lo desempaquetamos de esta forma. La extraccin crea un directorio
b id d e r con los ficheros class dentro de l.
jar xv bidder.jar
Paquete seller
Aqu estn los ficheros de la aplicacin en el paquete s e lle r que crea el Bean
Enterprise S e lle r.
seller.Seller.class
seller.SellerHome.class
seller.SellerBean.class
auction.DeploymentDescriptor.txt
SellerBeanEOImpl_ServiceStub.class
SellerBeanHomeImpl_ServiceStub.class
WLStub3xr4e731e6d2x3b3w5b693833v304q.class
WLStub86w3x4p2x6m4b696q4kjp4p4p3b33.class
WLSkel3xr4e731e6d2x3b3w5b693833v304q.class
WLSkel86w3x4p2x6m4b696q4kjp4p4p3b33.class
Unix:
jar cvf seller.jar seller/*.class
Win32:
jar cvf seller.jar seller\*.class
Una vez que el fichero JAR se ha copiado en el directorio de destino para los Beans
Enterprise, lo desempaquetamos de esta forma. La extraccin crea un directorio
s e lle r con los ficheros class dentro de l.
jar xv seller.jar
Unix:
jar cvf applet.jar admin/*.class polfile.java
Win32:
jar cvf applet.jar admin\*.class polfile.java
Para desplegar el applet, copiamos el fichero a p p le t . ja r en el directorio de destino
del applet y los extraemos de esta forma. La extraccin crea un directorio a d m in
con los ficheros del applet Administration dentro de l.
jar xf applet.jar
N o t a : El applet usa los APIs JDK 1.2. Necesita un fichero de polica para
acceder a la impresora y Java Plug-In para ejecutarse en un navegador
pre-JDK 1.2 . Puedes encontrar informacin sobre cmo ejecutar el
applet con Java Plug-In y un fichero de polica en las siguientes pginas
Plataforma Solaris y Plataforma Win32.
Oz it o
Plataforma Solaris
El software Plug-In de JavaTM nos permite dirigir applets o componentes JavaBeansTM en
pginas de una intranet para que se ejecuten usando el Java Runtime Environment
(JRE) en lugar de la mquina virtual por defecto del navegador. El Java Plug-In funciona
con Netscape Communicator y Microsoft Internet Explorer.
Descarga todo el software que necesites instalar y usa el Java Plug-In que est
disponible desde la pgina de download.
Obtener las Descargar
Extraer los Ficheros Descargados
Instalar el Java Plug-In
Instalar la Mejoras del Java Plug-In
Instalar Netscape Communicator
Chequear la Instalacin
Convertir Ficheros HTML
Ficheros de Polica de Seguridad
Tipos de Ficheros de Polica
Instalar el Fichero de Polica
Cambiar el Nombre o la Posicin
Ejecutar el Applet Administration
Get Downloads
Para istalar y usar el Java Plug-In en SolarisTM 2.6 o Solaris 7, necesitamos las
siguientes descargar. Ponemos las descargar en cualquier directorio que querramos.
Java Plug-In para Sistemas Operativos Solaris. Esta disponible para plataformas
Intel o Sparc.
Patches Java Plug-In para Solaris 2.6 o Solaris 7, dependiendo de la que
tengamos.
Netscape Communicator 4.5.1 (versn webstart).
Estas instrucciones se probarn sobre una Sun Microsystems Ultra 2 ejecutando Solaris
2.6 con Netscape Communicator 4.5.1.
plugin-12-webstart-sparc/Java_Plug-in_1.2.2/
common/Docs/en/Users_Guide_Java_Plug-in.html
La gua de usuario explica cmo instalar el Java Plug-In. Hay varias formas sencillas de
hacerlo, y la secuencia de comandos de abajo es una forma rpida de instalar Java
Plug-In en el directorio por defecto / o p t / N S CP c o m usando el comando p k g a d d :
su
<root password>
cd ~/plugin-12-webstart-sparc
pkgadd -d ./Java_Plug-in_1.2.2/sparc/Product
cd ~/JPI1.2-Patches-Solaris2.6-sparC
su
<password>
kq6py#ls
105210-19 105490-07 105568-13
kq6py#./105210-19/installpatch 105210-19
Veremos esta salida cuando la mejora se haya instalado satisfactoriamente:
cd ~/NETSCAPE/Netscape_Communicator_4.51/sparc/Product
su
<password>
pkgadd -d .
Chequear la Instalacin
Hay dos formas de chequear nuestra instalacin del Java Plug-In, las mejoras y
Netscape Communicator.
1. Abrir el men de ayuda de Netscape y seleccin About Plug_Ins. Veremos una lista
de los tipos Mime. Chequeamos esta lista contra la lista presente en la gua de
usuario. Si nuestros tipos mime son correctos, la instalacin est correcta y
completa.
2. Arrancamos el applet del panel de control, cargando el fichero
/ o p t / N S CP c o m / j2 p i/ Co n t ro lP a n e l. h t m l. Si el applet arranca la instalacin es
correcta y completa.
El applet de control nos permite cambiar valores por defecto usado en el arranque del
Java Plug-In. Todos los applets ejecutados dentro del Java Plug-In usan esos valores.
cd /opt/NSCPcom/j2pi
ControlPanel &
podemos cambiar el nombre y/o la localizacin de los ficheros de polica del sistema o
de usuario por defecto. Editamos los ficheros jd k 1 . 2 / jre / lib / s e c u rit y / ja v a . s e c u rit y
o jre 1 . 2 / lib / s e c u rit y / ja v a . s e c u rit y y le aadimos una tercera entrada especificando
el nombre y la localizacin del fichero de polica alternativo.
policy.url.1=
file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
policy.url.3=file:/<mypolicyfile path and name>
cp admin.jar /home/zelda/public_html
jar xf applet.jar
La extraccin sita el fichero de polica bajo p u b lic _ h t m l y crea un directorio a d m in
bajo el directorio p u b lic _ h t m l con el fichero class del applet dentro. Renombramos el
fichero de polica del directorio p u b lic _ h t m l como . ja v a . p o lic y y lo copiamos en
nuestro directorio home.
En el directorio p u b lic _ h t m l, creamos un fichero HTML que invoque al applet
Administration. Nos debemos asegurar de incluir el directorio a d m in cuando
especifiquemos la opcin COD E del applet. Observamos que cuando usamos Java
Plug-In, no podemos hacer que el navegador carge el fichero class desde el fichero JAR.
<HTML>
<BODY>
<APPLET CODE=admin/AdminApplet.class
WIDTH=550
HEIGHT=150>
</APPLET>
</BODY>
</HTML>
Arrancamos el HTML Converter.
java HTMLConverter
En el interface grfico de usuario del HTML Converter graphical, seleccionamos On e
File :, especificando el path al fichero a d m in . h t m l, y pulsamos el botn Co n v e rt .
Despus de completar la conversin, cargamos el fichero a d m in . h t m l en nuestro
navegador.
Oz it o
Plataformas Win32
En plataformas Win32, el software JavaTM est unido con el Java 2 Runtime
Environment (JRE). Java Plug-In permite a los navegadores usar el JRE de Java 2
para ejecutar applets basados en 1.2 y componentes JavaBeansTM en lugar de la
mquina virtual por defecto de los navegadores. El Java Plug-In funciona con
Netscape Communicator y Microsoft Internet Explorer.
Obtener las Descargas
unzip htmlconv12.zip
Aadimos el programa HTMLCo n v e rt e r. ja v a o su directorio a nuestro
CLAS S P ATH.
policy.url.1=file:${java.home}\lib\security\java.policy
policy.url.2=file:${user.home}\java.policy
policy.url.3=file:\<mypolicyfile path and name>
cp admin.jar \home\zelda\public_html
jar xf applet.jar
La extraccin sita el fichero de polica bajo p u b lic _ h t m l y crea un directorio
a d m in bajo el directorio p u b lic _ h t m l con el fichero class del applet dentro.
Renombramos el fichero de polica del directorio p u b lic _ h t m l como . ja v a . p o lic y y
lo copiamos en nuestro directorio home.
En el directorio p u b lic _ h t m l, creamos un fichero HTML que invoque al applet
Administration. Nos debemos asegurar de incluir el directorio a d m in cuando
especifiquemos la opcin COD E del applet. Observamos que cuando usamos Java
Plug-In, no podemos hacer que el navegador carge el fichero class desde el fichero
JAR.
<HTML>
<BODY>
<APPLET CODE=admin/AdminApplet.class
WIDTH=550
HEIGHT=150>
</APPLET>
</BODY>
</HTML>
Arrancamos el HTML Converter.
java HTMLConverter
En el interface grfico de usuario del HTML Converter graphical, seleccionamos
On e File :, especificando el path al fichero a d m in . h t m l, y pulsamos el botn
Co n v e rt .
Cmo Funciona?
En mquinas Windows, el Java Plug-In encuentra el Java Runtime Environment
(JRE) ejecutando el fichero de control OLE personalizado b e a n s . o c x instalado por
defecto en el directorio del navegador web \ P ro g ra m File s \ Ja v a S o ft \ 1 . 2 \ b in .
El control OLE examina el registro de Windows para buscar la clave del Java
Plug-In y usa el valor asociado con esa clave para encontrar el JRE instalado.
Si encontramos que se carga un JRE errneo, usamos re g e d it para chequear el
valor del registtro de Java Plug-In para el usuario actual. Si el JRE no est
instalado, el control chequea los valores Java Plug-in para la
HKEY_ LOCAL_ MACHI N E. Deberamos ver un valor para Ja v a Ru n t im e
En v iro n m e n t bajo S o ft w a re \ Ja v a S o ft .
Despus de completar la conversin, cargamos el fichero a d m in . h t m l en nuestro
navegaor Web.
Oz it o
Ms Tpicos de Seguridad
Este captulo presenta dos tpicos de seguridades adicionales que podramos
encontrar interesantes.
Applets Firmados
Tienes Prisa?
Esta tabla tiene enlaces directos a los tpicos especficos.
T p ic o S e c c i n
Applets Firmados Ejemplo de Applet Firmado
Desarrollador de Intranet
Usuario Final
Ejecutar una Aplicacin con un Fichero de Polica
Applets Firmados en JDK 1.1
Escribir un Controlador de El Programa FileIO
Seguridad El Programa PasswordSecurityManager
Ejecutar el Programa FileIO
Informacin de Referencia
Oz it o
Applets Firmados
Se peude definir un fichero de polica para requerir una firma de todos los applets o
aplicaciones que intenten ejecutarse con el fichero de polica. La firma es una
forma de verificar que el applet o la aplicacin vienen de una fuente fiable y que
puede ser creada para ejecutarse con los permisos concedidos por el fichero de
polica.
Si un fichero de polica requiere una firma, un applet o una aplicacin pueden
obtener el acceso concedido por el fichero de polica slo si tienen la firma correcta.
Si el applet o la aplicacin tienen una firma errnea o no tienen firma, no
obtendrn el acceso al fichero.
Esta seccin muestra un ejemplo de firma de una applet, verificacin de esa firma,
y ejecucin del applet con un fichero de polica.
Ejemplo Applet Firmado
Desarrollador de Intranet
Usuario Final
Ejecutar la Aplicacin con un Fichero de Polica
Applets Firmados en JDK 1.1
Write.jp fichero de polica que concede los accesos al directorio home del
usuario.
Una etiqueta Applet embebida en un fichero SignedApplet.html:
<applet code="SignedAppletDemo.class"
archive="SSignedApplet.jar"
width=400 height=400>
<param name=file value="/etc/inet/hosts">
</applet>
Normalmente un applet se envulve y se firma mediante un desarrollador de
intranet y es manejado por el usuario final que verifica la firma y ejecuta el applet.
En este ejemplo, el desarrollador de intranet performa los pasos 1 al 5, y el usuario
final realiza lo pasos del 6 al 8. Para mantener las cosas sencillas todos los pasos
ocurren en el mismo directorio.
1. Compilar el Applet.
2. Crear el Fichero JAR.
3. Generar las Claves.
4. Firmar el Fichero JAR.
5. Exportar el Certificado de Clave Pblica.
6. Importar el Certificado como Certificado Verdadero.
7. Crear el Fichero de Polica.
8. Ejecutar el Applet.
Desarrollador de Intranet
El desarrollador de intranet, envuelve el ejecutable del applet en un fichero JAR, lo
firma y exporta el certificado de la clave pblica.
1: Compilar el Applet
Un fichero JAR se firma con la clave privada del creador del fichero JAR y la firma
es verificada por el receptor del fichero JAR con el clave pblica de la pareja. El
certificado es una sentencia del propietario de la clave privada indicando que la
clave pblica de la pareja tiene una valor particular para que la persona que la est
usando puede estar segura de que es autntica. Las claves pblica y privada deben
existir en el almacen de calves antes de que se puede usar jarsigner para firmar o
verificar la firma de un fichero JAR.
El desarrollador crea un base de datos k e y s t o re llamada c o m p s t o re que tiene
una entrada para cada pareja de claves recientemente generadas con la clave
pblica en un certificado usando el comando k e y t o o l.
En su directorio de trabajo, el desarrollador crea una base de datos keystore y
genera las claves:
El certificado de la clave pblica se enva con el fichero JAR al usuario final que
usar el applet. Esta persona usa el certificado para autentificar la firma del fichero
JAR. Un certificado se enva exportandolo desde la base de datos c o m p s t o re .
En su directorio de trabajo, el desarrollador usa keytool para copiar el certificado
desde c o m p s t o re a un fichero llamado Co m p a n y Ce r. c e r de esta forma:
keystore "/home/ray/raystore";
java -Djava.security.manager
-Djava.security.policy=polfile MyProgram
Oz it o
Escribir un Controlador de Seguridad
Un controlador de seguridad es un objeto de la Mquina Virtual JavaTM (JVM) que
implementa un polica de seguridad. Por defecto, la plataforma Java 2
proporciona un controlador de seguridad que desactiva todos los accesos a los
recursos del sistema local menos los accesos de lectura al directorio y sus
subdirectorios dnde es invocado el programa.
Podemos extender el controlador de seguridad por defecto para implementar
verificaciones y aprovaciones personalizadas para applets y aplicaciones, pero la
implementacin debe incluir cdigo de verificacin de accesos apropiado para cada
mtodo c h e c k XXX que sobreescribamos. Si no incluimos este cdigo, no suceder
ningun chequeo de verificacin, y nuestro programa escindir el fichero de polica
del sistema.
Esta seccin usa una aplicacin de ejemplo para explicar cmo escribir un
controlador de seguridad personalizado antes de leer y escribir los ficheros
especificados. La implementacin incluye cdigo de verificacin de accesos por eso
una vez que el usuario pasa el chequeo de password, todava necesita que el
fichero tenga permisos de lectura y escritua en su fichero de polica.
El ejemplo consiste en la aplicacin File I O, y el programa
P a s s w o rd S e c u rit y Ma n a g e r que proporciona la implementacin del controlador
de seguridad personalizado.
El programa FileIO
El programa PasswordSecurityManager
Ejecutar el programa FileIO
Informacin de Referencia
El programa FileIO
El programa FileIO muestra un sencillo interface de usuario que pide al usuario que
introduzca algn texto. Cuando el usario pulsa el botn Clic k Me , el texto se graba
en un fichero en el directorio home del usuario, y se abre y se lee un segundo
fichero. El texto ledo del segundo fichero se muestra al usuario.
Antes de Pulsar el botn Despus de Pulsar el botn
La Clases PasswordSecurityManager
La clase PasswordSecurityManager declara dos variables de ejemplar privadas, que
son inicializadas por el constructor cuando se instala el controlador de seguridad
personalziado. La variable de ejemplar p a s s w o rd contiene el password real, y la
variable de ejemplar b u ffy es un buffer de entrada que almacena la password de
entrada del usuario final.
public PasswordSecurityManager(String p,
BufferedReader b){
super();
this.password = p;
this.buffy = b;
}
El mtodo a c c e s s OK le pide una password al usuario final, verifica la password, y
devuelve t ru e si el password es correcto y fa ls e si no lo es.
System.out.println("Password, please:");
try {
response = buffy.readLine();
if (response.equals(password))
return true;
else
return false;
} catch (IOException e) {
return false;
}
}
Verificar Accesos
Fichero de Polica
Aqui esta el fichero de polica que necesita el programa File I O para las
operaciones de lectura y escritura. Tambin conceder permiso al controlador de
seguridad personalizado para acceder a la cola de eventos en representacin de la
aplicacin y mostrar la ventana de la aplicacin si ningn aviso.
grant {
permission java.io.FilePermission
"${user.home}/text.txt", "write";
permission java.util.PropertyPermission
"user.home", "read";
permission java.io.FilePermission
"${user.home}/text2.txt", "read";
permission java.awt.AWTPermission
"accessEventQueue";
permission java.awt.AWTPermission
"showWindowWithoutWarningBanner";
};
Informacin de Referencia
El Apndice A: Seguridad y Permisos describe los permisos disponibles y explica las
consecuencias de conceder permisos. Una forma de usar esta es informacin es
para ayudarnos a limitar los permisos concedidos a un applet o aplciacin podran
necesitar ser ejecutados satisfactoriamente. Otra forma de usar esta informacin
es educarnos en la forma en un permiso particular puede ser explotado por cdigo
mailicioso.
El Apndice B: Clases, Mtodos y Permisos proporciona lista de mtodos de la
plataforma Java 2 que estn implementados para chequeos de seguridad, los
permisos que cada uno requiere, y el mtodo ja v a . s e c u rit y . S e c u rit y Ma n a g e r
llamado para realizar el chequeo de accesos.
Podemos usar esta referencia para escribir implementaciones de nuestro propio
controlador de seguridad o cundo implementamos mtodos abstactos que realizan
tareas relacionadas con la seguridad.
El Apndide C: Mtodos del SecurityManager lista los chequeos de permisos para
los mtodo de S e c u rit y Ma n a g e r.
Oz it o
Apndice A: Seguridad y Permisos
Todos los applets y cualquier aplicacion invocada con un controlador de seguridad
debe conceder permisos explcitos para acceder los recursos locales del sistema
apaerte del acceso de lectura en el directorio y subdirectorios desde donde se
invoc el programa. La plataforma JavaTM proporciona permisos para permitir
varios niveles de accesos a diferentes tiposde informacin local.
Como los permisos permiten a un applet o una aplicacin sobreescribir el polica de
seguridad por defecto, deberamos ser muy cuidadosos cuando asignemos
permisos para no crear una antrada al cdigo malicioso para que ataque nuestro
sistema.
Este apndice describe los permisos disponibles y explica cmo cada permiso
puede crear una entrada para un ataque de cdigo malicioso. Una forma de usar
esta informacin es ayudarnos a limitar los permisos dados a un applet o una
aplicacin a slo los necesarios para su ejecucin. Otra forma de usar esta
informacin es para aprender nosotros mismos las formas en que un permisi
particular puede ser explotado por cdigo malicioso.
Como consejo, nunca creas en un applet o una aplicacin desconocidos. Siempre
chequea el cdigo cuidadosamente con la informacin de este apndice para
asegurarte de que no ofreces permisos a codigo malicios que cause serios
problemas en el sistema local.
Introduccin
Conocer qu Permisos
AllPermission
AWTPermission
FilePermission
NetPermission
PropertyPermission
ReflectPermission
RuntimePermission
SecurityPermission
SerializablePermission
SocketPermission
Introduccin
Los permisos se le conceden a un programa con un ficheo de polica. Un fichero de
polica conteine permisos para accesos especficos. Un permiso consta de un
nombre de permiso, una fuente, y en algunos casos, una lista de acciones
separadas por comas.
Por ejemplo, la siguiente entrada de fichero de polica especifica un permiso
ja v a . io . File P e rm is s io n que concede acceso de re a d (la accin) a la fuente
$ { u s e r. h o m e } / t e x t 2 . t x t .
grant {
permission java.io.FilePermission
"${user.home}/text2.txt", "read";
};
Hay un fichero de polica de la instalacin de la plataforma Java (Sistema) y
opcionalmente un fichero de polica por cada usuario. El fichero de polica del
sistema est en { ja v a . h o m e } / lib / s e c u rit y / ja v a . p o lic y , y el fichero de polica
de usuario est en cada directorio home de los usuarios. Los ficheros de polica de
sistema y de usuario se combinan. Por eso por ejemplo, podra haber un fichero de
polica con muy pocos permisos concedidos a todos los usuarios del sistema, y un
fichero de polica individual concediendo permisos adicionales a ciertos usuarios.
Para ejecutar una aplicacin con el controlador de seguridad y un fichero de polica
llamado p o lfile en el directorio home del usuario, tecleamos:
java -Djava.security.main
-DJava.security.policy=polfile FileIO
Para ejecutar un applet en el aplletviewer con un fichero de polica llamando
p o lfile en el directorio home del usuario, tecleamos:
appletviewer
-J-Djava.security.policy=polfile fileIO.html
Cuando ejecutamos un applet en un navegador, este busca los ficheros de polica
de usuario y del sistema para encontrar los permisos que necesita el applet para
acceder a los recursos del sistema local en representacin del usuario que descarg
el applet.
Conocer qu Permisos
Cuando ejecutamos un applet o invocamos una aplicacin con un controlador de
seguridad que necesita permisos, obtendremos un seguimiento de pila si no hemos
proporcionado un fichero de polica con todos los permisos necesarios. El
seguimiento de pila contiene la informacin que necesitamos para aadir los
permisos al fichero de polica que caus el seguimiento de pila. Si el programa
necesita permisos adicionales, seguiremos obteniendo el seguimiento d epila hasta
que se aadan todos los permisos requeridos al fichero de polica. El nico
inconveniente de esta aproximacin es que tenemos que probar cada posbiel path
de cdigo de nuestra aplicacin.
Otra forma de determinar qu permisos necesita nuestro programa es visitar
Apndice B: Mtodos y Permisos. Este apndice nos cuenta qu mtodos de la
plataforma Java 2 tienen impedida la ejecucin sin los permisos listados. La
informacin del Apndice B tambin es til para los desarrolladores que quieran
escribir su propio controlador de seguridad para personalizar las verificaciones y
aprovaciones necesarias en un programa.
Aqu tenemos un pequeo ejemplo que nos muestra como traducir el primer par de
lneas del seguimiento de pila en una entrada del fichero de polic. La primera lnea
nos dice que el acceso est denegado. Esto significa que el seguimiento de pila fue
generado porque el programa intent acceder a recursos del sistema sin el permiso
apropiado. La segunda lnea significa que necesitamos un
ja v a . n e t . S o c k e t P e rm is s io n que le de programa permiso para c o n n e c t y para
re s o lv e el nombre de host para la direccin (IP) 129.144.176.176, puerto 1521.
grant {
permission java.net.SocketPermission
"129.144.176.176:1521", "connect,resolve";
};
AllPermission
ja v a . s e c u rit y . AllP e rm is s io n especifica todos los permisos en el sistema para
todos los posibles fuentes y acciones. Este permiso slo debera usarse para
pruebas ya que concede permiso para ejecutar con todas las restricciones de
seguridad desactivadas, como si no hubiera controlador de seguridad.
grant {
permission java.security.AllPermission;
};
AWTPermission
ja v a . a w t . AW TP e rm is s io n concede permisos a las siguientes fuentes AWT. Las
posibles fuentes se listan por nombre sin lista de acciones.
grant {
permission java.awt.AWTPermission
"accessClipboard";
permission java.awt.AWTPermission
"accessEventQueue";
permission java.awt.AWTPermission
"showWindowWithoutWarningBanner";
};
a c c e s s Clip b o a rd : Esta fuente concede permiso para poner informacin y para
recuperarla desde el portapapeles del AWT. Conceder este permiso puede permitir
a cdigo malicioso que comparta informacion potencialmente sensible o
confidencial.
a c c e s s Ev e n t Qu e u e : Esta fuente concede permiso para acceder a la cola de
eventos del AWT. Conceder este permiso podra permitir a cdigo mailicioso que
observe y elimine eventos del sistema, y ponga eventos falsos que podran causar
que la aplicacin o el appler realizarn acciones maliciosas.
lis t e n To AllAW TEv e n t s : Esta fuente concede permiso para escuvhar todos los
eventos AWT a travs del sistema. Conceder este permiso podra permitir a cdigo
malicios lea y explote entradas confidenciales del usuario como las passwords.
Cada oyente de evento AWT es llamado desde dentro del contexto
Ev e n t D is p a t c h Th re a d de la cola de eventos, por eso si tambin est activado el
permiso a c c e s s Ev e n t Qu e u e , cdigo malicioso podra modificar el contenido de la
cola de eventos del AWT a travs del sistema, lo que podra causar que el applet o
la aplicacin realizarn acciones maliciosas.
re a d D is p la y P ix e ls : Esta fuente concede permiso para leer pixels desde la
pantalla. Condeder este permiso podra permitir a interfaces como
ja v a . a w t . Co m p o s it e permitan examinar los pixels de la pantalla y fisgonee las
actividades del usuario.
s h o w W in d o w W it h o u t W a rn in g Ba n n e r: Esta fuene concede permiso para
mostrar una ventana sin mostrar el aviso de que la ventana fue creada por un
applet. Sin este aviso, un applet podra mostrar ventanas si que el usuario supiera
que pertenecen al applet. Esto podra ser un problema en entornos dnde el
usuario toma decisiones sensibles de seguridad bsandose en a quin pertenece la
ventana si a un applet o a una aplicacin. Por ejemplo, desactivar este aviso podra
significar que el usuario introdujeta informacin sensile como el nombre de usuario
y la password.
FilePermission
ja v a . io . File P e rm is s io n concede permiso para acceder a un fichero o directorior.
La fuentes consisten en el pathname y una lista de acciones separadas por comas.
Este fichero de polica concede permisos de lectura, escritura, borrado y ejecucin
para todos los ficheros.
grant {
permission java.io.FilePermission
"<<ALL FILES>>", "read, write, delete, execute";
};
Este fichero de polica concede permiso de lectura y escritura sobre t e x t . t x t en el
directorio home del usuario.
grant {
permission java.io.FilePermission
"${user.home}/text.txt", "read, write";
};
Podemos usar los siguiente comodines para especificar al pathname de la fuente:
Un pathname que termine en / * , donde / * es el carcter separador de
ficheros significa un directorio y todos los ficheros contenidos en ese
directorio.
Un pathname que termine con / - indica un directorio, y recursivamente,
todos los ficheros y subdirectorios incluidos en ese directorio
Un pathname que consista en un slo asterisco (* ) indica todos los ficheros
del directorio actual.
Un pathname que consista en un slo guin (- ) indica todos los ficheros del
directorio actual, y recursivamente, todos los ficheros y subdirectorios
contenidos en el directorio actual.
Las acciones son especificadas en una lista de palabras clave separadas por comas
que tienen el siguiente significado:
read: Permiso para leer un fichero o directorio.
grant {
permission java.net.NetPermission
"setDefaultAuthenticator";
permission java.net.NetPermission
"requestPasswordAuthentication";
};
s e t D e fa u lt Au t h e n t ic a t o r: Esta fuente concede permiso para seleccionar la forma
en que informacin de autentificacin es recuperad cuando un proxy o un servidor
HTTP piden autentificacin. Concedere ste permiso podra significar que cdigo
mailicioso puede seleccinar un autentificador que monitorice y robe la entrada de
autentificacin del usuario como si recuperar la informacin desde el usuario.
re q u e s t P a s s w o rd Au t h e n t ic a t io n : Esta fuente concede permiso para pedir al
autentificador registrado con el sistema una password. Conceder este permiso
podra significar que cdigo preciado podra robar la password.
s p e c ify S t re a m Ha n d le r: Esta fuente concede permiso para especificar un
manejador de stram cuando se construye una URL. Conceder este permiso podra
significar que cdigo malicioso podra crear una URLK con recursos a los que
normalmente no tendra acceso, o especificar un controlador de stream para
obtener los bytes reales desde algun real al que tenga acceso. Esto significa que el
cdigo malicios podra embaucar al sistema para crear una clase
ProtectionDomain/CodeSource incluso aunque la clase realmente no venga de esa
localizacin.
PropertyPermission
ja v a . u t il. P ro p e rt y P e rm is s io n concede acceso a las propiedades del sistema. La
clase ja v a . u t il. P ro p e rt ie s represetna selecciones persistentes como la localizacin
del directorio de instalacin, el nombre de usuario o el directorio home del usuario.
grant {
permission java.util.PropertyPermission
"java.home", "read";
permission java.util.PropertyPermission
"os.name", "write";
permission java.util.PropertyPermission
"user.name", "read, write";
};
La lista de fuentes contiene el nombre de la propiedad, por ejemplo, ja v a . h o m e o
o s . n a m e . La convencin de nombres para propiedades sigue la convencin de
nombres hereditarios, e incluye comodines. Un asterisco al final del nombre de
propiedad, despus de un punto (. ), o en solitario, significa un comodin. Por
ejemplo, ja v a . * o * son vlidos, pero * ja v a o a * b no lo son.
Las acciones se especifican en una listra de palabras claves separadas por comas,
que tienen este significado:
read: Permiso para leer (obtener) una propiedad.
ReflectPermission
ja v a . la n g . re fle c t . Re fle c t P e rm is s io n concede permiso para varias operaciones
reflectivas. Las posibles fuentes se listan por el nombre sin lista de acciones.
grant {
permission java.lang.reflect.ReflectPermission
"suppressAccessChecks";
};
s u p p re s s Ac c e s s Ch e c k s : Esta fuente concede permiso para acceder a los campos
e invocar mtodos de una clase. Esto incluye campos y mtodos pblicos,
protegidos y privados. Conceder este permiso pidra revelar informacin
confidencial y poner mtodos importantes al alcance del cdigo malicioso.
RuntimePermission
ja v a . la n g . Ru n t im e P e rm is s io n concede permiso a varias fuentes del entorno de
ejecucin, como el cargador de clases, la mquina virtual Java y los threads. Las
posibles fuentes se listan por el nombre sin lista de acciones.
grant {
permission java.lang.RuntimePermission
"createClassLoader";
permission java.lang.RuntimePermission
"getClassLoader";
permission java.lang.RuntimePermission
"exitVM";
permission java.lang.RuntimePermission
"setFactory";
permission java.lang.RuntimePermission
"setIO";
permission java.lang.RuntimePermission
"modifyThread";
permission java.lang.RuntimePermission
"modifyThreadGroup";
permission java.lang.RuntimePermission
"getProtectionDomain";
permission java.lang.RuntimePermission
"setProtectionDomain";
permission java.lang.RuntimePermission
"readFileDescriptor";
permission java.lang.RuntimePermission
"writeFileDescriptor";
permission java.lang.RuntimePermission
"loadLibrary.<library name>";
permission java.lang.RuntimePermission
"accessClassInPackage.<package name>";
permission java.lang.RuntimePermission
"defineClassInPackage.<package name>";
permission java.lang.RuntimePermission
"accessDeclaredMembers.<class name>";
permission java.lang.RuntimePermission
"queuePrintJob";
};
Las convenciones de nombrado para la fuente sigue la convencin de nombres
hereditarios, e incluye comodines. Un asterisco al final del nombre de propiedad,
despus de un punto (. ), o en solitario, significa un comodin. Por ejemplo,
lo a d Lib ra ry . * o * son vlidos, pero * lo a d Lib ra ry o a * b no lo son.
c re a t e Cla s s Lo a d e r: Esta fuente concede permiso para crear un cargador de
clases. Conceder este permiso podra permitir a una aplicacin maliciosa que
ejemplarize su propio cargador de clases y carge clases peligrosas en el sistema.
Una vez cargado, el cargador de clases podra situar esas clases bajo cualquier
dominio proegido dndoles total control sobre ese dominio.
g e t Cla s s Lo a d e r: Esta fuene concede permiso para recuperar el cargador de
clases para la clase llamante. Conceder este permiso podra permitir que cdigo
malicioso obtuviere el cargador de clases para una clase particular y cargar clases
adicionales.
s e t Co n t e x t Cla s s Lo a d e r: Esta fuente concede permiso para seleccionar el
contexto del cargador de clases usado por un thread. El cdigo del sistema y las
extensione susan este contexto para buscar recursos que podran no existir en el
cargador de clases del sistema. Conceder este permiso permite cambiar el contexto
del cargador de clases usado para un thread particular, incluyendo los threads del
sistema. Esto podra causar problemas si el contexto del cargador de clases tiene
cdigo malicioso.
s e t S e c u rit y Ma n a g e r: Esta fuente concede permiso para seleccionar o reemplazar
el controlador de seguridad. El controlador de seguridad es una clase que permite a
la aplicaciones implementar un polica de seguridad. Conceder este permiso podra
permitir al cdigo mailicioso instalar un controlador menos restrictivo, y por lo
tanto, evitar los chequeos a los que se forzado el controlador de seguridad original.
c re a t e S e c u rit y Ma n a g e r: Esta fuente concede permiso para crear un nuevo
controlador de seguridad. Conceder este permiso podra darle al cdigo malicioso
acceso a mtodo protegidos qie podran revelar informacin sobre otras clases o la
pila de ejecucin.
e x it VM: Esta fuente concede permiso para parar la mquina virtual Java.
Conceder este permiso podra permitir que cdigo malicioso a montar un ataque de
denegacin de servicio forzando automticamente a que se pare la JVM.
s e t Fa c t o ry : Esta fuente concede permiso para seleccioanr una fbrica de socket
usada por las clases S e rv e rS o c k e t o S o c k e t , o la fbrica de manejadores de
streams usada por la clase URL. Conceder este permiso permite al cdigo
seleccionar la implementacin actual para la factora de socket, server socket,
stream handler, o Remote Method Invocation (RMI). Un atacante podra
seleccionar una implementacin que manejara los streams de datos.
s e t I O: Esta fuente concede permiso para cambiar los valores de los streams
S y s t e m . o u t , S y s t e m . in , S y s t e m . e rr. Conceder este permiso podra pemritir a un
atancante cambiar el S y s t e m . in para robar la entrada del usuario, o seleccionar
S y s t e m . e rr a un stream de salida n u ll, lo que podra ocultar cualquier error
enviado a S y s t e m . e rr.
m o d ify Th re a d : Esta fuente concede permiso para modicar los threads mediante
llamadas a los mtodos s t o p , s u s p e n d , re s u m e , s e t P rio rit y , y s e t N a m e de la
clase Th re a d . Conceder este permiso podra permitir a un atancante arrancar o
suspender cualquier tread e el sistema.
s t o p Th re a d : Esta fuente concede permiso para parar threads. Conceder este
permisos permtie al cdigo que pare cualquier thread en el sistema proporcionando
el cdigo que ya tiene permiso para acceder a ese thread, EL cdigo malicioso
podra corromper el sistema eliminado threads existentes.
m o d ify Th re a d Gro u p : Esta fuente concede permiso para modificar threads
mediante llamadas a los mtodos d e s t ro y , re s u m e , s e t D a e m o n ,
s e t m a x P rio rit y , s t o p , y s u s p e n d de la clase Th re a d Gro u p . Conceder este
permiso podra permitir al atancante que cree un grupo de threadas y seleccionar
su prioridad de ejecucin.
g e t P ro t e c t io n D o m a in Esta fuente concede permiso para recuperar el ejemplar
P ro t e c t io n D o m a in para una clase. Conceder este permiso pemite al cdigo
obtener informacin de polica para ese cdigo fuente. Mientras que la obtencin
de la informacin de polica no compromete la seguridad del sistema, si que le
ofrece informacin adicional al atacante como los nombres de ficheros locales, por
ejemplo.
re a d File D e s c rip t o r: Esta fuente concede permiso para leer descriptores de
ficheros. Conceder este permiso permite al cdigo leer el fichero particular
asociado con el descriptor de fichero, que es peligroso si el fichero contiene datos
confidenciales.
w rit e File D e s c rip t o r: Esta fuente concede permiso para escribir descriptores de
ficheros. Conceder este permiso permite al cdigo escribir el fichero asociado con
el descriptor de fichero, lo que es peligroso si el descriptor apunta a un fichero
local.
lo a d Lib ra ry . { lib ra ry n a m e } : Este fichero concede permiso para enlazar
dinmicamente la librera especificada. Conceder este permiso podra ser peligroso
porque la arquitectura de seguridad no est diseada y no se extiende para las
clases nativas cargadas mediante el mtodo ja v a . la n g . S y s t e m . lo a d Lib ra ry .
a c c e s s Cla s s I n P a c k a g e . { p a c k a g e n a m e } Esta fuente concede permiso para
acceder al paquete especificado mediante el mtodo lo a d Cla s s del cargador de la
clase cuando el cargador de la clase llama al mtodo
S e c u rit y Ma n a g e r. c h e c k P a c k a g e Ac e s s s . Conceder este permiso le da al cdigo
acceso a las clases de paquetes a los que normalmente no tiene acceso. El cdigo
mailicioso podra usar estas clases para ayudarse en su intento de comprometer la
seguridad del sistema.
d e fin e Cla s s I n P a c k a g e . { p a c k a g e n a m e } : Esta fuente concede permiso para
definir las clases del paquete especificado mediante un mtodo d e fin e Cla s s del
cargador de clases cuando el cargador llama al mtodo
S e c u rit y Ma n a g e r. c h e c k P a c k a g e D e fin it io n . Conceder este permiso permite al
cdigo definir una clase en un paquete particular, lo que podra ser peligroso
porque el cdigo malicioso con este permiso podra definir clases peligrosas en
paquetes verdaderos como ja v a . s e c u rit y o ja v a . la n g , por ejemplo.
a c c e s s D e c la re d Me m b e rs : Esta fuente concede permiso para acceder a miembros
declarados de una clase. Conceder este permiso permite al cdigo solicitar una
clase por sus campos y mtodos pblicos, protegidos, por defecto (paquete) y
privados. Aunque el cdigo podra tener acceso a los nombres de los campos y
mtodos privados y protegidos, no podr acceder a sus datos y no podr invocar
ningn mtodo privado. A pesar de esto, el cdigo malicioso podra usar esta
informacin para mejorar su ataque. Adems, el cdigo malicios podra invocar
mtodos pblicos o acceder a campos pblicos de la clase, lo que podra ser
peligroso.
q u e u e P rin t Jo b : Esta fuente concede permiso para inicializar una peticin de
trabajo de impresin. Conceder este permiso podra permitir al cdigo qe imprima
informacin sensible en una impresora o que gaste papel maliciosamente.
SecurityPermission
ja v a . s e c u rit y . S e c u rit y P e rm is s io n conceder permiso ha varios parmetros de
configuracin de seguridad. Las fuentes posibles se listan por el nombre sin lista de
acciones. Los permisos de seguridad actualmente se aplican a mtodo llamados
sobre los siguientes objetos:
ja v a . s e c u rit y . P o lic y , que representa la polica de seguridad del sistema para
aplicaciones.
ja v a . s e c u rit y . S e c u rit y , que centraliza todas las propiedades de seguridad y
mtodos comunes. Maneja proveedores.
ja v a . s e c u rit y . P ro v id e r, que repesenta una implementacin de cosas como
algoritmos de seguridad (DSA, RSA, MD5, or SHA-1) y generacin de claves.
ja v a . s e c u rit y . S ig n e r, que maneja claves privadas. Aunque, S ig n e r est
obsoleto, los permisos relacionados estn disponibles por razones de
compatibilidad.
ja v a . s e c u rit y . I d e n t it y , que maneja objetos del mundo real como son
personas, compaias, y organizaciones, cuyas identidades pueden ser
autentificadas usando sus claves pblicas.
grant {
permission java.security.SecurityPermission
"getPolicy";
permission java.security.SecurityPermission
"setPolicy";
permission java.security.SecurityPermission
"getProperty.os.name";
permission java.security.SecurityPermission
"setProperty.os.name";
permission java.security.SecurityPermission
"insertProvider.SUN";
permission java.security.SecurityPermission
"removeProvider.SUN";
permission java.security.SecurityPermission
"setSystemScope";
permission java.security.SecurityPermission
"setIdentityPublicKey";
permission java.security.SecurityPermission
"setIdentityInfo";
permission java.security.SecurityPermission
"addIdentityCertificate";
permission java.security.SecurityPermission
"removeIdentityCertificate";
permission java.security.SecurityPermission
"clearProviderProperties.SUN";
permission java.security.SecurityPermission
"putProviderProperty.<provider name>";
permission java.security.SecurityPermission
"removeProviderProperty.SUN";
permission java.security.SecurityPermission
"getSignerPrivateKey";
permission java.security.SecurityPermission
"setSignerKeyPair";
};
g e t P o lic y : Esta fuente concede permiso para recuperar el polica de seguridad del
sistema. Conceder estep permiso revela qu permisis seberan concederse a una
aplicacin o un applet dados. Mientras que la revelacin del polica no compromete
la seguridad del sistema, proporciona al cdigo malicios informacin adicional que
podra usar para un mejor ataque.
s e t P o lic y : Esta fuente concede permiso para seleccionar el polica de seguridad
del sistema. Conceder este permiso podra permitir al cdigo malicioso que se
conceda a s mismo todos los permiso para montar un ataque al sistema.
g e t P ro p e rt y . { k e y } : Esta fuente concede permiso para recuperar la propiedad de
seguridad especificada mediante { k e y } . Dependiendo de la clave particular para el
que se concede el acceso, el cdigo podra tener accedo a una lista de proveedores
de seguridad y la localizacin de las policas de seguridad del sistema y de usuario.
Mientras que la revelacin de esta informacin no compromete la seguridad del
sistema, si proporciona informacin adicional que podra usar para un mejor
ataque.
s e t P ro p e rt y . { k e y } : Esta fuente concede permiso para seleccionar la propiedad
de seguridad especificada por { k e y } . Esto podra incluir la seleccin de un
proveedor de seguridad o definir la localizacin del polica de seguridad del
sistema. El cdigo malicioso podra usar un proveedor maligno que robar
informacin confidencial como las claves privadas. Adems, el cdigo malicioso
podra seleccionar con los permisos seleccionar la localizacin del polica de
seguridad del sistema que podra apuntar a un polica de seguridad que conceda al
atancante todos los permisos necesarios que requiera para montar el ataque al
sistema.
in s e rt P ro v id e r. { p ro v id e r n a m e } : Esta fuente concede permiso para aadir un
nuevo proveedor de seguridad especificado por { p ro v id e r n a m e } . Conceder este
permiso permite la introduccin un proveedor posiblemente malicioso que podra
desubrir cosas como las claves provadas que se les pasa. Esto es posible porque el
objeto S e c u rit y , que maneja todos los proveedores instaladore, no cheque
realmente la integridad o la autenticidad de un proveedor antes de adjuntarlo.
re m o v e P ro v id e r. { p ro v id e r n a m e } : Esta fuente concede permiso para eliminar
un proveedor de seguridad especificado por { p ro v id e r n a m e } . Conceder este
permiso podra cambiar el comportamietno o desactivar la ejecucinde partes del
programa. Si un proveedor solicitado por el programa ha sido eliminado, la
ejecucin podra fallar.
s e t S y s t e m S c o p e : Esta fuente concede permiso para seleccionar el mbito de
identidad del sistema. Conceder este permiso podra permitir al atacante configurar
el mbito de seguridad del sistema con certificados que no deberan ser creidos.
Esto podra conceder al cdigo firmado cuyos privilegios certificados podran ser
denegados por el mbito de identidad original.
s e t I d e n t it y P u b lic Ke y : Esta fuente concede permiso para seleccionar la clave
pblica de un objeto I d e n t it y . Si la identidad se marca como t ru s t e d , permite al
atacante introducir su propia clave pblica que no es verdadera mediante el mbito
de identidad del sistema. Esto podra conceder al cdigo firmado privilegios de
clave pblica que de otra forma seran denegados.
S e t I d e n t it y I n fo : Esta fuente concede permiso para seleccionar un string de
informacin general para un objeto I d e n t it y . Conceder este permiso permite al
atancate seleccionar una descripcin general para una identidad. Hacindolo
podramos embaucar a las aplicaciones a usar una identidad diferente que evite a
las aplicacioens encontrar una identidas particular.
a d d I d e n t it y Ce rt ific a t e : Esta fuente concede permiso para aadir un certificado
para un objeto I d e n t it y . Conceder este permiso permite a los atacantes
seleccionar un certificado para una clave pblica de identidad haciendo que la clave
pblica sea verdadera a una audiencia mayor de la original.
re m o v e I d e n t it y Ce rt ific a t e : Esta fuente concede permiso para eliminar un
certificado de un objeto I d e n t it y . Conceder este permiso permite al atacante
eliminar un certificado para la clave pblica de una identidad. Esto podra ser
peligroso porque una clave pblica podra ser considerada como menos verdadera
de lo que podra ser.
p rin t I d e n t it y : Esta fuente concede permiso para imprimir el nombre de un
prinicpal el mbito en que se usa el principal, y cuando el principal es considerado
como v e rd a d e ro en este mbito. El mbito impreso podra ser un nombre de
fichero, en cuyo caso podra robar informacin del sistema local. Por ejemplo, aqu
hay un ejemplo de impresin de un nombre de identidad ca ro l, que est marcado
como verdadero en la base de datos de identidad del usario:
carol[/home/luehe/identitydb.obj][not trusted].
c le a rP ro v id e rP ro p e rt ie s . { p ro v id e r n a m e } Esta fuente concede permiso para
borrar un objeto P ro v id e r para que no contenga ms propiedades usadas para
buscar servicios implementados por el proveedor. Conceder este permiso desactiva
los servicios de bsqueda implementados por el proveedor. Esto podra cambiar el
comportamiento o desactivar la ejecucinde otras partes del programa que
normalmente utiliar el Provider, como se describe bajo el permiso
re m o v e P ro v id e r. { p ro v id e r n a m e } de arriba.
p u t P ro v id e rP ro p e rt y . { p ro v id e r n a m e } : Esta fuente concede permiso para
seleccionar propiedades del proveedor seleccionado. Cada propiedad del proveedor
especifica el nombre y la localizacin de un servicio particular implementado por el
proveedor. Conceder este permiso permite al cdigo reemplazar la especificacin
de servicio con otro con una diferente implementacin y podra ser peligroso si la
nueva implementacin tiene cdigo malicioso.
re m o v e P ro v id e rP ro p e rt y . { p ro v id e r n a m e } : Esta fuente concede permiso para
eliminar propiedades del proveedor especificado. Conceder este permiso desactiva
la bsqueda de servicios implementada por el proveedor hacindola inaccesible.
Conceder este permiso a cdigo malicioso podra permitirle cambiar el
comportamiento o desactivar la ejecucin de otras partes del programa que
normalmente podran utilizar el objeto P ro v id e r, como se describe el permiso bajo
re m o v e P ro v id e r. { p ro v id e r n a m e } .
g e t S ig n e rP riv a t e Ke y : Esta fuente concede permiso para recuperar la clave
privada de un objeto S ig n e r. Las calves privadas deberan ser siempre secretas.
Conceder este permiso podra permtir a cdigo malicioso utilizar la clave privada
para firmar ficheros y reclamar que la firma venga del objeto S ig n e r.
s e t S ig n e rKe y P a ir: Esta fuente concede permiso para seleccionar la pareja de
claves pblica y privada para un objeto S ig n e r. Conceder este pemriso podra
permitir al atacante reemplazar la pareja de claves con una posible y pequea
pareja de claves. Esto tambin podra permitir a un atacante escuchar una
comunicacin encriptada entre la fuente y sus pares. Los pares de la fuente
podran envolver la sesin de encriptacin bajo la clave pblica n e w , que podra el
atacante (que posee la clave privada correspondiente) para desempaquetar la
clave de sesin y desencriptar la comunicacin.
SerializablePermission
ja v a . io . S e ria liz a b le P e rm is s io n concede acceso a operaciones de serializacin.
La fuentes posibles se listan por el nombre y no hay lista de acciones.
grant {
permission java.io.SerializablePermission
"enableSubclassImplementation";
permission java.io.SerializablePermission
"enableSubstitution";
};
e n a b le S u b c la s s I m p le m e n t a t io n : Esta fuente concede permiso para
implementar una subclase de Ob je c t Ou t p u t S t re a m o Ob je c t I n p u t S t re a m para
sobreescribir la serializacin o deserializacin por defecto de objetos. Conceder
este permiso podra permitir al cdigo usar esto para serializar o deserializar clases
de una forma maliciosa. Por ejemplo, durante la serializacin, el cdigo malicioso
podra almacenar campos privados confidenciales de una forma fcilmente
accesible para los atacantes; o durante la deserializacin el cdigo malicioso podra
deserializar una clase con todos sus campos privados puestos a cero.
e n a b le S u b s t it u t io n : Esta fuente concede permiso para sustituir un objeto por
otro durante la serializacin deserializacin. Conceder este permiso podra permitir
a cdigo malicioso reemplazar el objeto real con otro que tenga datos incorrectos o
malignos.
SocketPermission
El permiso ja v a . n e t . S o c k e t P e rm is s io n concede acceso a una red mediante
sockets. La fuente es un nombre de host y la direccin del puerto, y la accines
una lista que especifica las formas de conexin con ese host. Las coneciones
posibles son a c c e p t , c o n n e c t , lis t e n , y re s o lv e .
Esta entrada de fichero de polica permite que una conexin acepte conexiones al
puerto 7777 en el host p u ffin . e n g . s u n . c o m .
grant {
permission java.net.SocketPermission
"puffin.eng.sun.com:7777",
"connect, accept";
};
Esta entrada de fichero de policia permite a la conexin, aceptar conexiones para
escuchar cualquier puerto entre el 1024 y el 65535 en el host local.
grant {
permission java.net.SocketPermission
"localhost:1024-",
"accept, connect, listen";
};
El host se expresa con la siguiente sintaxis como un nombre DNS, una direccin IP
numrica, o como lo c a lh o s t (para la mquina local). El comodin asterisco (* ) se
puede incluir una vez en una especificacin de nombre DNS. Si se incluye dene
estr en la posicin ms a la izquierda, como en * . s u n . c o m .
Oz it o
Apndice B: Clases, Mtodos y Permisos
Un gran nmero de mtodos de la plataforma JavaTM 2 estan implementados para
verificar permisos de acceso. Esto significa que antes de ejecutarse, verifican si ay
un fichero de policia de sistema, usuario o programa con los permisos requeridos
para que continue la ejecucin. Si no se encuentran dichos permisos, la ejecucin
se detiene con una condicin de error.
El cdigo de verificacin de acceso pasa los permisos requeridos al controlador de
seguridad, y el controlador de seguridad comprueba estos permisos contra los
permisos del fichero de polica para determinar los accesos. Esto significa que los
mtodos de la plataforma Java 2 estn asociados con permisos especficos, y los
permisos especfcios estn asociados con mtodos especficos del
ja v a . s e c u rit y . S e c u rit y Ma n a g e r.
Este apndide lista los mtodos de la plataforma Java 2, los permisos asociados
con cada mtodo, y el mtodo ja v a . s e c u rit y . S e c u rit y Ma n a g e r llamado para
verificar la existencia de este permiso. Necesitamos esta informacin cuando
implementamos ciertos mtodos abstractos o creamos nuestro propio controlador
de seguridad para que podamos incluir cdigo de verificacin de acceso para
mantener nuestras implementaciones en lnea con la poltica de seguridad de la
plataforma Java 2. Si no incluimos cdigo de verificacin de acceso, nuestras
implementaciones no pasarn los chequeos de seguridad internos de la plataforma
Java 2.
java.awt.Graphics2D
java.awt.ToolKit
java.awt.Window
java.beans.Beans
java.beans.Introspector
java.beans.PropertyEditorManager
java.io.File
java.io.FileOutputStream
java.io.ObjectInputStream
java.io.ObjectOutputStream
java.io.RandomAccessFile
java.lang.Class
java.lang.ClassLoader
java.lang.Runtime
java.lang.SecurityManager
java.lang.System
java.lang.Thread
java.lang.ThreadGroup
java.lang.reflect.AccessibleObject
java.net.Authenticator
java.net.DatagramSocket
java.net.HttpURLConnection
java.net.InetAddress
java.net.MulticastSocket
java.net.ServerSocket
java.net.Socket
java.net.URL
java.net.URLConnection
java.net.URLClassLoader
java.rmi.activation.ActivationGroup
java.rmi.server.RMISocketFactory
java.security.Identity
java.security.IdentityScope
java.security.Permission
java.security.Policy
java.security.Provider
java.security.SecureClassLoader
java.security.Security
java.security.Signer
java.util.Locale
java.util.Zip
java.awt.Graphics2D
java.awt.Toolkit
java.awt.Window
Window()
checkTopLevelWindow
java.awt.AWTPermission
"showWindowWithoutWarningBanner"
java.beans.Beans
java.beans.Introspector
java.beans.PropertyEditorManager
java.io.File
java.io.FileInputStream
FileInputStream(FileDescriptor fdObj)
checkRead(FileDescriptor)
java.lang.RuntimePermission "readFileDescriptor"
~~~~~~~~~
FileInputStream(String name)
FileInputStream(File file)
checkRead(String)
java.io.FilePermission "{name}", "read"
java.io.FileOutputStream
FileOutputStream(FileDescriptor fdObj)
checkWrite(FileDescriptor)
java.lang.RuntimePermission "writeFileDescriptor"
~~~~~~~~~
FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
checkWrite(String)
java.io.FilePermission "{name}", "write"
java.io.ObjectInputStream
protected ObjectInputStream()
protected ObjectOutputStream()
checkPermission
java.io.SerializablePermission
"enableSubclassImplementation"
java.io.ObjectOutputStream
java.io.RandomAccessFile
java.lang.Class
java.lang.ClassLoader
ClassLoader()
ClassLoader(ClassLoader parent)
checkCreateClassLoader
java.lang.RuntimePermission "createClassLoader"
~~~~~~~~~
java.lang.Runtime
java.lang.SecurityManager
<all methods>
checkPermission
See Security Manager Methods.
java.lang.System
java.lang.Thread
Thread()
Thread(Runnable target)
Thread(String name)
Thread(Runnable target, String name)
checkAccess({parentThreadGroup})
java.lang.RuntimePermission "modifyThreadGroup"
~~~~~~~~~
java.lang.ThreadGroup
ThreadGroup(String name)
ThreadGroup(ThreadGroup parent,
String name)
checkAccess({parentThreadGroup})
java.lang.RuntimePermission "modifyThreadGroup"
~~~~~~~~~
java.lang.reflect.AccessibleObject
java.net.Authenticator
if (p.getAddress().isMulticastAddress()) {
java.net.SocketPermission(
(p.getAddress()).getHostAddress(),
"accept,connect")
}
El cdigo de verificacin de acceso para s e n d llama a c h e c k Co n n e c t en los
siguientes casos:
else {
port = p.getPort();
host = p.getAddress().getHostAddress();
if (port == -1) java.net.SocketPermission
"{host}","resolve";
else java.net.SocketPermission
"{host}:{port}","connect"
}
~~~~~~~~~
DatagramSocket(...)
checkListen({port})
El cdigo de verificacin de acceso para este mtodo llama a c h e c k Lis t e n y le
pasa permisos de sockets de esta forma:
if (port == 0)
java.net.SocketPermission "localhost:1024-",
"listen";
else
java.net.SocketPermission "localhost:{port}",
"listen"
~~~~~~~~~
java.net.HttpURLConnection
java.net.InetAddress
java.net.MulticastSocket
if (p.getAddress().isMulticastAddress()) {
java.net.SocketPermission(
(p.getAddress()).getHostAddress(),
"accept,connect")
}
El cdigo de verificacin de acceso para este mtodo llama a c h e c k Co n n e c t en los
siguientes casos:
else {
port = p.getPort();
host = p.getAddress().getHostAddress();
if (port == -1) java.net.SocketPermission
"{host}","resolve"
else java.net.SocketPermission
"{host}:{port}","connect"
}
~~~~~~~~~
MulticastSocket(...)
checkListen({port})
El cdigo de verificacin de acceso para este mtodo llama a c h e c k Lis t e n en los
siguientes casos:
if (port == 0)
java.net.SocketPermission
"localhost:1024-", "listen";
else
java.net.SocketPermission
"localhost:{port}","listen"
java.net.ServerSocket
ServerSocket(...)
checkListen({port})
El cdigo de verificacin de acceso para este mtodo llama a c h e c k Lis t e n en los
siguientes casos:
if (port == 0)
java.net.SocketPermission
"localhost:1024-","listen";
else
java.net.SocketPermission
"localhost:{port}","listen"
~~~~~~~~~
java.net.Socket
Socket(...)
checkConnect({host}, {port})
java.net.SocketPermission
"{host}:{port}", "connect"
java.net.URL
URL(...)
checkPermission
java.net.NetPermission "specifyStreamHandler"
java.net.URLConnection
java.net.URLClassLoader
URLClassLoader(...)
checkCreateClassLoader
java.lang.RuntimePermission "createClassLoader"
java.rmi.activation.ActivationGroup
java.rmi.server.RMISocketFactory
java.security.Identity
java.security.IdentityScope
java.security.Permission
java.security.Provider
SecureClassLoader(...)
checkCreateClassLoader
java.lang.RuntimePermission "createClassLoader"
java.security.Security
java.security.Signer
java.util.Locale
java.util.zip.ZipFile
ZipFile(String name)
checkRead
java.io.FilePermission "{name}","read"
Oz it o
Apndice C: Mtodos del Controlador de Seguridad
Esta tabla lista los permisos chequeados mediante las implementaciones de los
mtodos de ja v a . la n g . S e c u rit y Ma n a g e r. Cada mtodo de chequeo llama al
mtodo S e c u rit y Ma n a g e r. c h e c k P e rm is s io n con el permiso indicado, excepto
para los permisos c h e c k Co n n e c t y c h e c k Re a d que toman un argumento de
contexto. Los mtodos c h e c k Co n n e c t y c h e c k Re a d esperan que el contexto sea
un Ac c e s s Co n t ro lCo n t e x t y llaman al mtodo c h e c k P e rm is s io n del permiso con
el permiso especificado.
public SecurityManager();
java.lang.RuntimePermission "createSecurityManager";
Oz it o
Eplogo...
Esta seccin no forma parte del tutor original de
Sun.
Podes encontrar la versin original en Ingls de este "Cu rs o s o b re
P ro g ra m a c i n Av a n z a d a e n Ja v a 2 " en las pginas de Trainings OnLine de la
propia Sun MicroSystem.
Mo n ic a P a w la n
Oz it o