You are on page 1of 57

UI S

DO
CL I
IN AT
CD GR

Precio: 6 €(España) (IVA incluido) • AÑO X. 2.ª ÉPOCA • Nº 116 • UNA PUBLICACIÓN DE: REVISTAS PROFESIONALES S.L.

6
„ Fuentes
e
z Ejemplo JAXB
z XML con
co Castor
z ADO.NET
ADO
a or
Maximiza la
portabilidad
z Técnicas
T c Direct3D
D 3D
z JNI
„ Programación
gr
z Castor
st r 0.9.5.3
5
, S.L. z NetBeans IDE 3.6
3ª z Cooktop
o to 2.5
1994 z Cygwin
w
z WiX

y además...
Ofimática, navegadores y clientes de correo,
tratamiento de imágenes, visualizadores,
compresores, grabadores, Internet y
multimedia.

Y ADEMÁS...
ACTUALIDAD
Ganadores del concurso ASP.NET
Lo mejor del Tech-Ed 2004
MIDDLEWARE
Migrando hacia ASP.NET
JAXB: un caso práctico
Enlace de datos XML con Castor
BASES DE DATOS
Transacciones con ADO.NET
DISEÑO
Software moderno OO
Conecta Java con XML
ALGORITMOS Acceso a datos XML
Creación de gráficos con Direct3D mediante JAXB
Acceso a código nativo con JNI Mapeo entre documentos XML
CANAL PANDA y objetos Java con Castor
Defensa contra nuevos virus

Noticias, javaHispano, Libros, Preguntas y Respuestas


EDITORIAL
Expectativas superadas
Número 116 - septiembre 2004 Cuando en 1998 el W3C liberó la primera versión del llamado eXtensible Markup Langua-
Edita: REVISTAS PROFESIONALES S.L. ge o XML en ningún caso nadie imaginó las posibilidades que con ello se abrirían en el cam-
solop@revistasprofesionales.com
po del tratamiento de la información. De hecho, lo sorprendente del caso es que la industria
C/ Valentin Beato 42, 3ª. 28037 - Madrid.
del sector ha aceptado de forma masiva el uso de esta tecnología. Acostumbrados a ver co-
http://www.revistasprofesionales.com mo nuevas iniciativas son aceptadas por unos pero rechazadas por otros, no deja de ser una
Editor
agradable sorpresa el ver cómo XML, pese a su "juventud", goza de tanta salud. Y es que co-
Agustín Buelta mo se publica en el W3C, XML (algunos lo llaman el nuevo estándar de Internet) no precisa
•••••••••••••••••••••••••••••••••• licencia para ser usado, ofrece independencia de plataforma, puede trabajar con multitud de
Coordinación Técnica-Redacción herramientas y con cualquier aplicación que pueda procesar texto. Estos motivos pueden ex-
Carlos Laparra plicar el alto grado de implantación que ha experimentado una solución como XML.
••••••••••••••••••••••••••••••••••
Maquetación y tratamiento de imagen
Sin embargo, lo que nadie negará es que XML "está de moda", y esto hace que quizás se cai-
Mar Núñez ga en un abuso de esta tecnología. En cualquier caso, entendemos que XML es una solución más,
•••••••••••••••••••••••••••••••••• que no resolverá todos los problemas relacionados con el tratamiento de información, sin em-
Asesoría de Publicidad bargo como desarrolladores estamos obligados a contemplarlo como una opción más.
Felipe Ribagorda El lector encontrará en este número dos artículos con los que podrá introducirse en el uso
Tel.: (91) 304 87 64
Barcelona
de esta tecnología en combinación con Java, pues combinando XML y Java la portabilidad
C/ Rocafort, 241/243, 5º 1ª que conseguimos en nuestras aplicaciones es máxima.
Mariano Sánchez
Tel.: (93) 322 12 38
•••••••••••••••••••••••••••••••••• SUMARIO
Suscripciones
902160443 (de 10:00 a 13:00) ACTUALIDAD
Fax: (91) 327 13 03
••••••••••••••••••••••••••••••••••• 12. Concurso de Microsoft sobre programación web con ASP.NET
Impresión 13. Microsoft Tech-Ed Europe 2004
Ideas de Impresión
•••••••••••••••••••••••••••••••••••
Distribución MIDDLEWARE
Motorpress Ibérica
16. Migración de aplicaciones: de VB 6.0 a .NET (y III)
22. Tratamiento de XML desde Java (y III): un caso práctico
28. Enlace de datos XML con Castor
Distribución Mexico
Pernas & Cia
Editores y Distribuidores SA de CV BASES DE DATOS
C/ Poniente, 134 - Nº650
Col. Ind. Vallejo 34. Acceso a datos con ADO.NET (y III)
02300 (Mexico)
DISEÑO
Distribución Argentina 42. Introducción al software moderno orientado a objetos
Capital Federal: Distrimachisa
Interior: York Agency, S. A.
Tel. (005411) 43 31 50 51
ALGORITMOS
•••••••••••••••••••••••••••••••••• 48. Direct3D 9.0 avanzado (II)
La revista Sólo Programadores no tiene por qué
estar de acuerdo con las opiniones escritas por sus 54. Acceso a código nativo con JNI (y II)
colaboradores en los artículos firmados.
El editor prohibe expresamente la reproducción además…
total o parcial de los contenidos de la revista
sin su autorización escrita. 04. Noticias
Depósito legal: M-26827-1994 08. javaHispano: Java 5.0, JDIC, FreeTTS, WebCream 5.0, 3D y más
PRINTED IN SPAIN
COPYRIGHT 30-6-2004
10. Canal Panda: Defensa contra nuevos virus
P.V.P. 6,00 Euros 14. Curso de ASP.NET
Precio en Canarias, Ceuta y Melilla: 40. Sólo Programadores en formato digital
6,15 Euros
62. Preguntas y respuestas
64. Libros: Desarrollo web con J2EE y Visual Basic .NET
Asociación Española de Editoriales 66. Contenido del CD-ROM
de Publicaciones Periódicas
NOTICIAS

IBM albergarlos, caracte-


rísticas fundamenta-
IBM alcanza el 50% del mercado mundial de les en aquellos nego-
supercomputación cios que necesitan de
su potencia.
El ranking 'TOP500' establece una clasificación de los superordena- Otros motivos que
dores más potentes del mundo. IBM ha hecho público que, en dicha explican el liderazgo
clasificación, destaca como proveedor líder de sistemas de super- de IBM en supercom-
computación, tanto por el número de surperordenadores integrados putación son, por ejemplo, que de los 10 primeros superordenado-
en el ránking (224) como por el total de potencia instalada, con un res del ranking, 3 son IBM, mientras que entre los primeros 20, 10
record de 407 teraflops (billones de operaciones por segundo). son IBM. De entre los 100 primeros, 68 son IBM. Por otra parte, el
Por primera vez en la historia, los dos prototipos del superordena- 30% de los cluster Linux instalados en el mundo son IBM, lo que
dor de IBM Blue Gene, llamados Blue Gene/L, aparecen entre los 10 equivale a 150 superordenadores.
primeros puestos de esta lista. El BlueGene/L repre- Los motivos expuestos anteriormente explican los
senta un nuevo concepto en los superordenadores buenos resultados que ha obtenido IBM en el último
ya que su tamaño es 20 veces menor que el de las estudio "TOP500 List Supercomputing Sites", el rán-
máquinas existentes hoy día con la misma potencia. king independiente de mayor prestigio en el campo
Estos sistemas permiten así una gran reducción en el de la supercomputación. El listado completo puede
consumo energético, el coste y el espacio necesario para consultarse en la dirección www.top500.org

SUN MICROSYSTEMS rias para desarrollar Applets, aplicaciones y JRE (Java


Runtime Environment). Está disponible para su descarga en
Sun lanza J2SE 5 Beta 2 http://java.sun.com/j2se.
Sun centra sus esfuerzos en mejorar el rendimiento de la plataforma
Conocida hasta la fecha como Proyecto Tiger, la Java, y en los últimos días ha anunciado los resultados de una prueba
nueva versión de la plataforma Java introduce que demuestra las escalabilidad sin precedentes de J2SE 5.0. Sun
importantes mejoras en lo que se refiere a facilidad alcanzó resultados record en la prueba de rendimiento SPECjbb 2000
de desarrollo, incluye nuevas prestaciones de moni- (Standard Performance Evaluation Corporation Java Business
torización y gestión de aplicaciones, ofrece un sopor- Benchmark 2000) con JDK 5.0 ejecutándose sobre un Sun Fire V20z a
te cliente mejorado para escritorios de PC y cuenta 2,4 Ghz, basado en procesadores AMD64 Opteron. La configuración
con un rendimiento que bate records. Los lectores ya ofreció 59,648 JBB operaciones por segundo en el SPECjbb 2000 en
pudieron comprobar las novedades del Proyecto un sistema de dos vías con arquitectura de 64 bits, superando en un
Tiger en el número 112 de Sólo Programadores. 9% los mejores resultados obtenidos en esta área hasta la fecha.
Sun ha liberado recientemente la versión Beta 2 Además, la prueba indicó que Sun tiene la capacidad de soportar
del kit de desarrollo de software (SDK) para J2SE más warehouses que cualquier otro sistema de dos vías. La com-
5.0 (véase la sección "javaHispano" aportada por la comunidad pañía ha demostrado que es capaz de soportar 80 warehouses,
javaHispano.org para ampliar esta información), que incluye esto es, 10 veces la cantidad que típicamente soporta una confi-
herramientas tales como compiladores y depuradores, necesa- guración de dos vías.

TQS

El mundo académico y el mundo profesional unen


sus esfuerzos
proyectos de investigación en áreas de interés común. Además se contempla
TQS (Tecnología y Calidad de Software), empresa especializada en la presta- el asesoramiento mutuo y el intercambio de información y documentación
ción de servicios de consultoría e ingeniería en el campo de las tecnologías en cuestiones que sean de interés para las dos entidades. TQS y la UEM tie-
de la información y en el de la gestión de calidad, ha firmado un acuerdo de nen previsto reunirse periódicamente para dar continuidad a este convenio a
colaboración con la Universidad Europea de Madrid (UEM), que entrará en través nuevas actividades.
vigor el próximo curso 04/05. Uno de los aspectos más importantes que contribuye a cumplir el objetivo
El objetivo que persiguen tanto TQS como la UEM con este acuerdo es refor- principal de esta relación, es la difusión y la promoción de los cursos de pos-
zar los vínculos entre la vida universitaria y la vida profesional en el área de tgrado de la Universidad en el área informática.
desarrollo, calidad y mantenimiento de software. Las diferentes actividades y proyectos que se organicen dentro del marco de
Como fruto de este acuerdo, TQS y la UEM han establecido los cauces para esta colaboración estarán impartidos por parte del entrono universitario por
llevar a cabo actividades conjuntas de formación, asesoramiento e investiga- profesores, docentes e investigadores con amplia experiencia en el área de
ción que aporten un beneficio intelectual a los alumnos universitarios y a los desarrollo, calidad y mantenimiento de software; por otro lado los expertos
profesionales que trabajan en la empresa. en tecnología, los profesionales comerciales y los diseñadores de productos
Ambas partes colaborarán en actividades formativas tales como cursos, semi- de gran calidad, que forman parte del equipo de TQS, transmitirán a los asis-
narios, congresos, etc. así como en la realización y financiación de estudios y tentes sus conocimientos adquiridos a través de su experiencia profesional.

SOLO PROGRAMADORES 4
NOTICIAS

NOVELL incluye soporte just-in-time (JIT) y precom-


Novell anuncia la disponibilidad de Mono 1.0 pilación. Además, el proyecto Mono ofrece:
z Un entorno avanzado de desarrollo para
Novell anunció días atrás el lanzamiento de la primera versión del pro- escribir aplicaciones Linux con una pro-
yecto Mono, esto es, Mono 1.0. Mono es una plataforma de fuente ductividad sin precedentes.
abierta basada en el Framework .NET que permite a los desarrollado- z Una API completa que permite el des-
res de software construir aplicaciones Linux y multiplataforma. arrollo de aplicaciones cliente/servidor
Mono incluye un compilador C#, un runtime compatible .NET, dos y servicios web.
librerías de APIs, una librería Mono y un grupo de APIs compatible z Capacidades de despliegue multiplataforma, soporte para Linux,
con el Framework 1.1 de Microsoft .NET que ofrecen soporte para Sun Solaris, Apple MacOS X, Microsoft Windows NT/XP y otros
ASP.NET, ADO.NET y para otros componentes. Además, con el objeti- sistemas UNIX sobre una variedad de arquitecturas.
vo de ofrecer un mayor soporte a los desarrolladores de software, z Herramientas altamente efectivas que facilitan la creación de
Novell ha puesto en marcha un nuevo sitio web (http://www.mono- APIs y kits de desarrollo de software (SDK) independiente de la
project.com) que incluye herramientas, recursos, un roadmap del pro- plataforma.
yecto, así como información detallada sobre Mono. Este nuevo sitio, z Librería de programación multiplataforma que permite a los des-
a diferencia de los que ya hay (centrados en la creación y contribu- arrolladores trabajar con Linux, Windows y MacOS X con un único
ción de Mono) está orientado hacia los usuarios de Mono, a los que código, siendo este uno de los lenguajes soportados por Mono.
despliegan aplicaciones con Mono y a los que contribuyen al mismo. z Suporte para lenguajes tales como VisualBasic, Python, JScript y
Son cientos los desarrolladores que contribuyen al proyecto Mono en Java. A través del proyecto de fuente abierta iKVM, Mono inclu-
todo el mundo, convirtiéndolo en una plataforma recomendada para ye soporte Java, haciendo del popular lenguaje un vehículo
construir aplicaciones de escritorio sobre los sistemas operativos Linux. capaz de respaldar la tecnología Mono.
Mono 1.0 incorpora componentes clave .NET, tales como los que se Mono 1.0 puede descargarse en:
han comentado anteriormente y un sistema de ejecución portable que http://www.mono-project.com/downloads/index.html.

SUN MICROSYSTEMS Indra como Sun y sus partners tecnológicos realicen en este área.
La Sociedad de la Información y el acceso a Internet: Por un lado, Indra ofrece una licencia gratuita para la utilización de
una plataforma Hardware y Software para fomentar la participa-
un derecho universal de todos los ciudadanos ción ciudadana a través del Ayuntamiento de Jun: captar la opinión
Luis Enrique Hernández Lucendo, director de Administraciones Públicas y de los ciudadanos, procesar resultados y realizar estadísticas.
Sanidad de Indra, Pedro Montarelo, director de marketing de Sun Por otro lado, Sun otorga una licencia gratuita para uso personal,
Microsystems Ibérica y José Antonio Rodríguez, primer teniente alcalde del educativo y de investigación a todos los ciudadanos de Jun del soft-
Ayuntamiento de Jun (Granada) han firmado un acuerdo que permitirá ware StarOffice 7.0, junto con una licencia de uso gratuita de su
universalizar el acceso a la tecnología de todos los habitantes de Jun y paquete de software Java Enterprise System tanto para todas las
fomentar la participación ciudadana en el gobierno del municipio. El ayun- PYME (empresas con menos de cien empleados) domiciliadas en
tamiento de esta localidad granadina ha declarado el acceso a Internet y Jun como para el Ayuntamiento. De izquierda a derecha
la Sociedad de la Información un derecho universal de todos sus ciudada- Enrique Hernández, director
nos. Dicho ayuntamiento fue pionero también en la celebración del primer de AA.PP. y Sanidad de
pleno de la teledemocracia en Europa y, en las pasadas elecciones andalu- Indra, Zaida Sampedro,
Gerente de AA.PP. y Sanidad
zas del 14 de marzo, Jun fue el escenario de una exitosa experiencia pilo- de Indra, José Antonio
to de voto electrónico por Internet y a través de telefonía móvil. Rodríguez, Primer Teniente
Gracias al acuerdo firmado, el Ayuntamiento de Jun accederá de de Alcalde del Ayuntamiento
forma preferente a las nuevas aplicaciones y desarrollos que tanto de Jun y Pedro Montarelo,
Director de Markentig de Sun
Microsystems Ibérica.

TRANSCEND INFORMATION ciones de 640 x 480 píxeles o registrar hasta seis horas de vídeo MPEG 4.
Necesidades de almacenamiento insaciables A diferencia de otros fabricantes, Transcend insiste en usar sólo chip
Flash NAND SLC (Single-Level-Cell) al que se le supone una superior
El consumo de dispositivos multimedia crece día tras velocidad de escritura, menor consumo de potencia y mayor duración
día, y con ello las necesidades de almacenamiento. en comparación con tarjetas Secure Digital realizadas con chip MLC
Este hecho ha empujado a Transcend Information a (Multi-Level-Cell).
anunciar el aumento de la capacidad de sus tarjetas Además, esta tarjeta SD 45X Ultra Performance puede alcanzar una
Secure Digital (SD) 45X hasta 1 GB. velocidad de lectura de de hasta 7.7 Mbps y una velocidad de escritu-
Con esta tarjeta SD de elevada capacidad, se pueden ra de hasta 6.8 Mbps. Por lo tanto se convierte en una solución pro-
almacenar más de 13.000 fotografías JPEG con resolu- fesional al alcance de todos.
NOTICIAS

PANDA SOFTWARE tante de otros aparatos a los que enviarse,


El gusano Cabir amenaza la seguridad de los teléfonos aunque para ello deben encontrarse conecta-
dos mediante la tecnología Bluetooth. Este
móviles proceso acorta considerablemente el tiempo
PandaLabs ha identificado a Cabir, el primer gusano capaz de de operación de la batería del teléfono.
propagarse a través de teléfonos móviles. Concretamente, afec- Por otra parte, existe la posibilidad de que el
ta aquellos dispositivos que funcionan bajo el sistema ope- fichero Caribe.sis se copie en otro tipo de
rativo Symbian OS, utilizado en muchos modelos de aparatos que utilicen tecnología Bluetooth
teléfonos, entre los que se encuentran algunos (como pueden ser algunas impresoras), aunque no utilicen el
fabricados por las empresas Nokia, Siemens y Sony sistema operativo antes mencionado. En estos casos, el
Ericsson. gusano no podrá continuar su propagación.
Cabir no ha sido diseñado para propagarse masiva- La aparición de Cabir da paso a una nueva era para la
mente, sino que se trata de una prueba de concepto seguridad informática, cuyo ámbito ya no se restringe
que demuestra que pueden hacerse códigos maliciosos a los usuarios de ordenadores. "A partir de ahora,
para este tipo de dispositivos. antes de adquirir un dispositivo móvil deberán eva-
Cabir se propaga en forma de un archivo llamado Caribe.sis, luarse no solamente sus funcionalidades; también
que se instala automáticamente en el sistema cuando el usuario habrá que prestar mucha atención a los sistemas de
acepta la transmisión. En ese momento, muestra un mensaje en seguridad de los que dispone", concluye Luis Corrons,
pantalla con el texto: Caribe. Tras ello, inicia una búsqueda cons- director de PandaLabs.

locales o remotos. El tráfico de datos generado por gsBase es


GALDON mínimo y por lo tanto, el ancho de banda necesario para soportar
el trabajo del entorno multiusuario es muy pequeño, lo cual se
Galdón lanza nuevas mejoras en su herramienta gsBase traduce en costes de comunicaciones muy reducidos.
En su inquietud por ampliar mercado y pensando en la interna-
Galdón, compañía española especializada en el des- cionalización de su nuevo sistema, Galdón ha puesto en mar-
arrollo de software y creadora del gsBase (Galdón cha una nueva fase de su proyecto I+D, con el objetivo de
Software Base), ha anunciado que continúa avanzan- permitir a los consultores y desarrolladores de esta solución
do en la mejora de su herramienta. La solución gsBase poder definir sus aplicaciones en multilenguaje de una
puede entenderse como un sistema de diseño y ejecu- forma fácil y operativa. También han sido liberados contro-
ción de aplicaciones informáticas que utilicen bases les Active-X para atacar a servidores gsBase desde la
de datos, comunicaciones y cálculo (ERPs, CRMs, etc.) web, PDAs o bien usando otros lenguajes de programa-
y ofrece al usuario una interfaz gráfica de ventanas. La ción como Visual Basic, Delphi, Java, etc.
arquitectura del gsBase radica en un sistema clien- Además, gsBase también está disponible para platafor-
te/servidor y utiliza el protocolo estándar TCP/IP mas Linux, ya que hasta el pasado mes de Junio
para comunicaciones, que permite el trabajo gsBase sólo estaba disponible para sistemas
concurrente de cientos de usuarios finales Windows.

SUN MICROSYSTEMS terísticas como ventanas transparentes, rotación, zoom, entornos de trabajo
múltiples y miniaturización.
Sun aporta a la comunidad de código abierto tecnología 3D La versión para desarrolladores del Proyecto Looking Glass aportada por Sun
a la comunidad de código abierto ayuda a crear entornos de escritorio y apli-
Sun Microsystems quiere reafirmar su compromiso con el movimiento de caciones visuales en 3D capaces de ejecutarse sobre Solaris y sistemas Linux
código abierto al aportar el Proyecto Looking Glass y la tecnología Java 3D a como Java Desktop System. Esta versión persigue incitar a los desarrollado-
la comunidad de código abierto. Estas contribuciones (que forman parte de res de aplicaciones Java a explorar nuevas vías en el modo en que la infor-
la iniciativa Sun 3D Desktop Technology Open Source Project) propiciarán, mación y los datos se presentan al usuario.
según se afirma desde Sun, una nueva dimensión de innovaciones en la cre-
ación de aplicaciones. Iniciativas como esta permiten a los desarrolladores
acceder a las tecnologías englobadas en Sun 3D Desktop Technology Open
Source Project desde la comunidad online java.net (http://www.java.net).
Los lectores de Sólo Programadores ya tuvieron ocasión de conocer el
Proyecto Looking Glass en el número anterior, en la sección aportada por
javaHispano.
Para los que no hayan seguido la evolución de este asunto, diremos que la
primera demostración ante el público del Proyecto Looking Glass se realizó
en verano de 2003. Esta iniciativa fue la primera que despertó el interés de la
industria tecnológica por los entornos de escritorio tridimensionales, y la pri-
mera que se apartó del paradigma de las tradicionales ventanas. La innova-
dora interfaz del Proyecto Looking Glass ofrece un entorno intuitivo en 3D
que permite interactuar con las aplicaciones de escritorio, e incorpora carac-

SOLO PROGRAMADORES 6
JAVAHISPANO

Actualidad Java
de la mano de javaHispano
Nunca habrá un J2SE 1.5 o un J2EE 1.5

Por algún motivo el departamento de marketing de Sun mayor tiempo que lleva en el mercado la plataforma
Microsystems ha considerado conveniente cambiar el Java frente a .NET, actualmente en su versión 1.1 y cuya
sistema de versiones de la plataforma, cambio que afec- versión 2.0 aparecerá el año que viene.
ta ya a Tiger, la nueva revisión mayor de J2SE. A pesar de Estos caprichos con las versiones de los productos no
que hubo versiones Beta 1.5 de Tiger el número de la son nada sorprendente; recientemente BEA actualizó
versión estable, y el de la Beta 2, es el 5.0, y no el 1.5. Lo toda su familia de productos a la versión 8.1; antes sus
mismo sucederá con la próxima versión de J2EE, que productos (BEA Weblogic Portal, Integration, Server,
será la 5.0, y no la 1.5, que es la versión que se mencio- Liquid, JRockit, etc.) tenían versiones muy distintas. Por
na en el JSR 244, en el cual se está definiendo. otro lado nuca hubo una versión 8.0 en los productos
Desde Sun se justifica este salto en la numeración por de BEA, que parece preferir las versiones terminadas en
la enorme cantidad de cambios que se introducen en ".1" y no en ".0". El motivo último de estas decisiones
las nuevas versiones de la plataforma, los más notables queda para los departamentos de marketing de cada
desde la aparición de Java. Si este es realmente el moti- compañía; pero en lo que a nosotros atañe tendremos
vo cabría preguntarse por qué no se pasa a la versión que acostumbrarnos al nuevo versionado de la plata-
2.0, en vez de a la 5.0. Algunos opinan que el salto en forma, y abandonar la idea de desarrollar aplicaciones
el número de versión trata de reflejar la madurez y el con un JDK 1.5, sino con el 5.0.

Adobe construye una plataforma de servicios basándose en el formato PDF

Adobe pretende crear una nueva plataforma orienta- permitirá visualizar en formato PDF información pre-
da al servidor que permitirá automatizar y acelerar el cedente de cualquiera de las fuentes ligadas. La pla-
flujo de información dentro de una organización taforma también estará dotada de herramientas de
empleando documentos PDF. Esta plataforma, que se seguridad que permitirán entre otras cosas controlar
basa en J2EE, XML y los servicios web, recibe el nom- el acceso a la información del sistema, crear audito-
bre de "Intelligent Document Platform". Su fin es pro- rias del uso de la información, o verificar la autentici-
porcionar un modo único de conectar las diferentes dad de un documento mediante firmas digitales.
fuentes de datos de una empresa, permitiendo proce- Inicialmente Adobe ha orientado Intelligent Document
sar la información de modo automático y evitando Platform hacia organizaciones de gran tamaño, como
reintroducirla en el sistema. Para ello la información organismos gubernamentales o grandes empresas.
se representa en un formato que es básicamente PDF Quizás en un futuro Adobe cree versiones más simples
con una serie de extensiones basadas en XML. y reducidas de la plataforma que pudieran resultar más
Intelligent Document Platform podrá ligarse, por atractivas para organizaciones de menor tamaño, para
ejemplo, con los ERP o los CRM de una organización las cuales la solución actual probablemente resulte
empleando para ello servicios web y un API Java, y excesiva, tanto en complejidad como en funcionalidad.

Accediendo desde Java a aplicaciones nativas: JDesktop Integration Components

JDesktop Integration Components (JDIC) tema. También permite registrar aplicaciones Java
(https://jdic.dev.java.net/) es un proyecto distribui- en un sistema y asociarlas con un tipo de archivo.
do bajo licencia LGPL cuyo fin es hacer accesible Dentro de JDIC hay dos subproyectos interesantes,
desde Java aplicaciones nativas sacrificando la aunque aún no son completamente funcionales:
portabilidad de la aplicación lo menos posible. JDIC SaverBeans Screensaver SDK, un kit de desarrollo
permite, por ejemplo, acceder al cliente de correo, que permite crear protectores de pantalla multipla-
al navegador web, o a la aplicación que está aso- taforma, y Tray Icon API, que permite a las aplica-
ciada con un determinado tipo de archivo en el sis- ciones Java crear iconos en la bandeja del escritorio.

SOLO PROGRAMADORES 8
JAVAHISPANO
http://www.javahispano.org

Liberada Berkeley DB Java Edition 1.5

ción de la versión Java de esta base de


datos ha tenido una buena acogida por
parte de la comunidad Java, así por ejemplo
Apache Foundation ha hecho públicas sus
intenciones de emplear esta solución en el
servidor Apache Directory.
Berkeley DB Java Edition, al igual que la
SleepyCat Software ha lazado una versión aplicación cliente, lo que permite eliminar versión desarrollada en C, se distribuye bajo
java de su base de datos empotrada el cuello de botella de la comunicación una doble licencia libre-comercial: el pro-
Berkeley DB, la base de datos empotrada cliente-servidor en aquellas aplicaciones ducto puede incluirse como software libre
que cuenta con un mayor número de uni- que se pueden permitir tener una base de en cualquier desarrollo cuyo código fuente
dades distribuidas (más de 200 millones). datos local. sea libre, mientras que los desarrollos de
Esta base de datos puede ejecutare en el Berkeley DB tiene un soporte de ACID y de código propietario deben optar por la licen-
mismo espacio de memoria que la propia recuperación de datos completo. La crea- cia comercial para emplear la base de datos.

Soporte para voz en las aplicaciones Java: FreeTTS LISTADO 1 Dale voz a tu PC

FreeTTS (http://freetts.sourceforge.net) es un da al usuario, leer un Voice voz = VoiceManager.getIstance().getVoice("Kevin16");


voz.allocate();
sintetizador de voz escrito completamente en texto, crear un servi- voz.speak("Something is wrong");
Java con un soporte parcial de la especificación dor de telefonía auto-
JSAPI 1.0 (Java Speech API, véase Sólo matizado, o simplemente hacer más humanas voces inglesas, aunque es posible crear voces
Programadores 109, 110 y 111). Ha sido des- nuestras aplicaciones Java. Su uso es muy sim- propias en cualquier idioma y emplearlas desde
arrollado en los laboratorios de investigación ple; así por ejemplo el código del listado 1 nos FreeTTS. Sin embargo, y aunque existen herra-
de Sun Microsystems, y se distribuye bajo permite pronunciar con una voz masculina de mientas con tal fin, la creación de nuevas voces
licencia BSD. Este sintetizador de voz puede 16 KHz la frase "Something is wrong". La prin- dista mucho de ser tan simple como el uso de
emplearse, por ejemplo, para dar ayuda habla- cipal carencia de FreeTTS es que sólo soporta las ya integradas en FreeTTS.

Del escritorio a la web de modo transparente: WebCream 5.0

La compañía Creamtec recientemente ha hecho esos eventos, y genera una aplicación web equi- comporta-
pública la versión 5.0 de WebCream, una herra- valente con una apariencia y comportamiento miento de la
mienta que permite convertir una aplicación de muy similar a la aplicación de escritorio. aplicación
escritorio basada en Swing o AWT en una apli- En la imagen podemos observar la apariencia de original es
cación web de un modo totalmente transparen- la demo de Swing que se distribuye con el JDK total, si bien
te para el desarrollador. WebCream captura 1.2 o superior de Sun en el directorio las respues-
tanto la apariencia de la aplicación original como demo/jfc/SwingSet convertida a aplicación web tas a las acciones del usuario son más lentas por
sus eventos, y la lógica de negocio asociada a con WebCream. La fidelidad con la apariencia y la latencia de la red.

Las implementaciones de referencia de Java 3D y Java Server Faces pasan a ser libres

Recientemente Sun ha liberando una notable un proyecto muy prometedor: Looking Glass,
cantidad de código fuente, buena parte de él un escritorio tridimensional para entornos
relacionado con la plataforma Java. Entre Linux y Unix que podría volverse muy popular
este código están las implementaciones de en las distribuciones de Linux, ahora que la
referencia de Java 3D (https://java3d.dev. licencia de su código es GPL. Por otro lado
java.net, véase Sólo Programadores 113 y hace bastantes meses que en la compañía se
114) y de Java Server Faces (https://javaser- está estudiando la posibilidad de distribuir
verfaces.dev.java.net), que se han convertido Solaris bajo una licencia libre tipo GPL. Parece
en proyectos de java.net. que cada vez más Sun apuesta por el softwa-
Sun también ha liberado el código fuente de re libre como modelo de negocio.

Sobre el autor
Abraham Otero (abraham.otero@javahispano.org)
es responsable de calidad y miembro de la junta de javaHispano. (http://www.javahispano.org)

9 SOLO PROGRAMADORES
CANAL PANDA

Defensa contra nuevos


virus
FERNANDO DE LA CUADRA Los últimos tiempos han supuesto un nuevo reto en
el mundo de la tecnología antivirus. Las amenazas ya
Las nuevas soluciones antivirus no no tardan meses, ni días en propagarse: ¡les bastan
pueden basar su estrategia en la unos minutos! Códigos como SQLSlammer, Blaster o
Sasser son capaces de propagarse tan rápidamente
detección y la posterior eliminación, que los usuarios no tienen tiempo material para
ya que el tiempo del que se dispone reaccionar ante ellos. Los creadores de virus saben
que existe un tiempo en el que los ordenadores están
es muy limitado, por la rapidez con indefensos, e intentan que los virus ataquen precisa-
la que se contaminan los equipos. mente en ese pequeño espacio de tiempo.
En un sistema antivirus clásico, los virus son detec-
Una mejor solución será actuar tados en función de las características que tiene
anticipándonos al comportamiento cada programa. Al igual que un código genético,
cada virus dispone de unos cuantos bytes que son
del virus, es decir, a priori en lugar únicos e irrepetibles, que se utilizan para buscar
de a posteriori. cada virus. Pero, como hemos comentado antes, es
necesario un tiempo para distribuir la actualización
del antivirus que detecte y elimine el virus.
Hace 14 años, Panda Software inició su andadura en La solución a los nuevos virus no puede basarse en
el mundo de los antivirus. Su primer producto era un una detección a posteriori, ya que el tiempo para
sencillo antivirus que era capaz de detectar y desin- detenerlos es escaso, sino que debe estar organi-
fectar ¡tres virus! No es una cifra espectacular, y está zada en torno a las acciones que el virus pueda lle-
muy lejos de los 70.000 virus de hoy en día, pero en var a cabo. Si observamos cómo se comportaron
1.990 era más que suficiente para las necesidades los virus anteriormente citados, todos ellos explo-
básicas. No hay que olvidar que por esas fechas los taban alguna vulnerabilidad del sistema operativo,
ordenadores personales no estaban tan extendidos, por lo que a través de ella puede conseguirse la
eran casi un lujo y no todas las empresas estaban solución. Y no me refiero al clásico "parcheado" de
informatizadas al nivel actual. los equipos, que aunque se ha demostrado com-
Según fueron pasando los años, la tecnología utilizada pletamente eficaz para la prevención no es lleva-
para la detección de los virus fue mejorando considera- do a cabo con la rapidez necesaria. Me refiero al
blemente. Los creadores de los virus iban siendo cada vez control de los "exploits" para las vulnerabilidades.
más hábiles para hacer que los antivirus no detectaran Sasser, por citar el ejemplo más cercano, producía
sus códigos, mientras que los desarrolladores de antivirus un desbordamiento de buffer aprovechando una
creaban nuevos métodos de detección y desinfección. vulnerabilidad. Si se instala en el ordenador un sis-
Cuando Internet empezó a popularizarse, los adminis- tema de vigilancia de las tareas que están ejecután-
tradores vieron cómo los virus empezaban a propa- dose, y de su actividad a la hora de interactuar con
garse por canales a los que los antivirus clásicos no el sistema operativo, puede evitarse un uso inade-
podían acceder. El correo electrónico, por ejemplo, cuado de la pila de datos de los programas (el buf-
supuso una fuente inagotable de sustos víricos para fer) que pueda resultar perjudicial para el sistema.
aquellas redes con protecciones antivirus anticuadas. La idea no es nueva. Cuando los virus de boot esta-
Además, los virus dejaron de ser un problema local ban ampliamente difundidos, muchos fabricantes
para convertirse en una lacra a nivel global. Gracias a de placas base desarrollaron sistemas "antivirus",
Internet la propagación de un virus ya no se restringía simplemente grabando programas que evitaran
a una determinada área, sino que las fronteras pasa- escrituras en los sectores de arranque de los discos.
ron a ser una mera anécdota. Es una protección básica, que intenta evitar la
Otro factor muy importante fue la velocidad con acción del virus en lugar de detectar y eliminarlo.
la que los nuevos virus se propagaban. Si antes un La protección futura contra códigos maliciosos
Con el objetivo de dar protección a las virus podía tardar meses en distribuirse, gracias a basada en la vigilancia de procesos es la clave para
grandes corporaciones, pero también a
los particulares, Panda Software ofrece Internet el tiempo quedó reducido a unos escasos poder proteger no ya solo un ordenador, sino toda
una amplia oferta de soluciones días. La actualización del software contra los virus una red, contra las nuevas amenazas que se difun-
antivirus. empezaba a ser más necesaria que nunca, hasta el den a gran velocidad. Funcionando en conjunto con
punto de llegar a tener una frecuencia diaria. los antivirus clásicos, y soportado por un sistema de

SOLO PROGRAMADORES 10
CANAL PANDA
Defensa contra nuevos virus

vigilancia y desarrollo de las empresas antivirus que antivirus actuales son capaces de ofrecer este nuevo
pueda dar respuesta casi inmediata a las sospechas tipo de tecnologías. Sólo podrán ofrecerlas aquellas
de virus transmitidas por el sistema, es ya, sin duda, que tengan departamentos de investigación, desarro-
la protección que las empresas necesitan. llo e innovación trabajando en ellas, y hayan sabido
Sin embargo, no todas las empresas desarrolladoras de detectar el problema con antelación.

Sobre el autor
Fernando de la Cuadra (Fdelacuadra@pandasoftware.com) es editor técnico internacional de Panda Software
(http://www.pandasoftware.com).

Hoaxes informáticos: un peligro fácilmente


evitable
Los hoaxes son un tipo de malware bastante simple
pero no por ello menos efectivo. Se trata de e-mails
que contienen información engañosa sobre los temas
más diversos. Así, pueden avisar sobre virus inexisten-
tes excepcionalmente dañinos, o acerca de "leyendas
urbanas" de todo tipo.
En muchas ocasiones, los hoaxes informáticos son cre-
ados por usuarios maliciosos que sólo pretenden gastar
una broma pesada. También pueden servir para recoger
un gran número de direcciones de correo electrónico a
las que, posteriormente, enviar mensajes de correo no
deseado o spam.
Algunas veces, los hoaxes pueden causar graves perjui-
cios a los usuarios. Es el caso de Sulfnbk, uno de los más
extendidos y que lleva más de tres años en circulación. todo el mundo. Pero no contiene virus alguno, sino que
se trata de un fichero necesario para el funcionamiento En los laboratorios de investigación
El texto del mensaje anuncia que un peligroso virus ha de Panda Software (PandaLabs)
infectado muchos ordenadores, sin que los usuarios lo del sistema operativo. Por tal motivo, en caso de ser se trabaja intensamente
sepan, y se esconde en los equipos en un archivo con el borrado, el ordenador dejará de funcionar normalmente. para proporcionar herramientas
nombre Sulfnbk.exe. En caso de que el fichero se Una buena medida para cortar la propagación de los y ayuda para la detección
hoaxes es aplicar al correo electrónico reglas de filtrado y desinfección de nuevos virus.
encuentre en el sistema, el hoax recomienda eliminarlo
inmediatamente. Efectivamente, el archivo Sulfnbk.exe de contenidos, de manera que los falsos mensajes sean
existe y se encuentra en millones de ordenadores de eliminados directamente sin que puedan ser leídos.

Prevenir los ataques basados en enlaces maliciosos


Algo tan cotidiano y aparentemente inofensivo como un legítimo, pudiendo falsificar el aspecto del web o enviar
enlace web puede ser el origen de un sofisticado ataque al atacante datos confidenciales de la sesión que el
Cross Site Scripting (XSS), o bien el cebo para un fraude usuario ha iniciado.
bancario online (phishing). A continuación se repasarán Las técnicas de phishing, que tienen como objetivo
las técnicas más utilizadas y las medidas básicas para engañar a los usuarios para conseguir datos confiden-
prevenir dichos ataques. ciales, como, por ejemplo, las claves de acceso a sus
El ataque Cross Site Scripting (XSS) tiene su origen en la cuentas bancarias, suelen basarse también en enlaces
posibilidad de que una aplicación web legítima devuelva, fraudulentos. Normalmente se presentan en forma de
como parte de su respuesta, un código malicioso enviado mensajes de correo electrónico supuestamente enviados
por un atacante. Este tipo de vulnerabilidad suele estar por las propias entidades, en los que se solicita al usua-
presente en formularios y consultas web que no realizan rio que acceda a una dirección web que, en realidad,
los filtros adecuados y permiten inyectar código. redirige a un servidor que tiene el mismo aspecto que el
La técnica más habitual de XSS se basa en un enlace del servicio bancario legítimo, pero que enviará todos
especialmente construido por un atacante que incluye los datos suministrados a los atacantes.
en la URL el código malicioso. Esta dirección suele ser La recomendación más básica consiste en no acceder a
publicada en foros web o puede ser enviada a través de los enlaces que lleguen a través de correo electrónico o
correo electrónico a potenciales víctimas, a las que que se encuentren en páginas web no fiables. Debería
intenta engañar con diferentes artimañas para que utili- tenerse especial cuidado en caso de que los enlaces per-
cen el enlace. En caso de conseguirlo, se realizará una tenezcan a servicios de banca electrónica, o donde se Panda Software pone a nuestra
petición al servidor web incluyendo el envío del código soliciten datos confidenciales tales como usuario y con- disposición su antivirus on line gratuito:
malicioso incrustado en la URL. Debido a la vulnerabili- traseña. Lo ideal en estos casos es escribir directamente ActiveScan.
dad de la aplicación web, el servidor devolverá al nave- la URL en la barra de direcciones de nuestro navegador
gador del usuario el código malicioso como si fuera o seleccionarla desde nuestra lista de favoritos

11 SOLO PROGRAMADORES
ACTUALIDAD

Ganadores
a do e del
de concurso
o s de programación
progra a ón webb con
o ASP.NET
AS . E
Acerca del concurso Primer premio y agradable pero con el máximo rigor, dicho
jurado se pronunció. Queremos aclarar a los
z Una consola de videojuegos Xbox más un
El pasado 1 de Abril fue la fecha elegida por lectores que los criterios que tuvo en cuenta el
Microsoft Ibérica para dar el pistoletazo de salida juego, mando a distancia para ver DVDs en jurado para hacer una valoración de los pro-
al concurso de programación web con ASP.NET la Xbox y una película DVD. yectos presentados fueron, a grandes rasgos, la
z Un visual Studio .NET 2003 Enterprise
que finalizó el pasado 15 de Junio. calidad de la capa de presentación, la proce-
Este concurso, patrocinado por distintos medios Developer. dencia del código, la usabilidad, la fiabilidad y
z Alojamiento gratuito ASP.NET con una de las
entre los que se encuentra Sólo Programadores, la originalidad. Bajo estos parámetros debe
ha nacido con la idea de animar a los desarrolla- empresas patrocinadoras durante un año. entenderse el veredicto del jurado, que se
z Suscripción gratuita a una de las revistas
dores a participar en una experiencia de progra- muestra en las tablas de la parte inferior.
mación con ASP.NET. La idea que ha perseguido patrocinadoras durante un año. El lector puede quedar sorprendido al ver que no
esta iniciativa ha sido difundir la tecnología Segundo premio todas las categorías tienen 1º, 2º y 3º premio. Esto
ASP.NET como una potente solución para aque- z Un juego para Xbox y una película DVD. ha sido así por decisión del jurado. El motivo de
llos programadores que deseen construir sitios z Un visual Studio .NET 2003 Professional. estas decisiones ha sido, siempre, intentar buscar
web. Sin duda la organización de una competi- z Alojamiento gratuito ASP.NET con una de las justicia y premiar a quien más ha trabajado. En
ción como esta es una fórmula original de entu- empresas patrocinadoras durante un año. este sentido, se consideró que, por ejemplo, no
siasmar, en primer lugar a aquellos que nunca han z Suscripción gratuita a una de las revistas había ningún proyecto dentro de la categoría
trabajado con ASP.NET, y en segundo lugar, a patrocinadoras durante un año. Portal que mereciera un 3º premio. Del mismo
aquellos programadores con horas de experiencia modo, se acordó que ningún proyecto de la cate-
que han querido evaluar sus conocimientos. Tercer premio goría Comunidad merecía un 1º premio. Por otro
Microsoft Ibérica ha dividido el concurso en 6 z Una película DVD. lado, en la categoría Tiempos el jurado consideró
categorías temáticas: Comercio, Informes, Portal, z Un Visual Basic .NET 2003 Sandard. que tan sólo uno merecía ser recompensado. Por
Comunidades, Tiempos y una categoría libre para z Suscripción gratuita a una de las revistas último, en la categoría Libre, se han dado dos 1º
dar rienda suelta a la creatividad. patrocinadoras durante un año. premios dado que el jurado decidió que ambos
trabajos eran merecedores de tal recompensa.
Premios puso a disposición del jurado 18 premios para que Desde estas líneas queremos agradecer a todos
éste pudiera premiar a las mejores aplicaciones. aquellos que habéis participado en el concurso,
Como en todo concurso, aquellos trabajos que y queremos animar a que, aquellos que no lo
han demostrado mayor dedicación e implicación Reunión y veredicto del jurado han hecho, lo hagan en posibles futuras edi-
han sido premiados. Es importante destacar que ciones. De igual modo, animamos al lector a
sólo por participar Microsoft Ibérica ha regalado Como ya anunció Microsoft Ibérica, el jurado visitar la web del concurso: http://www.micro-
dos entradas de cine a los concursantes. estuvo compuesto por una persona de cada soft.com/spanish/msdn/spain/concuasp. Allí se
Los premios a los que podía aspirar un participan- empresa de alojamiento, una persona de cada encuentran publicados todos los proyectos
te con su aplicación web dentro de una categoría revista colaboradora y personal de Microsoft presentados, y el lector podrá comprobar si en
son los que aparecen en el cuadro de la parte Ibérica. La reunión del jurado se celebró el día su opinión el jurado ha decidido correctamen-
superior. Por lo tanto, se deduce que Microsoft 23 de Junio y, en un ambiente muy distendido te o no.

Comercio Informes Libre


Net Shopping Generador de Informes Control de Precipitaciones
http://csanchez.veriospain.net/default.aspx http://gnieto.aspnet.acens.biz/informes/admin.aspx http://drodero.veriospain.net
1º 1º 1º
Constantino Sánchez Ballesteros José Ignacio Merino Martín Diego Rodero Pulido
Alcalá de Henares Montilla Linares
Comercio ASP Servidor de Encuestas Proyecto Freedom MSN
http://iperez.veriospain.net http://lvalles.veriospain.net http://fjrodriguez.veriospain.net
2º 2º 1º
Iván Pérez Lucía Valles Barbeito Fco. Javier Rodríguez Mesa
Madrid La Coruña LEON
Travel Agencia de Viajes ETeacher First Certificate Tutor Lector de Titulares para una Web
http://druiz.aspnet.acens.biz http://bmiller.veriospain.net http://pespinosa.veriospain.net
3º 3º 3º
David Ruiz Rincón Brent A. Miller Patrick Espinosa
Pamplona Córdoba Cerdanyola del Vallès

Tiempos Portal Comunidad


MC Servicios Informáticos Mehcca Film Ide-a: Industrial Design & Arts
http://jmmendoza.veriospain.net http://despinosa.veriospain.net http://lmguerrero.veriospain.net
2º 1º 2º
Jose Manuel Mendoza Contreras David Espinosa Regueiro Luis Miguel Guerrero Guirado
Sevilla Sestao Málaga
Portal de Programación Acceso Remoto y Multiplataforma a PIM
http://www.jvizcaya.veriospain.net http://www.davix.aspnet.acens.biz
2º 3º
Juan Vizcaya García David Marín Calleja
Mislata Puertollano

SOLO PROGRAMADORES 12
ACTUALIDAD

Microsoft Tech-Ed Europe 2004


29 de Junio - 2 de Julio,
Ámsterdam, Holanda
Como ya se anunció desde Microsoft y mitir el acercamiento, a
también desde la web de Sólo muy bajo coste, de aque-
Programadores, la 11ª edición en Europa llos desarrolladores no
del Tech-Ed tuvo lugar del 29 de Junio al profesionales que deseen
2 de Julio en Ámsterdam, Holanda. aprender a crear aplicacio-
Microsoft considera el Tech-Ed como uno nes basadas en la web y en el
de los eventos más importantes para el sistema operativo Windows.
desarrollo, implementación, seguridad y Como no podía ser de otra manera, la
gestión de soluciones conectadas. nueva versión del entorno de dearrollo
Microsoft Tech-Ed ofrece una buena para .NET, Visual Studio 2005 (Whidbey) Desarrollo sobre dispositivos móviles
combinación de contenidos para desarro- también generó muchas expectativas. Según Microsoft, más de 380.000 desarro-
lladores, convirtiéndose así en la princi- Según ha anunciado Microsoft, la versión lladores profesionales de todo el mundo
pal conferencia de formación técnica en Beta 1 queda accesible para su descarga están trabajando sobre la plataforma de
la que pueden coincidir una amplia gama en http://msdn.microsoft.com/vs2005/. software Windows Mobile, y más de 12.000
de profesionales en tecnología. La versión Beta 1 incluye Visual Studio aplicaciones ya están disponibles en el
El Tech-Ed es el evento elegido por Tema Architect Edition, un componente mercado para dispositivos basados en
Microsoft para mostrar sus nuevas líneas del Visual Studio Team System. Windows Mobile. Estos datos han servido a
de productos, alianzas y nuevas oportu- Servidores Microsoft para mostrar el buen momento
nidades. En este sentido, vamos a inten- El acuerdo alcanzado entre TeliaSonera que atraviesa el sector y la programación
tar resumir en las próximas líneas las (operadora móvil de los países nórdicos) y sobre dispositivos móviles, i en concreto su
novedades presentadas por Microsoft. Microsoft tiene como objetivo ofrecer a plataforma Windows Mobile.
Nuevas líneas de producto las empresas un servicio de localización, Y además…
Microsoft ha lanzado una nueva línea de en tiempo real, de sus activos móviles y A las cuestiones destacadas anteriormente,
producto, llamada Microsoft Express, su fuerza de trabajo móvil. La pieza cen- hay que añadir otras iniciativas que tam-
orientada a los desarrolladores no pro- tral de este engranaje será Microsoft bién centraron gran parte de la atención en
fesionales. Esta iniciativa pretende ofre- MapPoint Location Server, que va a per- esta edición del Tech-Ed Europe.
cer productos de fácil aprendizaje para mitir a los desarrolladores, ISVs e inte- Destaca un aumento de la adopción de
aficionados y estudiantes. En esta nueva gradores de sistemas la creación y des- Microsoft Internet Security y Acceleration
línea también se incluye Visual Studio pliegue de aplicaciones corporativas Server 2004 por parte de los OEM para
Express y SQL Server Express Edition. El móviles orientadas a la localización en productos especializados en seguridad de
objetivo de esta nueva iniciativa es per- tiempo real. redes o MSDN Product Feedback Center,
que permite crear un foro para que los
desarrolladores puedan enviar preguntas
a Microsoft durante la fase de desarrollo
de un producto, así como las ponencias
sobre Microsoft Office Systems.
ASP NET

Curso
ur o de ASP.NET
SP.NET
Colecciona
ole ci las
as 10
0 entregas
ega a partir
part r del próximo
p i o número
n ero
FRANCISCO CHARTE OJEDA objetos más importantes de la aplicación,
como Request, Response o Application. Uso
A medida que la conexión a Internet ha ido de servicios de la plataforma, como los de
popularizándose en todos los ámbitos, y al tiem- GDI+, para enriquecer las interfaces.
po que sus tecnologías fundamentales han pasa- 4 . Proceso de formularios: La mayoría de las
do a aplicarse también en el interior de empre- aplicaciones ASP.NET recogerán datos de
sas de todo tamaño y tipo, la conocida como formularios para su tratamiento. En esta
WWW se ha convertido en una importante pla- entrega se introducirán los conceptos más
taforma de ejecución de aplicaciones y permite importantes sobre formularios, así como el
avistar un futuro en el que usar un cliente web uso de controles de validación, manteni-
para acceder a un determinado programa será miento de estado entre solicitudes y con-
tan habitual como lo era hasta ahora la ejecu- ceptos similares.
ción local en Windows. 5 . Acceso a datos: El uso de bases de datos
Dejando atrás técnicas como los CGI y los filtros desde aplicaciones ASP.NET tiene unas
de servidor, las páginas de servidor: ASP, JSP y peculiaridades que se conocerán en esta
PHP, se han convertido en la primera opción a la entrega, junto con componentes específi-
ahora de diseñar aplicaciones web. ASP.NET es la cos para esta tarea y un avance de los con-
evolución de ASP y también la propuesta más troles de datos que aparecerán con ASP.NET
reciente en este campo, por lo que no es de 2.0 y que harán mucho más fácil el diseño
extrañar que cuente con múltiples ventajas res- de este tipo de proyectos.
pecto a las demás. 6 . Temas de seguridad: Esta sexta entrega se
A partir del próximo mes de septiembre, y duran- centrará en los temas relativos a seguridad,
te diez meses, Sólo Programadores publicará un como la autenticación de los usuarios, por
curso sobre ASP.NET con un formato similar a los ejemplo, en el acceso a bases de datos, etc.
publicados previamente sobre los lenguajes 7 . Servicios Web: ASP.NET esta pensado no úni-
Visual Basic .NET y C#. El contenido de este camente para el diseño de aplicaciones web,
curso, a grandes rasgos, será el siguiente: sino también para la creación de servicios
1 . Introducción: ASP.NET se ejecuta sobre la web. En esta entrega se describiría todo el
plataforma .NET, por lo que tiene acceso a proceso y los servicios de la plataforma que
todos los servicios de la FCL y puede utilizar- tendrían que utilizarse para ello.
se prácticamente cualquier lenguaje .NET. En 8 . Desarrollo de controles web: Además de
esta primera entrega se introducirán concep- los controles web incorporados en ASP.NET,
tos básicos, destacando la separación entre nosotros podemos desarrollar todos los que
interfaz y lógica, la estructura general de una pudiéramos necesitar simplemente cono-
aplicación ASP.NET, su funcionamiento en un ciendo unas reglas básicas. En esta entrega
servidor web externo (IIS o Cassini) o interno se describirán esas reglas y aportarán ejem-
(el integrado por WebMatrix o VS2005) y las plos prácticos.
herramientas que podemos usar, incluyendo 9 . Páginas maestras: Una de las novedades
el nuevo Visual Web Developer Express. más interesantes de ASP.NET 2.0 será la
2 . Herramientas disponibles: Descripción de las incorporación de las páginas maestras,
características más importantes, en lo relati- tanto al nivel de la infraestructura de eje-
vo a ASP.NET, de Visual Studio .NET 2003, cución como al nivel de diseño, en el entor-
WebMatrix y los futuros productos Visual no de VS2005. Esta penúltima entrega des-
Studio 2005 y Visual Web Developer Express. cribiría el funcionamiento y uso de páginas
De esta forma el lector podrá elegir la que maestras para abreviar el ciclo de desarro-
crea más adecuada a sus necesidades, sabien- llo de una aplicación web.
do que Sólo Programadores entregará gratui- 10. Skinning y otras características de
tamente WebMatrix, Visual Web Developer ASP.NET 2.0: En esta última entrega se
Express y otros recursos actuales. abordarán otras características del nuevo
3 . Diseño de interfaces: Cómo usar controles ASP.NET 2.0, entre ellas la posibilidad de
HTML y controles WebForm para diseñar modificar de manera global la apariencia
interfaces de usuario, generando código en el visual de las interfaces (skinning) y algunos
cliente y en el servidor. Descripción de los de los nuevos controles.

SOLO PROGRAMADORES 14
MIDDLEWARE

Migración de aplicaciones:
de VB 6.0 a .NET (y III)
MARINO POSADAS (M.V.P. Visual Developer - VISUAL C#) Esta posibilidad resulta muy útil si hay que
migrar en varias fases un sitio de gran tamaño y
En esta última entrega de nuestro en constante cambio a ASP.NET. Además, si se
propone la migración a ASP.NET como un objeti-
curso sobre migración de vo a largo plazo, se deberán mejorar al máximo
aplicaciones, estudiaremos el caso el diseño y la arquitectura. En situaciones como
concreto de la migración de ésta, de migraciones paulatinas, la coexistencia
se convierte en una necesidad.
aplicaciones web ASP. Nos
marcaremos como objetivo migrar El grado de compatibilidad
nuestra aplicación web a ASP.NET, Aunque el grado de compatibilidad es alto, no
destacando aquellos aspectos más obstante, existen problemas a la hora de migrar
aplicaciones reales, no tanto por el conjunto de
delicados del proceso. componentes equivalente sino por la diferente
arquitectura en la que estos se integran.
Fundamentalmente, podemos dividir los cambios
La migración de aplicaciones web realizados en los siguientes bloques:
z Cambios de estructura y la gestión del estado
La migración de aplicaciones web tiene carac- de las aplicaciones.
terísticas especiales vinculadas a la platafor- z Cambios en las APIs principales.
ma y al servidor de páginas (en este caso, IIS). z Cambios en la configuración de las aplicacio-
El esquema utilizado en .NET es el de la sepa- nes.
ración total entre páginas de presentación y z Cambios relacionados con la seguridad.
código funcional (si bien pueden utilizarse z Cambios en el lenguaje Visual Basic.
estructuras de código mixtas, al estilo anti- z Cambios relacionados con COM.
guo, por compatibilidad). Ya nos hemos referido en artículos anteriores a
Esto significa que los elementos que componen los cambios en el lenguaje Visual Basic y a los
la parte visual de la página no se entremezclan componentes COM. Vamos a comentar, somera-
con el código fuente que aporta el mecanismo mente, el resto.
funcional de nuestro código produciendo pági-
nas mucho más claras de mantener y especial- Cambios de estructura y la gestión del
mente, de depurar. Además, en ASP.NET se intro- estado de las aplicaciones
duce el concepto de controles de servidor, que no
son sino componentes más complejos que el Los cambios estructurales son aquellos que afec-
simple HTML, que el desarrollador puede incluir tan al diseño y al estilo del código de las páginas
en las páginas, y que se resuelven en elementos Active Server. Es necesario tener en cuenta
HTML cuando la página es servida al cliente. varios de estos cambios para garantizar que su
Respecto a ASP en convivencia con ASP.NET, código funcionará en ASP.NET.
ASP.NET separa aclararemos al lector que las aplicaciones de Bloques de código: declaración de funciones
ambos sistemas pueden ejecutarse a la vez en un y variables
la presentación mismo servidor sin que se vean afectadas nega- En ASP se pueden declarar subrutinas y variables
tivamente entre sí. Esto se debe principalmente globales entre los delimitadores del código:
de la lógica a que las dos tecnologías utilizan diferentes <%
extensiones de archivos (.asp frente a .aspx) y
de negocio modelos de configuración (metabase/registro Dim X
frente a archivos de configuración basados en Dim str
XML). Ambos sistemas tienen motores de proce-
samiento totalmente independientes. Esto impli- Sub MySub()
ca que una aplicación puede ejecutar ASP mien- Response.Write "Esto es una cadena."
tras otra parte trabaja con ASP.NET.

SOLO PROGRAMADORES 16
MIDDLEWARE
Migración de aplicaciones: de VB 6.0 a .NET (y III)

End Sub
Las funciones de procesamiento ya no Administración de estado
%> son válidas Si la aplicación emplea los objetos intrínse-
En ASP los desarrolladores llegaron a la cos Session o Application para almacenar la
En ASP.NET, esta opción ya no está permiti- conclusión de que podían obtener mejores información de estado, podrá seguir usán-
da. En su lugar, se deben declarar todas las resultados utilizando las denominadas dolos en ASP.NET sin ningún problema.
funciones y variables dentro de un bloque "funciones de procesamiento" (Render Además contará con varias opciones adi-
<script>: Functions). Una función de procesamiento cionales para la ubicación donde almacene
<script language = "vb" runat = "server"> es, básicamente, una subrutina que contie- el estado.
ne bloques de HTML insertados en el cuer- Opciones de administración de estado
Dim str As String po. Por ejemplo: En ASP.NET, existen opciones adicionales
Dim x, y As Integer <%Sub RenderMe() para el modelo de almacenamiento de esta-
do que permitirán por fin ir más allá de un
Function Add(I As Integer, J As %> sólo servidor web y admitirán la adminis-
Integer) As Integer <h4>Texto a procesar</h4> tración de estado en toda una red.
Return (I + J) Estas opciones se pueden configurar en la
<%End Sub sección <sessionState> de su archivo
End Function
RenderMe web.config del siguiente modo:
</script> <sessionState
%>
Mezcla de lenguajes de programación mode="Inproc"
En ASP se puede elegir principalmente A pesar de que se pueden obtener resulta- stateConnectionString="tcpip=
entre dos lenguajes de programación: dos interesantes con este tipo de funciones,
127.0.0.1:42424"
VBScript o Microsoft JScript. Además, exis- esta forma de escribir código ya no está
te total libertad para mezclar y combinar permitida en ASP.NET. Probablemente se sqlConnectionString="data source=
bloques de secuencias de comandos en una mejore con el cambio. Estoy seguro de que 127.0.0.1;user id=sa;password="
misma página. alguna vez se ha encontrado con funciones
En ASP.NET, podemos elegir entre tres que rápidamente se vuelven ilegibles o son cookieless="false"
lenguajes de programación: C#, Visual imposibles de administrar tan pronto se timeout="20"
Basic .NET, o JScript. VBScript no existe empiezan a mezclar y combinar código y
en la plataforma .NET porque está total- HTML de esta manera. La forma más senci- />
mente incluido en Visual Basic .NET. Si lla de que esto funcione en ASP.NET consis-
bien es cierto que se puede utilizar cual- te en reemplazar los resultados HTML por El atributo de modo especifica la ubicación
quiera de estos lenguajes, es importante llamadas a Response.Write, como se mues- donde desea guardar la información de
recordar que, a diferencia de lo que suce- tra a continuación: estado. Las opciones disponibles son Inproc,
de en ASP, no se pueden mezclar en la <script language="vb" runat="server"> StateServer, SqlServer y Off.
misma página. Es perfectamente factible
que la Página1.aspx de su aplicación con- Sub RenderMe() Cambios en las APIs principales
tenga código de C# mientras la Response.Write("<h4>Texto a pro
Página2.aspx de la misma aplicación con- Las APIs principales de ASP están compues-
cesar</h4>")
tenga código de Visual Basic .NET. La tas de algunos objetos intrínsecos (Request,
única limitación es que no pueden mez- End Sub Response, Server, etc.) y sus métodos aso-
clarse en la misma página. </script> ciados. Salvo algunos cambios sencillos,
Nuevas directivas de página estas API siguen funcionando correctamen-
En ASP todas las directivas deben colocarse <% te en ASP.NET. Todos los cambios están
en la primera línea de una página y dentro Call RenderMe() relacionados con el objeto Request y se
del mismo bloque delimitador. Por ejemplo: muestran en el cuadro "Cambios en la API".
<%LANGUAGE="VBSCRIPT" CODEPAGE="932"%>
%> Como se puede observar, los cambios son

En ASP.NET, la directiva Language ha de


colocarse junto a una directiva Page, como Cambios en la API
se muestra a continuación:
<%@Page Language="VB" CodePage="932"%> Método Cambio

<%@OutputCache Duration="60" VaryByPar Request(item) En ASP, este método devuelve una serie de cadenas. En ASP.NET, devuelve un
am="none" %> objeto NameValueCollection.

Las directivas se pueden situar en cual- Request.QueryString(item) En ASP, este método devuelve una serie de cadenas. En ASP.NET, devuelve un
quier lugar del archivo .aspx, aunque por objeto NameValueCollection.
lo general suelen colocarse al principio
del archivo. Además, en ASP.NET se han Request.Form(item) En ASP, este método devuelve una serie de cadenas. En ASP.NET, devuelve un
incluido varias directivas nuevas. objeto NameValueCollection.

17 SOLO PROGRAMADORES
MIDDLEWARE

Secciones de configuración basado en archivos XML sencillos. Cada


aplicación ASP.NET posee su propio archivo
Configuración Descripción Web.Config que se encuentra en el directo-
rio de su aplicación principal. Desde aquí se
<appSettings> Configura los valores de la aplicación personalizados. controla la configuración personalizada, el
comportamiento y la seguridad de las apli-
<authentication> Configura la compatibilidad con la autenticación ASP.NET. caciones web.
Ahora existen dos modelos con una confi-
<pages> Identifica valores de configuración específicos de páginas. guración totalmente independiente. Salvo
algunos valores de seguridad, la mayoría de
<processModel> Configura los valores del modelo de proceso ASP.NET en sistemas IIS. valores creados mediante la herramienta de
administración IIS son omitidos por las
<sessionState> Especifica las opciones del estado de la sesión. aplicaciones ASP.NET. Debe colocar los
valores de configuración en el archivo
Web.Config.
Opciones de autenticación en ASP.NET Dado que la configuración de las aplicacio-
nes en .NET es un tema tan extenso, en este
Tipo Descripción artículo no vamos a entrar en detalles. El
cuadro "Secciones de configuración" mues-
Windows ASP.NET utiliza la autenticación de Windows. tra algunas de las secciones de configura-
ción más interesantes que pueden estable-
Forms Formularios personalizados basados en cookies con inicio de sesión. cerse en el archivo. Tenga en cuenta que
existen muchas más.
Passport Servicio externo Passport proporcionado por Microsoft.
Cambios relacionados con la seguridad
None No se lleva a cabo la autenticación.
La seguridad en ASP.NET se controla prin-
cipalmente desde la configuración en las
idénticos para todos los métodos utilizados. ción se ha de utilizar un índice de base cero, secciones de seguridad del archivo
Si se tiene acceso a un ítem que contiene no de base uno: Web.config. ASP.NET e IIS colaboran con la
solamente un valor para la clave especifica- <% finalidad de proporcionar un modelo de
da, no es necesario modificar el código. No seguridad completo para sus aplicaciones.
obstante, si existen varios valores para una 'Esto dará como resultado "10" La configuración de seguridad de IIS es
misma clave, habrá que utilizar otro méto- Response.Write (Request.QueryStri una de las pocas que realmente se pueden
do para devolver la colección de valores. trasladar y aplicar a la aplicación ASP.NET
ng.GetValues("Datos")(0))
Asimismo, nótese que, en Visual Basic .NET, de una manera parecida a como se hace
las colecciones son de base cero, mientras 'Esto dará como resultado "20" en ASP. Natural-mente, presenta otras
que en VBScript son de base uno. muchas mejoras.
Por ejemplo, en ASP se tendría acceso a los Response.Write (Request.QueryStri
Autenticación
valores de cadenas de consulta individuales ng.GetValues("Datos")(1)) En lo que respecta a la autenticación,
desde una solicitud a http://localhost/my %> ASP.NET admite las diferentes opciones que
web/valuetest.asp? Datos=10& Datos=20 aparecen en el cuadro "Opciones de auten-
de la siguiente forma: Tanto en el caso de ASP como en el de ticación en ASP.NET".
<% ASP.NET, el siguiente código actuará de A excepción de la nueva opción Passport, el
igual forma: resto son idénticas a las que hay en ASP. A
'Esto dará como resultado "10"
<% modo de ejemplo, la siguiente sección de
Response.Write Request.QuerySt configuración permite la autenticación
'Esto dará como resultado "10", "20" basada en Windows para una aplicación:
ring("Datos")(1)
Response.Write (Request.QueryStr <configuration>
'Esto dará como resultado "20"
ing("Datos")) <system.web>
Response.Write Request.QuerySt %>
<authentication mode="Windows"/>
ring("Datos")(2)
%> Cambios en la configuración de las </system.web>
aplicaciones </configuration>
En ASP.NET, la propiedad QueryString
devuelve un objeto NameValueCollection. Mientras en ASP toda la información sobre Autorización
Es necesario recuperar la colección Datos la configuración de aplicaciones web se Una vez que los usuarios se hayan autenti-
de este objeto antes de recuperar el ele- almacena en el registro del sistema y la cado, puede centrarse en asignarles permi-
mento real que desea. Recuerde que para metabase de IIS, en ASP.NET se presenta un sos de acceso a los recursos que desee. En
recuperar el primer elemento de la colec- modelo de configuración totalmente nuevo el siguiente ejemplo, "Juancho" y "Claudio"

SOLO PROGRAMADORES 18
MIDDLEWARE
Migración de aplicaciones: de VB 6.0 a .NET (y III)

Se espera el lanzamiento de la nueva versión de Visual Stuido para el 2005.

reciben permiso para tener acceso, mien- ASP. Si cuenta con esta función, necesitará VB.NET, por el contrario, estamos ante un
tras que al resto se le deniega: habilitarla en el archivo Web.config de la lenguaje totalmente orientado a objetos
<authorization> siguiente manera: con una implementación elegante de la
<identity> OOP que incluye todas sus características
<allow users="España\Juancho, fundamentales, a excepción de la sobrecar-
USA\Claudio"/> <impersonation enable = "true"/> ga de operadores (si bien esta característi-
<deny users="*"/> </identity> ca, aparecerá en la próxima versión, Visual
Studio .NET 2005, al igual que la muy apre-
</authorization>
Consideraciones relativas al lenguaje ciada cualidad de modificar código en
Representación (Impersonation) Visual Basic depuración, y volver a ejecutar "hacia
A modo de recordatorio, la representación atrás", sin necesidad de recompilación).
es el proceso por el cual un objeto ejecuta En lo tocante al lenguaje, los cambios han Orientación a objetos
código con la identidad de la entidad en sido significativos, pero especialmente, hay La implementación de la OOP es realmen-
cuyo nombre actúa. En ASP, la representa- que llamar la atención sobre la propia filo- te exquisita. Todo son objetos, sin excep-
ción permite ejecutar código en nombre de sofía. Ahora, al igual que sucede con el ción (no existen tipos primitivos misterio-
un usuario autenticado. Por otra parte, los resto de lenguajes .NET, VB.NET es total- sos, como en Java, por ejemplo), y la
usuarios pueden trabajar de forma anónima mente orientado a objetos. Eso significa herencia puede realizarse a partir de cual-
utilizando una identidad especial. ASP.NET una modificación radical de los esquemas, quier clase heredable (marcada como
no utiliza representación por solicitud de ya que VB en versiones anteriores sólo Inheritable), de la inmensa jerarquía de
manera predeterminada, a diferencia de soportaba la OOP de forma parcial. En clases de .NET, o de nuestras propias jerar-
Asistente
de migración
de código.

19 SOLO PROGRAMADORES
MIDDLEWARE

valente al antiguo Integer, que ahora es siempre nos gusta incluir en los procesos de
equivalente al tipo Long de VB6). instalación en cliente: Creación de grupos y
También es posible la declaración de varia- carpetas en el Menú de Inicio, ubicación de
bles "in-line" dentro de los bucles: iconos de acceso directo en el escritorio,
For Each X as string In Colección_de_ control de todo el proceso de instalación,
pudiendo personalizar el aspecto de cada
Strings
una de las pantallas de solicitud de infor-
'proceso de strings mación inicial, ubicación de archivos de la
Next aplicación, y lo que es mejor, la posibilidad
quías. De igual forma, disponemos de poli- de intercalar entre cualquiera de las fases
morfismo real, haciendo innecesarios los y las declaraciones multivariable para un del proceso llamadas a nuestros propios
conocidos parámetros opcionales (natu- mismo tipo, con asignación de valor inicial: programas, para garantizar que cualquier
ralmente, el polimorfismo, se extiende Dim x,y,z as Integer = 0 otro procedimiento necesario en el cliente
hasta los métodos constructores). a la hora de lanzar la aplicación se encuen-
La encapsulación, (que era una de las También es notable el cambio respecto al tre adecuadamente instalado.
características soportadas anteriormen- tratamiento de las excepciones, que (por Distribución de aplicaciones Windows
te) se ha mejorado notablemente con la fin) pasa a ser estructurado mediante vía Internet
separación conceptual que permiten las una sentencia Try-Catch-Finally, en Además de esa posibilidad, podemos distri-
Properties, pero mejoradas en su sintaxis detrimento de la antigua On-Error. buir aplicaciones Windows a través de
y capacidades. También se han añadido Naturalmente, en lo que respecta al len- Internet. Hay que tener en cuenta que los
asistentes que permiten la migración del guaje existen más cambios, y recomen- EXEs son autocontenidos y se ejecutan
código de VB6 a VB.NET de forma direc- damos al lector cualquiera de la literatu- siempre bajo la supervisión del CLR
ta, insertando el código convertido en la ra al respecto que se encuentra publica- (Common Language Runtime). De modo
posición del cursor, tal y como podemos da en papel o en la red, donde encontra- que si los permisos establecidos en la
ver en la figura. rá listados exhaustivos de dichas diferen- máquina cliente son los adecuados, es posi-
Es más, debido a que el lenguaje VB no cias. Destacamos, por ser la fuente origi- ble descargar y ejecutar programas de una
diferencia entre mayúsculas y minúsculas, nal, el sitio web http://msdn.micro URL utilizando una sintaxis del tipo:
el "Intellisense" del editor de código fuente soft.com/vb con abundante información http://MiSitioWeb/MiEjecutable.EXE
es capaz de recordarnos errores en la al respecto (incluyendo jugosos aparta-
estructura del código, como por ejemplo, el dos de código fuente y ejemplos, muy Lo que proporciona además, nuevas posibi-
intento de sobrescribir un método que no recomendables antes de abordar un pro- lidades de actualización de aplicaciones de
haya sido marcado como overridable en la ceso de migración real). forma remota.
clase antecesora, u otras características de Incluso podemos hacer referencia a esos
formación polimórfica. El modelo de distribución de ejecutables mediante código fuente produ-
Otra característica notable, es la capacidad aplicaciones en .NET ciendo su descarga a voluntad, mediante
de generar código de forma "intencional". un código similar al siguiente:
Imaginemos que el usuario declara que una Para concluir esta revisión de las caracte- Dim a as [Assembly] = Assembly.LoadFr
clase implementa una interfaz determina- rísticas de la migración a VB.NET, no pode-
om("file://C:/usr/bin/xyzzy.dll");
da, por ejemplo. Como respuesta a ello, el mos pasar por alto una de las mejores y
generador de código del IDE de Visual más apreciadas cualidades de esta plata- return a.CreateInstance("Programa.Ve
Studio produce toda la estructura necesa- forma: la capacidad de distribuir aplicacio- ntana1");
ria de código sólo a falta de la compleción nes sin necesidad de tocar el registro, y
por parte del usuario. pudiendo, incluso, hacer la distribución Y, siguiendo esta misma lógica, el código
De esta manera, estaremos trabajando con web de aplicaciones Windows. anterior podría ser parte de un código de
un "asistente inteligente" permanentemen- Las aplicaciones .NET generan EXEs o DLLs script en una página web, sustituyendo en
te activado, lo cual facilitará muchísimo la denominadas ensamblados (assemblies), el método LoadFrom() el acceso file:// por
edición de código. que se encuentran autodescritas en su su correspondiente protocolo de Internet
Por lo demás, otros asistentes convertirán cabecera (llamada Manifest), con lo que se (http://).
código de la versión Visual Basic .NET 2002 hace innecesario el uso del Registro de
a la 2003 (o a la venidera 2005), de forma Windows en el proceso de instalación, de Conclusiones
automática, sin necesidad de ningún tipo forma que .NET Framework libera a los pro-
de conversión. gramadores de Visual Basic de las ataduras Muchas son las novedades aportadas por la
Tipos soportados y no soportados que suponían los problemas de versiones de plataforma .NET al desarrollador y conse-
Otros cambios notables tienen que ver con los componentes, más conocido como cuentemente, muchas las posibilidades que
las variables y algunas de las estructuras "Infierno de las DLL" (DLL Hell). se ofrecen a la hora de abordar un proceso
clásicas del mismo. Por ejemplo, debido a Por si esto fuera poco, un nuevo tipo de complejo como es una migración completa
que todos los lenguajes en .NET siguen un proyecto, denominado Proyecto de de un programa. No obstante, nunca antes
patrón común de tipos, los tipos Variant y Instalación y Distribución, se encuentra había resultado tan poderoso el cambio, ni
Currency desaparecen, pasando a ser, res- disponible desde Visual Studio .NET, con lo tan sencillo el proceso. Y podemos aventu-
pectivamente, Object y Decimal. Además que nos facilita enormemente la creación rar, que, una vez concluido el trabajo, el
aparecen tipos nuevos, como Short (equi- de los otros elementos necesarios que resultado merecerá la pena.

SOLO PROGRAMADORES 20
MIDDLEWARE

Tratamiento de XML desde


Java (y III): un caso práctico
FRANCISCO JOSÉ GARCÍA PEÑALVO (profesor titular del El siguiente paso a realizar es la construcción
departamento de Informática y Automática de la Universidad de un esquema XML (véase la referencia 2)
de Salamanca)
JORGE CARABIAS GONZÁLEZ donde se defina la estructura de los datos que
se van a manejar.
Esta última entrega nos servirá para El esquema XML
programar, a modo de ejemplo, una
Tras definir los datos que se van a utilizar en la
aplicación para gestionar nuestros aplicación se debe definir el esquema XML que
contactos, usando la tecnología XML establezca las etiquetas que se podrán utilizar y la
estructura que deberán obedecer estas etiquetas.
para conseguir la persistencia de la En el listado 2 se muestra el esquema que se uti-
información de nuestra aplicación. lizará para los datos de la aplicación de ejemplo.
En este sencillo esquema XML se puede observar
cómo se define un elemento raíz agenda del tipo
Introducción AgendaType. Este tipo se define como una
secuencia de elementos contacto. Esta secuencia
En los dos artículos anteriores de esta serie se han se indica que podrá ser de cero o varios elemen-
introducido diferentes maneras de uso de XML a tos mediante los atributos minOccurs="0" y
través del lenguaje de programación Java, haciendo maxOccurs="unbounded".
especial hincapié en la API JAXB (Java API for XML Los elementos contacto son del tipo Contac-
Binding, véase la referencia 1). Se aborda ahora en toType, que se define más abajo como una
este tercer y último artículo la realización de una secuencia de elementos. Estos elementos son:
aplicación de ejemplo que muestre, de forma prác- z nombre: almacena el nombre del contacto,
tica, la facilidad que esta API proporciona en el tra- por ello es de tipo string.
tamiento de datos XML (véase la referencia 3). z primer_apellido: almacena el primer apellido
La aplicación a construir consiste en una agenda del contacto. Es de tipo string.
muy simple, la cual ofrece la posibilidad de z segundo_apellido: almacena el segundo apelli-
administrar contactos. Los archivos de contactos do del contacto. También va a ser de tipo string.
se van a guardar en XML, y a lo largo de este z telefono: almacena el número de teléfono del
artículo se explicarán detalladamente los pasos contacto. En este caso se define como un
para la construcción de esta agenda. entero positivo, positiveInteger.
z email: almacena la dirección de correo elec-
Estructura del archivo de contactos trónico del contacto. Se define de tipo string.
z direccion: almacena la dirección postal del
El primer paso a realizar en la construcción de contacto. Se define de tipo string.
esta agenda, que nos va a servir como aplicación z notas: almacena anotaciones varias sobre el
ejemplo, es definir los datos que se van a alma- contacto. Se define de tipo string.
cenar, esto es, diseñar la estructura que van a
La combinación tener los contactos en nuestra agenda. Compilación del esquema
La información básica a tratar es información
de Java y XML sobre el nombre, apellidos, dirección, etc. de nues- Hasta ahora los pasos que se han visto son los
tros contactos. En el listado 1 se muestra un ejem- normales para cualquier aplicación que trate con
maximiza plo de un fichero de datos con los contactos de datos XML. De ahora en adelante el desarrollo
nuestra agenda expresados en XML. vendrá marcado por el uso de la API JAXB (véase
la portabilidad Como se puede observar en el ejemplo, el fichero la referencia 1), así como por los pasos que hay
XML está formado por una etiqueta raíz <agenda> que realizar para hacer uso de esta API desde
de código y datos y cero o más etiquetas <contacto> que albergan los una aplicación Java.
datos de cada contacto como nombre, apellidos, Para utilizar la API JAXB se deberá tener ins-
teléfono, correo electrónico, dirección y unas notas talado el paquete JWSDP (Java Web Services
sobre el contacto. Developer Pack). Si no se dispone de este

SOLO PROGRAMADORES 22
MIDDLEWARE
Tratamiento de XML desde Java (y III): un caso práctico

paquete se puede descargar de http://ja LISTADO 1 Fichero de contactos en formato XML


va.sun.com/xml/jaxb.
Una vez instalado este paquete ya se dis- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<agenda>
pone, dentro de la ubicación de la instala- <contacto>
ción, de un directorio jaxb dentro del que se <nombre>Jorge</nombre>
encuentra otro denominado bin (binarios) <primer_apellido>Carabias</primer_apellido>
<segundo_apellido>Gonzalez</segundo_apellido>
que alberga el compilador de esquemas xjc. <telefono>923232323</telefono>
Como ya se explicó en el artículo anterior, <email>jorgecarabias@telefonica.net</email>
se debe compilar el esquema XML realiza- <direccion/>
do para obtener los archivos .java de las <notas/>
</contacto>
clases que nos servirán para manejar los <contacto>
datos XML mediante JAXB. <nombre>Francisco</nombre>
Si el esquema XML que se mostró en el lis- <primer_apellido>García</primer_apellido>
<segundo_apellido>Peñalvo</segundo_apellido>
tado 2 se almacena en un archivo que lleve <telefono>923101010</telefono>
por nombre agenda.xsd, lo único que se debe <email>fgarcia@usal.es</email>
realizar es compilarlo mediante la orden: <direccion/>
<notas/>
xjc agenda.xsd </contacto>
<contacto>
Por defecto la salida se almacena en el <nombre>Maribel</nombre>
directorio generated (si se desea que la <primer_apellido>Martín</primer_apellido>
<segundo_apellido/>
salida se almacene en un directorio especí- <telefono>923121212</telefono>
fico se debe indicar mediante la opción -d, <email/>
seguida del nombre del directorio. El direc- <direccion/>
<notas/>
torio debe existir antes de compilar el </contacto>
esquema). En el caso de la compilación del </agenda>
archivo agenda.xsd se obtiene el mencio-
nado directorio generated que contiene los
siguientes archivos: LISTADO 2 XML Schema correspondiente al listado 1
z Agenda.java: El archivo para el elemen-
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
to agenda. <xs:element name="agenda" type="AgendaType"/>
z AgendaType.java: El archivo para el tipo <xs:complexType name="AgendaType">
complejo AgendaType. <xs:sequence>
<xs:element name="contacto" type="ContactoType" minOccurs="0"
z ContactoType.java: El archivo para el maxOccurs="unbounded"/>
tipo complejo ContactoType. </xs:sequence>
z ObjectFactory.java: Contiene métodos </xs:complexType>
para la creación de los elementos. <xs:complexType name="ContactoType">
z bgm.ser: Es un archivo que se utiliza <xs:sequence>
para la validación en tiempo de ejecu- <xs:element name="nombre">
ción ya que contiene información del <xs:simpleType>
<xs:restriction base="xs:string">
esquema. <xs:minLength value="1"/>
z jaxb.properties: Archivo de propiedades. </xs:restriction>
Dentro de este directorio se encuentra otro, </xs:simpleType>
</xs:element>
denominado impl, que contiene los <xs:element name="primer_apellido" type="xs:string"/>
siguientes archivos: <xs:element name="segundo_apellido" type="xs:string"/>
z AgendaImpl.java: Implementación de la <xs:element name="telefono" type="xs:positiveInteger" default="1"/>
interfaz del elemento agenda. <xs:element name="email" type="xs:string"/>
<xs:element name="direccion" type="xs:string"/>
z AgendaTypeImpl.java: Implementación <xs:element name="notas" type="xs:string"/>
de la interfaz del tipo complejo </xs:sequence>
AgendaType. </xs:complexType>
</xs:schema>
z ContactoTypeImpl.java: Implementación
de la interfaz del tipo complejo
ContactoType. Creación de la interfaz de la aplicación cionalidades para la visualización de los
z JAXBVersion.java: Provee la versión de JAXB. datos de los contactos almacenados, adi-
A su vez, en el directorio impl se encuentra Tras la creación de las clases que servirán para ción, modificación y eliminación de con-
otro, llamado runtime, que contiene las clases el manejo de los datos XML, se debe proceder tactos, así como con la capacidad de cargar
como MarshallerImpl, UnmarshallerImpl, etc. a la construcción de la aplicación en sí. y guardar archivos de contactos, además de
Tras la creación de los archivos .java sólo La aplicación de agenda deberá ser capaz de permitir la creación de nuevos archivos.
queda compilarlos para poder usar las cla- manejar los datos de los archivos XML de con- En la figura 1 se presenta la pantalla principal
ses generadas desde cualquier aplicación. tactos, semejantes al presentado en el listado 1. de la aplicación. Se observa que aparece una
Este paso se puede realizar con el compila- A grandes rasgos, a modo de aplicación lista en la parte superior izquierda donde apa-
dor de siempre, esto es, con javac. sencilla, nuestra agenda contará con fun- recerán los contactos disponibles. En la parte

23 SOLO PROGRAMADORES
MIDDLEWARE

LISTADO 3 Esqueleto de la aplicación AgendaJAXB


[...]
/**Clases generadas al compilar el esquema*/
import generated.*;
import generated.impl.*;
import generated.impl.runtime.*;

public class AgendaJAXB extends javax.swing.JFrame {


// Variables para el uso de JAXB
private JAXBContext contexto;
//Instancia de la clase raíz del documento XML
private Agenda agenda;
// Variables de la interfaz gráfica
[...]

/** Crea una nueva ventana de AgendaJAXB*/


Figura 1. Aspecto general de la agenda.
public AgendaJAXB() {
this.setTitle("Agenda"); cación se importan, entre otras, las genera-
initComponents(); das tras la compilación del esquema definido
/**Crea el contexto de JAXB*/
try{ en el listado 2 mediante las sentencias:
contexto = JAXBContext.newInstance("generated"); import generated.*;
}catch(Exception excep){
System.out.println("Error al crear el contexto"); import generated.impl.*;
excep.printStackTrace();
} import generated.impl.runtime.*;
/*Establece el elemento raíz del árbol de contenidos a nulo*/
agenda = null; En la clase AgendaJAXB se definen dos atribu-
}
tos, contexto y agenda, de tipos JAXBContext y
/** Este método es llamado desde el constructor para inicializar la ven- Agenda respectivamente. El atributo contexto
tana*/ provee un punto de entrada al cliente a la API
private void initComponents() { [...] }
JAXB, mientras que el atributo agenda es el ele-
/** Sale de la aplicación */ mento raíz del árbol de contenidos JAXB que
private void exitForm(java.awt.event.WindowEvent evt) { representará los datos de un fichero XML de
System.exit(0); contactos. Estos atributos son inicializados en el
}
constructor de la clase a la que pertenecen. El
/**@param args Los parámetros a pasar a la aplicación*/ atributo contexto establece su valor mediante el
public static void main(String args[]) { método newInstance() de la clase JAXBContext,
AgendaJAXB agenda = new AgendaJAXB();
agenda.setBounds(50,50,490,390); al cual se le pasa como parámetro el nombre del
agenda.show(); paquete de las clases generadas al compilar el
} esquema, esto es generated en nuestro caso. Por
} su parte, agenda establece su valor a nulo pues-
/**Clase que contiene los métodos para manejar las selecciones en el menú*/ to que en el inicio de la aplicación no hay nin-
class ManejadorMenu implements ActionListener gún archivo de agenda cargado.
{ [...] Los métodos initComponents() y exitForm() ini-
/** Fichero de agenda que se está utilizando*/ cializan la ventana y la destruyen respectiva-
private static String fichero; mente. En el método main() se crea una nueva
private JList lista; instancia de la clase AgendaJAXB y se muestra.
private AgendaJAXB agendajaxb;
Se provee también una clase ManejadorMenu,
ManejadorMenu(AgendaJAXB agndjaxb, JList list) { [...] } la cual contiene los métodos para manejar las
selecciones de los elementos del menú. Esta
public void actionPerformed(ActionEvent e) { [...] } clase mantiene un atributo fichero con la ruta
}
[...] del fichero de agenda que se esté manejando en
el momento y una instancia de la clase
AgendaJAXB.

superior derecha aparecen tres botones, Añadir, z Cargar: Carga un archivo de agenda Opciones "nuevo", "cargar" y
Modificar y Borrar, que servirán para incluir, existente. "guardar"
modificar o eliminar contactos, respectivamen- z Guardar: Guarda los datos del archivo de
te. En la parte inferior se han proporcionado agenda con el que se esté tratando. Como se ha dicho en el apartado anterior se ha
algunos campos para mostrar los datos de los z Salir: Sale de la aplicación. creado una clase específica, ManejadorMenu,
contactos que se seleccionen en la lista. Se ha En el listado 3 se muestra un fragmento de para manejar las selecciones del menú. Las
provisto también a la aplicación de un menú código que representa el esqueleto de la apli- acciones que se pueden realizar desde el menú
Archivo con las opciones siguientes: cación AgendaJAXB. Se observa que la clase son las de crear un nuevo archivo de agenda,
z Nuevo: Crea un nuevo archivo de agen- principal, AgendaJAXB, hereda de la clase cargar uno creado o guardar los cambios del
da y permite operar con él. JFrame. Antes de definir las clases de la apli- actual, así como salir de la aplicación.

SOLO PROGRAMADORES 24
MIDDLEWARE
Tratamiento de XML desde Java (y III): un caso práctico

Lo primero que cualquier usuario realizará LISTADO 4 Opción "Nuevo"


al iniciar la aplicación de agenda será la
creación de un nuevo archivo, por lo que se [...]
try{
verá este caso en primer lugar. fichero = file.toString();
En el listado 4 se presenta una parte del códi- file.createNewFile();
go del manejador de la selección de Nuevo ObjectFactory of = new ObjectFactory();
Agenda agenda = of.createAgenda();
en el menú. Tras la selección de esta opción agendajaxb.setRoot(agenda);
se muestra un cuadro de diálogo, del tipo Marshaller marshaller = agendajaxb.getContexto().createMarshaller();
JFileChooser, para que el usuario seleccione marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
la ubicación del nuevo archivo y proporcione FileOutputStream stream = new FileOutputStream(fichero);
marshaller.marshal(agenda, stream);
un nombre para el mismo. Esta parte del List items = agenda.getContacto();
código se ha omitido del fragmento presen- ListIterator iterador = items.listIterator();
tado en el listado 4 por claridad, pero se [...]
}catch(Exception excep){
puede consultar en el código completo de la System.out.println("Error en la creación del archivo de contactos");
aplicación que se incluye en el CD-ROM. excep.printStackTrace();
La primera acción que se realiza, tras obtener }
[...]
el nombre y la ubicación para el nuevo archi-
vo, es copiar su valor en el atributo fichero que lo que se le ha provisto de un método Para iniciar el proceso de creación del árbol
se mencionó anteriormente. Téngase en cuen- getContexto() para poder proporcionarlo a de contenidos se invoca el método unmars-
ta que file es una instancia de la clase File con las demás clases que lo necesiten, tal y hal() de la clase Unmarshaller, pasando
la ruta al nuevo fichero. Tras crear el nuevo como se muestra a continuación: como parámetro una instancia de la clase
fichero mediante el método createNewFile() se public JAXBContext getContexto() File que indica la localización del fichero
instancia un objeto de la clase ObjectFactory, agenda a cargar. Este método devuelve una
clase de la API JAXB generada mediante la { return contexto; } instancia de la clase Object, pero se le hace
compilación del esquema agenda.xsd, para un casting a Agenda para que sea de la
poder crear nuevos elementos. Como en la cre- Como se aprecia en el fragmento de código clase raíz del árbol. La instancia de Agenda
ación de nuevo archivo el contenido del mismo anterior, el método getContexto() simple- obtenida se establece como elemento raíz
simplemente debe ser la etiqueta raíz, se crea mente devuelve la instancia de la clase al llamar al método setRoot() anteriormen-
un nuevo elemento Agenda mediante el méto- JAXBContext. te mencionado.
do createAgenda() de la clase ObjectFactory Una vez obtenido el objeto de la clase Una vez creado el árbol de contenidos se
que se acaba de instanciar. Ya se ha citado que Marshaller se establece la propiedad de que muestran los contactos en la lista.
la clase AgendaJAXB mantiene un atributo que formatee la salida mediante el método Mediante el método getRoot() de la clase
es la raíz del árbol de contenidos, por lo que se setProperty(), indicando que active la propie- AgendaJAXB se obtiene una referencia al
debe establecer este nuevo objeto agenda dad Marshaller.JAXB_FORMATTED_OUTPUT. elemento raíz.
como la raíz del árbol de contenidos a tratar. Después se crea un flujo de salida al fichero El elemento raíz tiene un método getContacto()
Para realizar esta acción se ha provisto a la nuevo y se invoca el método marshal() de la que devuelve una lista de contactos disponibles.
clase AgendaJAXB de un nuevo método clase Marshaller, pasándole como parámetros Para obtener los datos de todos los contactos
setRoot(), que se muestra a continuación: el elemento raíz del árbol, agenda, y el flujo simplemente se debe ir recorriendo esta lista.
public void setRoot(Agenda agnd) de salida, stream. Tras esto ya se encuentra Para ello se crea una instancia de la clase
creado el nuevo archivo de agenda y en su ListIterator mediante el método listIterator() de
{ agenda = agnd; } interior aparecerá el siguiente contenido: la lista. Se recorre con este iterador la lista y se
<?xml version="1.0" encoding="UTF-8" van recogiendo los datos de cada contacto. En
Como se aprecia en el fragmento de código cada pasada del bucle se crea una instancia de
standalone="yes"?>
anterior, este método simplemente asigna la clase ContactoTypeImpl que representa un
al atributo agenda el valor que se le pasa <agenda/> contacto en particular. De este contacto se
como parámetro. En el artículo anterior se recogen el nombre y los apellidos mediante sus
indicó que para trabajar con datos XML En el caso de la carga de un archivo de métodos getNombre(), getPrimerApellido() y
usando JAXB se debe realizar primero un agenda ya creado anteriormente, las accio- getSegundoApellido(). Con estos datos se forma
proceso denominado unmarshalling (o paso nes a realizar serán las de hacer el unmars- una cadena que formará una entrada de la lista.
de datos del fichero XML a árbol de conte- halling y recopilar los datos de los contac- Para la última opción, esto es, la de guardar los
nidos) y después otro llamado marshalling tos existentes para ser mostrados en la lista datos en el archivo de agenda, simplemente
(o paso de árbol de contenidos a datos XML de contactos disponibles. hay que realizar de nuevo un marshalling.
en el fichero). En el caso que se trata ahora, Como se aprecia en el listado 5, en primer lugar El proceso de marshalling, que se ilustra a
y tras la creación del árbol de contenidos se crea una instancia de la clase Unmarshaller continuación, comprueba en primer lugar si
más simple, ya que sólo tiene un elemento mediante el método createUnmarshaller() de la hay algún archivo de agenda cargado. El resto
agenda, se debe escribir en el nuevo fiche- clase JAXBContext. Para asegurar que se reali- del proceso es idéntico al visto en el caso de la
ro. Para ello se instancia un objeto de la za la validación de los datos almacenados creación de un nuevo archivo de agenda.
clase Marshaller, que se obtiene mediante mientras se crea el árbol de los contenidos se if(agendajaxb.getRoot() != null)
el método createMarshaller() de la clase invoca el método setValidating() de la clase
JAXBContext. La clase AgendaJAXB tam- Unmarshaller, pasándole como parámetro true {
bién mantiene el contexto que se usa, por para activar la validación con el esquema XML.

25 SOLO PROGRAMADORES
MIDDLEWARE

LISTADO 5 Opción "Cargar"


Unmarshaller unmarshaller = agendajaxb.getContexto().createUnmarshaller();
unmarshaller.setValidating(true);
agendajaxb.setRoot((Agenda)unmarshaller.unmarshal(file));
List items = agendajaxb.getRoot().getContacto();
ListIterator iterador = items.listIterator();
ArrayList datos = new ArrayList();
while(iterador.hasNext())
{
ContactoTypeImpl contacto = (ContactoTypeImpl)iterador.next();
datos.add(contacto.getNombre() + " " + contacto.getPrimerApellido() + " " +
contacto.getSegundoApellido());
}
lista.setListData(datos.toArray()); Figura 2. Selección de un contacto en la agenda.
la agenda con un fichero de contactos car-
gado y un contacto concreto seleccionado.
LISTADO 6 Mostrando la información de un contacto
Adición, modificación y eliminación de
contactos
// Código que se ejecutará al seleccionar un contacto de la lista de contactos
disponibles
jList1.addListSelectionListener(new ListSelectionListener()
{ Para terminar con la aplicación de agenda
public void valueChanged(ListSelectionEvent e) y, por tanto, con la muestra de la utilización
{
[...] de JAXB para el manejo de datos XML
String seleccionado = jList1.getSelectedValue().toString(); desde el lenguaje de programación Java,
[...] simplemente queda por añadir los maneja-
jTextField1.setText(nombre);
jTextField2.setText(apellido_1);
dores de los botones para la adición, modi-
jTextField3.setText(apellido_2); ficación y borrado de contactos.
List items = agenda.getContacto(); En el caso de la adición y la modificación se
ListIterator iterador = items.listIterator(); establece que se muestre una nueva pantalla
ArrayList datos = new ArrayList();
while(iterador.hasNext()) { para la recogida o modificación de los datos.
ContactoTypeImpl contacto = (ContactoTypeImpl)iterador.next(); La figura 3 presenta el formulario de inserción
String nombretemporal = contacto.getNombre(); o modificación de los datos de un contacto. Se
String ape1temporal = contacto.getPrimerApellido();
String ape2temporal = contacto.getSegundoApellido(); puede observar que aparecen campos de texto
if((nombre.compareTo(nombretemporal) == editables para la inserción de los datos.
0)&&(apellido_1.compareTo(ape1temporal) == 0) &&(apellido_2.compareTo(ape2tempo- Obviando los detalles de la creación de la
ral) == 0)) {
[...] }
interfaz gráfica, nos vamos a centrar en el
} manejador del botón Aceptar de esta pantalla
} que es donde radicará el uso de JAXB.
}); El listado 7 ilustra el fragmento de código corres-
Marshaller marshaller = agendajaxb de un manejador de selección, ListSelection pondiente con la inserción de un nuevo contacto.
.getContexto().createMarshaller();
Listener. Dentro del método valueChanged() Se puede observar que el primer paso a realizar es
de este manejador es donde se incluye el códi- la obtención de una instancia de ObjectFactory
marshaller.setProperty(Marshaller.JAX go que se ejecutará al seleccionar un contac- para la creación de nuevos elementos. Una vez
B_FORMATTED_OUTPUT, Boolean.TRUE); to. Lo primero que se debe realizar es recoger obtenida esta instancia, of, se crea un nuevo con-
el contacto que ha sido seleccionado. Tras tacto de tipo ContactoTypeImpl mediante el
FileOutputStream stream = new FileO
establecer los campos de nombre y los apelli- método createContactoType() de ObjectFactory. Es
utputStream(fichero); dos con los valores que se recogen de la entra- necesario realizar un casting a ContactoTypeImpl
marshaller.marshal(agendajaxb.getR da de la lista que ha sido seleccionada, nom- ya que este método devuelve una referencia a
oot(), stream);
bre, apellido_1 y apellido_2, se realiza de Object. Para que el esquema sea válido es necesa-
nuevo un recorrido por todos los contactos del rio que se proporcione un número de teléfono y un
}
árbol de contenidos en busca del contacto que nombre, por lo que se establece una comproba-
se ha seleccionado. Para ello se vuelve a obte- ción de estos campos. Si están vacíos se muestra
Mostrar los datos de los contactos ner una lista mediante el método un mensaje al usuario pidiendo estos datos.
getContacto() de agenda y se recorre con un
Una vez cargados los datos de un archivo iterador comparando los datos de cada con-
de contactos, se pueden visualizar todos los tacto con los que se han obtenido del selec-
datos de cada uno seleccionándolo en la cionado. En el momento de que coincida el
lista de contactos disponibles. Los datos contacto que se está comprobando del árbol
disponibles para el contacto aparecerán en de contenidos con el que se debe mostrar, se
los campos de texto de la parte inferior. recogen el resto de los datos mediante los
Como se aprecia en el fragmento de código métodos getDireccion(), getEmail(), getNotas()
presentado en el listado 6, se provee a la lista y getTelefono() de la clase ContactoTypeImpl.
que muestra los contactos disponibles, jList1, En la figura 2 se puede apreciar la interfaz de
Figura 3. Formulario de inserción y modificación de
los datos de un contacto.
SOLO PROGRAMADORES 26
MIDDLEWARE
Tratamiento de XML desde Java (y III): un caso práctico

Si se proporciona un nombre y un teléfono se


LISTADO 7 Opción "Añadir"
procede a rellenar los atributos del contacto [...]
mediante los métodos getXXX() de ObjectFactory of = new ObjectFactory();
ContactoTypeImpl, donde XXX es el nombre de ContactoTypeImpl contactonuevo = (ContactoTypeImpl)of.createContactoType();
if((camponombre.getText().trim().length() == 0)
un elemento del interior de la etiqueta contac- ||(campotlf.getText().trim().length() == 0))
to. Hay que resaltar que el campo teléfono se JOptionPane.showMessageDialog(ventana, "Introduzca un nombre y un teléfono
definió como un entero y el método que esta- como mínimo");
else
blece el teléfono recibe como parámetro una {
instancia de la clase java.math.BigInteger(). Para contactonuevo.setNombre(camponombre.getText().trim());
añadir finalmente el nuevo contacto al árbol de contactonuevo.setDireccion(campodireccion.getText().trim());
contenidos se utiliza el método add() de la lista contactonuevo.setEmail(campocorreo.getText().trim());
contactonuevo.setNotas(camponotas.getText().trim());
que devuelve el método getContacto() de contactonuevo.setPrimerApellido(campoape1.getText().trim());
Agenda. De esta manera simple los cambios contactonuevo.setSegundoApellido(campoape2.getText().trim());
quedan reflejados en el árbol de contenidos. contactonuevo.setTelefono(new
java.math.BigInteger(campotlf.getText().trim()));
En el listado 8 se muestra el caso de la modifi- agenda.getContacto().add(contactonuevo);
cación de un contacto. En primer lugar se debe }
conseguir una referencia al elemento contacto [...]
que se desea modificar. Esto se realiza reco-
rriendo la lista de contactos como se ha visto
anteriormente. En el momento en que el con- LISTADO 8 Opción "Modificar"
tacto que se está evaluando de la lista de con- ContactoTypeImpl contactomodificartemp = null;
tactos coincide con el que se desea modificar while(iterador.hasNext())
se sale del bucle y se establece el valor de con- {
tactomodificar con la instancia del contacto a contactomodificartemp = (ContactoTypeImpl)iterador.next();
String nombretemporal = contactomodificartemp.getNombre();
modificar. Simplemente se deben establecer los String ape1temporal = contactomodificartemp.getPrimerApellido();
valores de los atributos del contacto a modifi- String ape2temporal = contactomodificartemp.getSegundoApellido();
car con los nuevos mediante los métodos if((nombre.compareTo(nombretemporal) == 0)
setXXX() de la clase ContactoTypeImpl, donde &&(apellido_1.compareTo(ape1temporal) == 0)
&&(apellido_2.compareTo(ape2temporal) == 0)) {
XXX es el nombre de un elemento del interior [...]
de la etiqueta contacto. break;
En el caso de la eliminación de un contacto se }
}
debe buscar la referencia al elemento contacto [...]
exactamente igual que en el caso de la modifi- final ContactoTypeImpl contactomodificar = contactomodificartemp;
cación. Una vez obtenida la referencia se debe [...]
contactomodificar.setNombre(camponombre.getText().trim());
eliminar del árbol de contenidos JAXB. Para ello contactomodificar.setDireccion(campodireccion.getText().trim());
se debe invocar al método remove() de la lista contactomodificar.setEmail(campocorreo.getText().trim());
que devuelve el método getContacto() de agen- contactomodificar.setNotas(camponotas.getText().trim());
da, pasando como argumento la referencia del contactomodificar.setPrimerApellido(campoape1.getText().trim());
contactomodificar.setSegundoApellido(campoape2.getText().trim());
contacto a eliminar. Con esta acción ya quedan contactomodificar.setTelefono(new
reflejados los cambios en el árbol de contenidos, java.math.BigInteger(campotlf.getText().trim()));
tal y como se muestra a continuación:
agenda.getContacto().remove(aborrar); Binding, véase la referencia 1) facilita en tratado de ilustrar las diferentes formas de
gran manera el trato con este tipo de datos, utilización de datos XML que existen hacien-
Conclusiones abstrayendo al programador de los detalles do uso del lenguaje de programación Java y
de tratamiento de los ficheros y de las eti- sus diferentes APIs, pero haciendo un espe-
Durante este artículo se ha mostrado la quetas, proporcionando además un conjunto cial hincapié en JAXB. Todas las APIs vistas
construcción de una simple aplicación de de clases personalizadas en cada caso para pertenecen al conjunto JWSDP (Java Web
agenda que maneja archivos de contactos en realizar el manejo de los datos XML, simple- Services Developer Pack) disponible en la
formato XML. Como novedad se ha mostra- mente con crear el esquema XML adecuado. web de Java, http://java.sun.com/webservi-
do como la API JAXB (Java API for XML En general, en esta serie de artículos se han ces/downloads/webservicespack.html

Agradecimientos
Se quiere agradecer al grupo AWEG (Adaptive Web Engineering Group) de la Universidad de Salamanca sus aportaciones y consejos para la elabora-
ción de este artículo. Este trabajo ha sido parcialmente financiado por el proyecto SA017/02 de la Junta de Castilla y León (España).

Referencias
[ 1 ] SUN MICROSYSTEMS. (2004). JAXB (Java API for XML Binding). http://java.sun.com/xml/jaxb.
[ 2 ] WORLD WIDE WEB CONSORTIUM. (2000). XML Schema, http://www.w3.org/XML/Schema.
[ 3 ] WORLD WIDE WEB CONSORTIUM. (2004). eXtensible Markup Language (XML), http://www.w3.org/XML.

27 SOLO PROGRAMADORES
MIDDLEWARE

Enlace de datos XML


con Castor
RICARDO DÍEZ FERREIRA Por todo esto, han surgido múltiples herramientas
para hacer más llevadera esta tarea del progra-
Castor es una herramienta que ayuda mador, de las cuales, Castor es un buen ejemplo.
al programador en la tediosa tarea de ¿Qué es Castor?
manejar los datos en XML y
convertirlos en objetos Java, y Castor es un proyecto de software libre desarro-
llado por Exolab Group, que permite encapsular
viceversa, encapsulando las tareas de la tarea del mapeo XML con Java.
parsear y mapear esos datos. Con las herramientas que proporciona, se puede
fácilmente convertir un documento XML en un obje-
to Java, o viceversa, en muy pocas líneas de código.
También cuenta con una aplicación, llamada
El problema del mapeo XML generador de código, que nos permite generar el
código del objeto Java correspondiente a un
La problemática por la que surge Castor es bas- esquema XML.
tante común en el mundo de la programación. Además del mapeo XML, Castor proporciona herra-
Todo aquel que ha trabajado con datos en for- mientas para la persistencia de los objetos, tanto en
mato XML, se ha encontrado alguna vez con la bases de datos relacionales como en LDAP.
necesidad de convertir esos datos en un objeto Como en casi todos los proyectos de software
manejable desde la aplicación que está desarro- libre, se han realizado muchas aportaciones a
llando. Esta tarea, requiere parsear el documen- través de Internet para la mejora de las herra-
to XML, con ayuda de algún API, y después guar- mientas que proporciona, por lo que es un pro-
dar cada campo de datos XML en el atributo yecto en constante evolución. Cualquiera puede
correspondiente del objeto que se quiere crear. descargarse el código fuente de Castor para
Algo parecido sucede cuando lo que se quiere es estudiarlo y realizar sugerencias a los responsa-
convertir los datos que tenemos almacenados en bles del proyecto.
un objeto, en un documento XML, para ofrecer
un servicio web o algo semejante. Castor XML
Todo esto supone escribir muchas líneas de códi-
go, que hacen que el código resultante sea poco La utilidad más relevante de Castor es, sin duda,
claro y el mantenimiento muy complicado. el mapeo XML, definido como la forma de trans-
En la actualidad, el uso masivo del formato XML, formar un documento XML en una instancia de
tanto para proporcionar servicios web, como un objeto Java, y la operación contraria.
para la sustitución de las bases de datos relacio- Las clases Java que definen los objetos que serán
nales o los ficheros de texto plano en todo tipo mapeados con Castor deben tener ciertas carac-
de aplicaciones, hace que el problema sea mayor. terísticas, como implementar el interfaz
Serializable y ser estilo Bean, con métodos get y
Estructura general set para cada atributo de la clase. Además, estas
de las herramientas
de Castor. clases deben contener un constructor público
por defecto (sin argumentos).
El listado 1 luce una clase muy sencilla que nos
permitirá mostrar el modo de utilizar Castor.
De objeto Java a XML (Marshal)
A continuación se muestra un ejemplo de códi-
go que permite realizar la conversión de una ins-
tancia del objeto Producto en un fichero XML:
Producto producto = new Producto("Producto
1", "Primer producto", new Date());

FileWriter writer = new FileWriter("produc

SOLO PROGRAMADORES 28
MIDDLEWARE
Enlace de datos XML con Castor

LISTADO 1 Clase tomada como ejemplo


import java.util.Date;

public class Producto implements java.io.Serializable {


private String nombre = null;
private String descripcion = null;
private Date fechaCreacion = null;
public Producto(String nombre, String descripcion, Date fechaCreacion) {
this.nombre = nombre;
this.descripcion = descripcion;
this.fechaCreacion = fechaCreacion;
}
public String getNombre() {
Castor XML permite la transformación simple entre return nombre;
Java y XML en múltiples direcciones. }
public void setNombre(String nombre) {
to.xml"); this.nombre = nombre;
}
Marshaller.marshal(producto, writer); public String getDescripcion() {
return descripcion;
Con las tres líneas anteriores se ha genera- }
do un fichero XML con los datos de la ins- public void setDescripcion(String descripcion) {
tancia de la clase Producto. La clase this.descripcion = descripcion;
Marshaller, con su método marshal, permi- }
public Date getFechaCreacion() {
te generar el fichero XML, recibiendo como return fechaCreacion;
parámetros el objeto y un objeto FileWriter }
del fichero a generar. public void setFechaCreacion(Date fechaCreacion) {
De XML a objeto Java (Unmarshal) }
this.fechaCreacion = fechaCreacion;

Es la operación contraria a la anterior, y es igual }


de simple, como se observa a continuación:
FileReader reader = new FileReader("produc
to.xml"); LISTADO 2 fichero XML que se desea mapear
Producto producto = (Producto)Unmars <Historico>
haller.unmarshal(Producto.class, reader); <Cliente>
<Nombre>Juan Nadie</Nombre>
<Email>juan@midominio.com</Email>
En este caso, se hace uso de la clase </Cliente>
Unmarshaller, que en su método unmars- <Pedido referencia="001">
hal, recibe el tipo de producto a crear y un <Descripcion>Perros verdes</Descripcion>
<Cantidad>10</Cantidad>
objeto FileReader del fichero XML que con- </Pedido>
tiene los datos. Este método permite obte- <Pedido referencia="002">
ner una instancia del objeto Producto, con <Descripcion>Gatos azules</Descripcion>
los datos almacenados en el fichero. <Cantidad>4</Cantidad>
</Pedido>
Ficheros de mapeo </Historico>
Aunque las dos operaciones anteriores pue-
den ser suficientes para manejar los datos
de una aplicación, normalmente los fiche- LISTADO 3 Estructura de clases
ros XML son bastante más complicados que
el del ejemplo, lo que produce que haya que import java.util.Vector;
public class MiHistorico {
generar estructuras más complejas de cla- private DatosCliente cliente;
ses para albergar esos datos. Además, no private Vector pedidos;
siempre el documento XML tiene el forma-
public DatosCliente getDatosCliente()
to de las clases que se quieren utilizar, { return cliente; }
teniendo que amoldar el fichero XML a un public void setDatosCliente(DatosCliente cliente)
modelo de datos anterior. { this.cliente = cliente; }
public Vector getPedidos()
A consecuencia de esto, para controlar el { return pedidos; }
formato y el contenido del documento public void setPedidos(Vector pedidos)
XML, hay que utilizar ficheros de mapeo, { this.pedidos = pedidos; }
que son ficheros XML que contienen un }
elemento por cada clase del modelo de public class DatosCliente {
datos, y que permiten definir qué campo public String _nombre;
del documento XML corresponde a cada public String _email;
atributo de esas clases. El listado 2 repre- public String get_nombre()
senta un fichero XML que se desea mapear. { return _nombre; }
Para albergar la información contenida en public void set_nombre(String _nombre)

29 SOLO PROGRAMADORES
MIDDLEWARE

LISTADO 3 (continuación)
{ this._nombre = _nombre; }
public String get_email()
{ return _email; }
public void set_email(String _email)
{ this._email = _email; }
}

public class DatosPedido {


public String _referencia;
public String _descripcion;
public int _cantidad;

public String get_referencia()


{ return _referencia; }
public void set_referencia(String _referencia)
{ this._referencia = _referencia; } Castor JDO proporciona una interfaz simple para la
public String get_descripcion()
{ return _descripcion; }
persistencia de los objetos en bases de datos
public void set_descripcion(String _descripcion) relacionales.
{ this._descripcion = _descripcion; }
public int get_cantidad() Al definir el fichero de mapeo, ya se pueden
{ return _cantidad; } utilizar las clases Marshaller y Unmarsha-
public void set_cantidad(int _cantidad)
{ this._cantidad = _cantidad; }
ller para hacer la conversión que se necesi-
} te. La forma de llamar a los métodos cam-
bia ligeramente con respecto a la versión
sin fichero de mapeo, pues hay que especi-
LISTADO 4 Fichero de mapeo ficar a estas clases el fichero de mapeo que
se va a utilizar para las conversiones, usan-
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD Version
do para ello la clase Mapping, y el método
1.0//EN" setMapping de las clases Marshaller y
"http://castor.exolab.org/mapping.dtd"> Unmarshaller.
<mapping> Para la conversión de objeto Java a docu-
<class name="MiHistorico">
<map-to xml="Historico"/> mento XML utilizando el fichero de mapeo,
<field name="DatosCliente" type="DatosCliente"> estúdiese el código siguiente:
<bind-xml name="Cliente"/>
</field> Mapping mapping = new Mapping();
<field name="Pedidos" type="DatosPedido" collection="vector">
mapping.loadMapping("mapping.xml");
<bind-xml name="Pedido"/>
</field> FileWriter writer = new FileWriter("
</class>
<class name="DatosCliente"> historico2.xml");
<field name="_nombre" type="java.lang.String">
<bind-xml name="Nombre" node="element"/> Marshaller marshaller = new Marshalle
</field>
<field name="_email" type="java.lang.String"> r(writer);
<bind-xml name="Email" node="element"/> marshaller.setMapping(mapping);
</field>
</class> marshaller.marshal(historico);
<class name="DatosPedido">
<field name="_referencia" type="java.lang.String" direct="true">
<bind-xml name="referencia" node="attribute"/> Y en el caso de la conversión de documento
</field> XML a objeto Java, el código es muy similar:
<field name="_cantidad" type="integer" direct="true">
<bind-xml name="Cantidad" node="element"/> Mapping mapping = new Mapping();
</field>
<field name="_descripcion" type="java.lang.String" direct="true"> mapping.loadMapping("mapping.xml");
<bind-xml name="Descripcion" node="element"/>
</field> FileReader reader = new FileReader("
</class> historico.xml");
</mapping>
Unmarshaller unmarshaller = new Unmars
haller(MiHistorico.class);
dicho fichero, se crea una estructura de que controla la creación de los objetos Java
clases como la publicada en el listado 3. a partir del XML. Este fichero de mapeo se unmarshaller.setMapping(mapping);
La clase MiHistorico contiene los datos del muestra en el listado 4. MiHistorico historico = (MiHistorico)u
cliente, en un objeto DatosCliente, y un Como se puede observar, para cada clase
nmarshaller.unmarshal(reader);
vector con un listado de pedidos, definidos definida, existe un campo class en el fiche-
por el objeto DatosPedido. ro de mapeo. A su vez, para cada atributo Como se puede apreciar en los ejemplos, el
Una vez se ha generado el modelo de cla- de las clases, hay que definir un campo sistema de mapeo por fichero da flexibili-
ses, se puede definir el fichero de mapeo field con el tipo de ese atributo. dad al programador en cuanto al formato y

SOLO PROGRAMADORES 30
MIDDLEWARE
Enlace de datos XML con Castor

la nomenclatura de los atributos de las cla- LISTADO 5 Esquema XML


ses. Es este un buen modo de desasociar los
cambios en el modelo de datos de los cam- <?xml version='1.0'?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
bios en el formato de los documentos XML. targetNamespace="http://castor.exolab.org/Examples" >
Castor proporciona además, una herra- <xs:complexType name="Persona">
mienta para generar el fichero de mapeo a <xs:sequence>
<xs:element name="nombre" type="xs:string"/>
partir de las clases Java. La clase que reali- <xs:element name="apellido" type="xs:string"/>
za este trabajo es MappingTool. </xs:sequence>
</xs:complexType>
El generador de código </xs:schema>

En la mayoría de aplicaciones que utilizan


documentos XML, éstos vienen definidos LISTADO 6 Código generado a partir del esquema XML
por esquemas XML que definen el conteni-
do, la estructura, y el significado de cada /*
* This class was automatically generated with
uno de esos documentos. * <a href="http://www.castor.org">Castor 0.9.5.3</a>, using an XML
Para representar en Java el modelo de * Schema.
datos que define esa estructura, normal- * $Id$
*/
mente el desarrollador debe escribir todas //---------------------------------/
las clases necesarias. //- Imported classes and packages -/
Realmente, un documento XML es una ins- //---------------------------------/
tancia de un esquema XML, al igual que un import java.io.IOException;
import java.io.Reader;
objeto es una instancia de una clase con- import java.io.Serializable;
creta, por lo que la clase es una represen- import java.io.Writer;
tación en Java de ese esquema XML. import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Marshaller;
Cuando se trata de estructuras sencillas, import org.exolab.castor.xml.Unmarshaller;
como las del ejemplo anterior, no supone import org.exolab.castor.xml.ValidationException;
demasiado esfuerzo codificar esas clases, import org.xml.sax.ContentHandler;
/**
pero cuando se trata de estructuras más * Class Persona.
complejas, se convierte en un proceso *
tedioso y complicado. * @version $Revision$ $Date$
El generador de código de Castor permite */
public class Persona implements java.io.Serializable {
realizar este proceso automáticamente, //--------------------------/
ahorrando mucho tiempo en el desarrollo //- Class/Member Variables -/
de la aplicación. Utilizando un esquema //--------------------------/
private java.lang.String _nombre;
XML que cumpla el estándar W3C, se va a private java.lang.String _apellido;
generar el código de todas las clases Java public static java.lang.Object unmarshal(java.io.Reader reader)
necesarias, con todos los atributos, y los throws org.exolab.castor.xml.MarshalException,
org.exolab.castor.xml.ValidationException
métodos necesarios para realizar el mars- {
halling y unmarshalling. return (Persona) Unmarshaller.unmarshal(Persona.class, reader);
La llamada al generador de código se puede }
hacer directamente desde la línea de coman- public void marshal(java.io.Writer out)
throws org.exolab.castor.xml.MarshalException,
dos, escribiendo la siguiente instrucción: org.exolab.castor.xml.ValidationException
java org.exolab.castor.builder.Sour {

ceGenerator -opciones Marshaller.marshal(this, out);


}
Existen múltiples opciones del generador de
código, y algunas de ellas se deben incluir en Combinando Castor XML y JDO, se puede diseñar
la propia línea de comandos. De éstas, las cualquier tipo de servicio web, con una estructura
más importantes son las siguientes: sencilla.
z -i nombre_fichero: Indica el fichero que
contiene el esquema XML Hay otras opciones avanzadas que se defi-
z -package nombre_paquete: Nombre del nen en el fichero castorbuilder.properties,
paquete en el que se quiere generar la clase. como definir una superclase, generar el
z -dest ruta: En esta opción se indica la método equals, etc.
ruta donde se quiere generar la clase. Para que funcione correctamente es nece-
z -nomarshall: Con esta opción se le indi- sario que todos los ficheros de Castor estén
ca al generador que no es necesario crear en el CLASSPATH de Java. La distribución
los métodos de marshal y unmarshal. también incluye ficheros .bat y .sh que faci-
z f: Fuerza la supresión de los errores no litan la utilización de esta herramienta.
fatales. En el listado 5 se muestra un ejemplo de un

31 SOLO PROGRAMADORES
MIDDLEWARE

XML. Para ello, Castor proporciona también


una herramienta que permite generar, a partir
de un documento XML, su esquema XML
correspondiente. Esta herramienta está conte-
nida en la clase XMLInstance2Schema, y aun-
que contiene algunos errores, ahorra una can-
tidad considerable de trabajo en caso de no
disponer de un esquema.

Castor JDO y DAX


Aunque la parte más conocida y utilizada es el
enlace de datos XML, Castor también proporciona
herramientas para la persistencia en bases de
datos relacionales y LDAP.
Castor JDO (Java Data Objects) es el API que ges-
tiona la persistencia de objetos Java en todo tipo
de bases de datos relacionales como Oracle,
MySql, SqlServer, Informix, Sybase, etc.
El JDO maneja automáticamente la inserción y
recuperación en bases de datos de cualquier
Sitio web de Castor, objeto Java, haciendo transparente todo el
donde se puede descargar pequeño esquema XML que nos permitirá ilustrar proceso de conexión y las consultas SQL nece-
la aplicación el uso del generador de código. Dicho esquema sarias para sacar esa información. Permite
(http://www.castor.org).
representa una clase Persona con sólo dos atribu- incluso manejar objetos Java collection como
tos de tipo String. Vector, Hashtable, Collection, Set, y Map. Para
A continuación, en el listado 6, mostramos una ello, utiliza ficheros de mapeo similares a los
porción del código generado tras la ejecución del de Castor XML, para definir las corresponden-
generador de códigos, a partir del esquema del cias entre los atributos de la clase y los cam-
listado 5. pos de las tablas de la base de datos.
Después de observar el listado 6, el lector se Castor JDO y Castor XML se pueden combinar
habrá dado cuenta de que hemos generado una para realizar operaciones transaccionales en
clase completa simplemente ejecutando un bases de datos, utilizando XML como entrada
comando. En este caso es una clase sencilla, pero y salida.
funciona igualmente con modelos de datos más Por otra parte, Castor DAX proporciona la posibili-
complicados. dad de gestionar la persistencia en LDAP, pero debi-
Sitio web de Exolab Group, que se Muchas veces, no disponemos de un esquema do al poco uso de esta herramienta por parte de los
ocupa del desarrollo de Castor, así XML con el que podamos generar estas clases, desarrolladores, el proyecto no ha avanzado.
como de muchos otros proyectos sino únicamente un ejemplo de documento
(http://www.exolab.org).
Conclusiones
Castor nos proporciona una serie de herramientas
con el objetivo de ahorrar trabajo al desarrollador
de aplicaciones Java, haciendo inmediatos los pro-
cesos más pesados y repetitivos del desarrollo de
una aplicación.
Otra ventaja, además del ahorro de trabajo, es que
el resultado final es una aplicación más limpia,
intuitiva, y con un mantenimiento más sencillo.
Este API es una clara demostración de que
muchas veces, el software libre puede ser una
opción muy válida, e incluso recomendable, para
el desarrollo de aplicaciones profesionales.
Actualmente, con el auge de los llamados ser-
vicios web, es de gran utilidad una herramien-
ta como Castor para poder manejar grandes
cantidades de información y ofrecerlas al
usuario del servicio en XML.
En resumen, Castor es una herramienta muy
útil y muy versátil, que todo desarrollador Java
debería conocer.

SOLO PROGRAMADORES 32
BASES DE DATOS

Acceso
c so a datoss
con
n ADO.NET
DO E (y( III)
I
MIGUEL EGEA (Microsoft M.V.P. en SQL Server), Sinergia No hace mucho que han tenido ustedes la
Tecnológica S.L. oportunidad de leer en esta misma publica-
ción un artículo sobre nuevos paradigmas en
Terminamos la serie de artículos sobre las formas de tratar las transacciones, sin
ADO.NET hablando de una embargo y en mi opinión, el famoso ACID,
Atomicidad, Consistencia, Aislamiento
miscelánea de cuestiones relacionadas (Isolation en inglés) y Durabilidad tiene plena
con el acceso a datos, todas vigencia hoy en día. Veremos las formas que
tiene ADO.NET de tratar las transacciones y
importantes, como por ejemplo el qué significan los niveles de aislamiento.
tratamiento de transacciones, que Trataremos los campos largos, es decir cómo
introducir datos grandes en una base de datos,
pueden marcar la diferencia entre y cómo recuperarlos y usarlos en nuestras
aplicaciones bien hechas y aplicaciones. En concreto veremos cómo
introducir esos datos desde una aplicación
aplicaciones mediocres. Windows Forms tradicional y cómo extraer esa
información en un datagrid desde ASP.NET.
Sin embargo para comenzar veremos el méto-
Introducción do update del objeto DataAdapter, veremos
sus eventos y proporcionaremos pistas sobre
En esta última entrega veremos el tratamien- cómo incluir tratamiento personalizado a las
to de transacciones, las formas más adecuadas excepciones que puedan producirse.
de usar el método update del DataAdapter Hablaremos de los problemas que puede oca-
unido al enlace a datos (databinding) y vere- sionar el bloqueo optimista, tipo por defecto si
mos también el tratamiento de los campos usamos DataSets y las soluciones que pode-
largos (Binary Large Objects, blobs). mos adoptar.

El DBAdapter y su método update


Quedaba pendiente abordar el tema de la
actualización de datos. Por supuesto que
estas actualizaciones pueden realizarse
mediante llamadas al método ExecuteNon-
Query del objeto Command que ya vimos en
el número anterior.
Sin embargo, a través de los Datasets y usan-
do el método Update del Adapter podemos
realizar actualizaciones por lotes de datos.
La problemática inicial que plantean este
tipo de mecanismos es que requieren de blo-
queo optimista, ya sabemos que el DataSet es
una especie de copia de parte de una base de
datos en memoria, los cambios que realice-
mos sobre un Dataset se realizan en memo-
Figura 1. ria. Por lo tanto no hay nada que nos garan-
Ejemplo de aplicación web
que devuelve imágenes tice que cuando vayamos a entregar cambios
obteniéndolas de una a nuestro servidor de datos, los datos que
base de datos. tomemos de partida para las modificaciones
sigan presentes en la base de datos.

SOLO PROGRAMADORES 34
BASES DE DATOS
Acceso a datos con ADO.NET (y III)

almacenarlos en el motor relacional de la


base de datos o dejarlos simplemente en
el sistema de archivos.
De momento, con lo que tenemos ahora
mismo los sistemas de archivos presen-
tan un problema serio, la consistencia de
los datos. Es muy posible que si almace-
namos la información de la ruta en regis-
tros en la base de datos, alguien mueva
una carpeta, le cambie el nombre y
parezca que han desaparecido todos los
archivos. Si los datos están contenidos en
la base de datos, esto es mucho más difí-
cil que suceda. Además si sucede, des-
Figura 2. Ejemplo de actualización fallida por problemas de concurrencia. aparece todo, no solamente una parte de
la información, es decir, los datos siem-
Este es uno de los problemas que tendre- A través de la clase DataView podemos pre quedan consistentes.
mos que solucionar, estos problemas se obtener las versiones actualizadas, pro- Sin embargo, los motores relacionales,
presentan siempre en actualizaciones y puestas u originales de los datos de hasta ahora, están pensados para mane-
en borrados, nunca en inserciones. nuestro dataset. Estos valores serán los jar información 'tratable', información
Para ayudarnos el Adapter nos genera que se suministren al comando update sobre la que hacer consultas en cual-
código SQL en los objetos SelectCom- para actualizar. En el ejemplo que se pro- quiera de los dialectos SQL que hay en el
mand, UpdateCommand, DeleteCo- porciona el lector encontrará un datagrid mercado.
mmand e InsertCommand. Los objetos con estos valores. Las imágenes, los archivos de los proce-
que lo necesitan tienen mecanismos Los problemas que presenta el mecanis- sadores de texto, los videos, no están
para garantizar el bloqueo optimista. La mo optimista de bloqueos son evidentes, pensados para ser consultados vía SQL,
técnica que usa por defecto ADO.NET es si no hay nada bloqueado, nada impide además la estructura de almacenamiento
añadir en la cláusula WHERE los valores que alguien lo cambie mientras yo me lo de los objetos en las bases de datos,
originales de los datos para comparar pienso. Es una problemática muy conoci- generalmente también está optimizada
con los que hay en el instante de ejecu- da en las aplicaciones de reservas. Lo que pensando en un tipo de datos que en
tar las actualizaciones o borrados. en realidad sucede es que se toma una nada se parecen a imágenes etc.
El comportamiento que tendrá el método estrategia, en algunas ocasiones (la En resumen, si los dejamos fuera, pueden
update ante un error (algún registro que mayoría) acaba ganando, (actualizando), quedar inconsistencias y tendremos que
no pueda modificarse por ejemplo) el primero que llega, en otras, el último. administrar dobles sistemas de permisos,
dependerá de la propiedad ContinueUp- No penséis por ello que son todo desven- si los metemos en el motor de base de
dateOnError. Veamos cómo. tajas, tiene muchas ventajas, la primera datos, tendremos que afrontar la dificul-
En nuestro ejemplo añadiremos un la escalabilidad. Al no existir bloqueos tad que presenta su introducción y
DataAdapter pinchando y arrastrando físicos grandes en las bases de datos, extracción y la sobrecarga en espacio y
desde el administrador de servidores a un éstas suelen comportarse de forma uso de la base de datos.
formulario Windows. Después añadire- mucho más ágil, son más eficaces con los La decisión depende por tanto de varios
mos las instrucciones necesarias para recursos del servidor y generan menos factores, algunos a favor y otros en con-
rellenar el DataSet y mostrar la informa- problemas a los administradores. tra y ninguno de ellos es determinante,
ción en un datagrid. Aunque la informa- no hay un sí o un no.
ción podría modificarse por otros meca- Binary Large Objects Lo cierto es que la decisión de almace-
nismos, para ver el funcionamiento basta nar este tipo de datos en la base de
con enlazar el Dataset a un Datagrid y Qué son y qué problemas generan datos quedará a elección de cada uno de
ver el resultado. Pensemos ahora en elementos como imá- ustedes.
Como podemos ver en la figura 2 el pro- genes, hojas de cálculo, documentos de Es muy probable que esto cambie con
pio datagrid nos informará de la excep- procesador de texto, etc. Siempre surge LongHorn, ya saben, la próxima versión
ción si se produce un problema de con- la duda sobre la conveniencia o no de de Windows, que trae entre otras
currencia. En nuestro caso simplemente
hemos mostrado el error y hemos captu-
rado la excepción atendiendo al evento LISTADO 1 Atendiendo errores en la actualización
de actualización como se puede ver en el
código del listado 1. private void sqlDataAdapter1_RowUpdated(object sender,
System.Data.SqlClient.SqlRowUpdatedEventArgs e)
Añadiendo código personalizado a los {
eventos que nos proporciona el DataA- if (e.Errors!=null) {
dapter podríamos permitir a nuestras MessageBox.Show("Se ha produccido una excepción al actualizar la fila
con código " + e.Row["CustomerId"] +". Seguiremos con las actualizaciones");
aplicaciones recuperarse de errores, com- }
parar valores con valores que hay en este }
momento en la tabla etc.

35 SOLO PROGRAMADORES
BASES DE DATOS

inconvenientes que les describía en las Forms tradicional, la extracción de esa


líneas anteriores desaparecerán. información la implementaremos desde
Por otro lado WinFs está (estará) basado una aplicación web, usando enlace a
o contiene una parte de SQL-Server, ima- datos y un datagrid.
ginen ustedes las posibilidades. Seguro Introducir campos largos en una base de
que a poquito que miren a su alrededor datos con ADO.NET
encontrarán centenares de usos nuevos Para ilustrar todos los ejemplos hemos
que nos proporcionarán entretenimiento usado SQL-Server de modo que tanto los
(y trabajo, claro) a los desarrolladores. scripts, como los objetos de ADO.NET que
¿Y cómo solucionamos el problema de las vamos a ver se refieren al gestor de base
imágenes con ADO.NET? de datos de Microsoft.
En realidad hay dos problemas diferen- Comenzaremos estableciendo un objeto
tes que solucionar. De una parte está el conexión a nuestra base de datos que
Figura 3. problema de la introducción de la infor- contendrá una tabla con la estructura
Este es el aspecto de la aplicación Windows que hemos
usado para introducir información en nuestra BBDD. mación en la base de datos, de otra que podemos ver en el listado 2.
parte extraer esa información para ser En dicho listado podemos observar
muchas novedades y mejoras la de un mostrada. En éste artículo veremos varias cosas, el campo CodEmpleado es
nuevo sistema de archivos (WinFs) que cómo realizar ambas operaciones. La un autonumérico, algo similar existe en
entre otras características es transac- introducción de la información la reali- Access y en Oracle. Después hemos
cional y por tanto buena parte de los zaremos desde una aplicación Windows introducido un campo para almacenar la
identidad de la persona y dos campos
que permitirían almacenar la fotografía
LISTADO 2 Estructura de la tabla y el currículum de la persona en cues-
tión. En esta tabla dos de los campos
CREATE TABLE [blob] ( son campos largos, la fotografía y el
[CodEmpleado] [int] IDENTITY (1, 1) NOT NULL ,
[NombreYApellidos] [nvarchar] (100) NOT NULL , currículo de la persona.
[Fotografia] [image] NULL , Para poder introducir los ficheros en la
[Curriculum] [image] NULL , base de datos debemos conocer esos
(
PRIMARY KEY CLUSTERED ficheros. Para abrir los ficheros hemos
[CodEmpleado] usado un objeto de tipo OpenFileDialog,
) ON [PRIMARY] que nos facilita la tarea. Una vez conoci-
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] das las rutas de los archivos de imagen y
GO
currículo, debemos leerlos para poder
introducirlos a la base de datos, esto se
hace con las cinco líneas de código del
LISTADO 3 Introduciendo ficheros en la BBDD listado 3.
// Abrimos el fichero de la imagen. Además de tener en variables (buffer en
System.IO.FileStream fs este caso) las imágenes, antes de intro-
= new System.IO.FileStream( file, FileMode.Open, FileAccess.Read); ducirlas necesitamos también preparar
// Usaremos un lector binario para obtener los datos del fichero…
BinaryReader r = new BinaryReader(fs); nuestra instrucción SQL. Para ello hemos
// …para introducirlo en un array de bytes. usado un objeto command tal y como
byte[] buffer = new byte[fs.Length]; podemos ver en el listado 4.
// Por último invocamos a leer sobre la variable buffer
r.Read(buffer,0,(int)fs.Length-1);
La instrucción del listado 4 es en reali-
fs.Close(); dad un conjunto de tres que ejecutare-
mos en una sola. La primera evita que el
servidor nos devuelva información sobre
el número de registros afectados.
LISTADO 4 Instrucción para hacer la inserción Después ejecutamos la instrucción que
realmente inserta los valores y por últi-
SqlCommand InsertCommand = new SqlCommand("SET NOCOUNT ON " + mo recuperamos el autonumérico recién
"Insert Into dbo.Blob (NombreYApellidos,Fotografia,Curriculum)" + "
Values(@NombreYApellidos,@Fotografia,@Curriculum) " + insertado.
" Select Scope_identity() as Clave",con); En SQL-Server 2000 el uso de
Scope_Identity() es más adecuado en
este caso (y en general) que el tradicional
LISTADO 5 Construyendo la URL @@identity.
Por último añadimos los parámetros y
<asp:TemplateColumn HeaderText="Fotografia">
<ItemTemplate> ejecutamos el comando. Como ejemplo
<asp:Image ImageUrl='<%# mostramos uno de los parámetros que
ConstruyeURL(DataBinder.Eval(Container.DataItem,"codEmpleado"))%>' Width=150 son de tipo image para que se vea claro
Height=125 runat=server />
</ItemTemplate>
cómo se le pasa el valor y cómo se defi-
</asp:TemplateColumn> ne el parámetro:

SOLO PROGRAMADORES 36
BASES DE DATOS
Acceso a datos con ADO.NET (y III)

InsertCommand.Parameters.Add
("@Fotografia",SqlDbType.VarBinary,0,
"@Fotografia").Value=buffer;
De esta forma conseguimos introducir
la información binaria en campos de
tipo imagen (en este caso) con la limi-
tación que nos imponga el motor de
base de datos (2GB en el caso de SQL-
Server).
Recuperar campos largos de una base de
datos con ADO.NET
Decíamos que la segunda problemática
era recuperar la información y mostrarla
por pantalla. Para hacer esto hemos ele-
gido realizar una aplicación web, el
resultado es el que puede verse en la
figura 4.
A lo largo de las siguientes líneas vere-
mos los pasos que hemos seguido para
conseguir mostrar estas imágenes.
Algunos de los pasos tienen más que ver
con ASP.NET que con ADO.NET y no
entraremos demasiado en detalle, sin
embargo si que comentaremos los trozos
de código que tienen la mayor responsa- Figura 4.
El entorno de desarrollo preparado para albergar las imágenes de la base de datos.
bilidad en el resultado final.
Nuestra aplicación web tiene dos for-
mularios web (extensión aspx). Como
seguramente conocerán la mayoría de LISTADO 6 Recuperando una fotografía
los lectores dentro de los proyectos
private void Page_Load(object sender, System.EventArgs e)
ASP.NET para cada formulario tenemos {
dos partes, la definición y el código que // Variable para la conexión a la base de datos
le da sustento. Luego el motor de SqlConnection con;
ASP.NET se encarga de traducir todo SqlCommand cmd;
SqlDataReader dr;
este código a su resultado HTML y // recogemos el código de empleado del que nos están solicitando la fotogra-
devolver ese código al navegador del fía
cliente (que no necesita por supuesto int codEmpleado;
codEmpleado=int.Parse(this.Request.Params["idEmpleado"].ToString());
tener nada instalado). Dentro de la // obtenemos la cadena de conexión del web.config (deberíamos encriptarlo)
parte que define la página (la más // ConfigurationSettins de System.Configuration
parecida al HTML) hemos usado un con = new sqlConnection(ConfigurationSettings.AppSettings["conexion"]);
// abrimos conexión a BBDD
control de servidor, en concreto un con.Open();
DataGrid. // Recojamos el valor que nos están demandando
Hay muchos ejemplos del manejo de este cmd= new SqlCommand("Select Fotografia From blob where
control en esta dirección URL: codEmpleado=@CodEmpleado",con);
// Suministramos el parámetro código de empleado
http://samples.gotdotnet.com/quicks cmd.Parameters.Add
("@CodEmpleado",SqlDbType.Int,4,"@codEmpleado").Value=codEmpleado;
tart/aspplus/samples/webforms/ctrlref // Usamos un Reader para devolver la información
dr=cmd.ExecuteReader(CommandBehavior.SequentialAccess);
/webctrl/datagrid/doc_datagrid.aspx Response.Buffer=true;
Response.Expires=0;
El lector puede acudir a este enlace para Response.Clear();
ampliar la información que se está pro- // Devolvemos la imagen
Response.ContentType="image/bmp";
porcionando. // Recorremos el reader
En la sección HTML de nuestro formula- while (dr.Read())
rio hemos creado una columna de plan- {
// Escribimos la respuesta
tilla y en esa columna hemos personali- Response.BinaryWrite((byte [])dr["Fotografia"]);
zado la acción que se ejecutará cuando }
se dibuje nuestra página. Esta acción // Cerramos y liberamos todos los objetos
dr.Close();
será llamar al código subyacente, para cmd.Dispose();
construir dinámicamente la URL de la con.Close();
que nos traeremos la imagen (obsérvese // Y acabamos
el listado 5). }
Response.End();

37 SOLO PROGRAMADORES
BASES DE DATOS

base de datos evidentemente no hay nin- dito y si no se puede por un error, sim-
gún problema, pero esto no sucede, nor- plemente deshacemos ese trozo de códi-
malmente decenas o cientos de personas go, no toda la transacción.
se conectan a las aplicaciones empresa- Algunos de ustedes estarán preguntán-
riales de una compañía. Incluso por dose cuándo se crean estas transaccio-
millares pueden conectarse si estamos en nes. Pues bien, se crean a partir de la
un desarrollo web, es por tanto muy función BeginTransaction del objeto
importante conocer qué está haciendo Connetion.
ADO.NET con las transacciones y en qué Este método declara el comienzo de
momento. una transacción y asegura que las ope-
En este mundo de las transacciones la raciones que se realicen dentro de esa
regla es muy fácil, para abrir una trans- transacción cumplirán el ACID: se
acción hay que esperar al último momen- harán completas o no se harán en
to, para cerrarla sin embargo, cuanto absoluto, los cambios validados perma-
antes mejor. necerán en la base de datos, no dejarán
Figura 5. El Objeto Transacción la base de datos en un estado inconsis-
Algunas de las propiedades y métodos que tiene el
objeto transacción. Utilizaremos el objeto transacción cuan- tente y garantizarán el aislamiento de
do toda la problemática transaccional la transacción:
La función ConstruyeURL tiene por esté en ADO.NET, es decir en la comuni-
// creamos una transacion y la asocia
único cometido devolver un string con cación con un servidor de base de datos.
una dirección del estilo: Si hay más de un servidor involucrado (un mos a nuestra primera conexión.

Imagen.aspx?idEmpleado=23 servidor de colas y un servidor de base de Pedimos lecturas repetibles


datos por ejemplo) en el proceso habría
El resultado es que cada imagen se irá a que utilizar el MS-DTC (coordinador de Tran1 = Conexion1.BeginTransaction(I
la página indicada para dibujarse. Por lo transacciones distribuidas). La forma más solationLevel.RepeatableRead,"Tr1");
tanto, el código que hay en la página será sencilla en ese caso es usar los
el que realmente leerá la imagen del ser- EnterpriseServices. Estos quedan sin También tiene una propiedad interesantí-
vidor de base de datos, vea el código del embargo fuera por completo del alcance sima, IsolationLevel. Esta propiedad
listado 6. de este artículo. 'matiza' la I del ACID. En teoría aislado
Como puede verse en el listado 6, hemos En algunas otras ocasiones puede dispa- significa eso, como si estuviese solo en la
usado un modificador especial para abrir rarse de forma automática el coordinador base de datos, sin embargo en la vida real
un datareader (SequentialAccess), sin de transacciones distribuidas, por ejem- eso no es así de sencillo.
embargo hay más alternativas a este plo cuando desde SQL-Server accedemos Si estoy solo en la base de datos y ejecu-
método, por ejemplo el método a servidores vinculados, se abren este to un comando Select MAX(codigo),
ExecuteScalar: tipo de transacciones (y no es necesario nadie más debería poder insertar un
// Otra forma de hacer lo mismo es: usar Enterprise Services en este caso). registro, ya que si lo hiciese, potencial-
El objeto transacción tiene tres métodos mente podría tener un código mayor, y mi
byte[] b=(byte [])cmd.ExecuteScalar(); importantes: conexión no se comportaría como si
Response.BinaryWrite(b); z Commit, indica el final exitoso de una estuviese sola en la base de datos. Sin
transacción. Usaremos el comando para embargo este mecanismo es muy agresi-
indicar al servidor de base de datos que vo con la concurrencia y daría lugar a
Tratamiento de transacciones con hemos terminado nuestras operaciones bases de datos permanentemente blo-
ADO.NET y que debe liberar los bloqueos que queadas.
pudiesen quedar abiertos. La propiedad IsolationLevel tiene varios
Transacciones y concurrencia z Rollback, lo usaremos para deshacer una valores posibles, que son escritos de
Realmente el objeto transacción es uno transacción, dejaremos en ese momento menos bloqueante a más: lecturas sin
de los objetos que sin ser novedoso es la base de datos como si no hubiésemos confirmar, lecturas confirmadas (por
de los más desconocidos, no tanto por tocado ningún registro. defecto en SQL-Server), lecturas repeti-
que no se conozcan sus métodos sino z Save, permite abrir puntos de salvaguar- bles y por último serializables. Cada uno
por la complejidad que guarda en sí da (savepoints) dentro de la base de de estos modos indica mecanismos dis-
mismos. datos, estos savepoints sirven para tintos de entender el aislamiento. Por
No son realmente métodos complejos. encerrar funcionalidad que no sea críti- ejemplo en las lecturas confirmadas se
Comenzar una transacción y validarla o ca y que de fallar no implican una vuel- mantienen bloqueos compartidos sobre
rechazarla no tendría por qué ser una ta atrás de toda la transacción. Ejemplos las lecturas, pero es posible que otra
tarea difícil, sin embargo viene a jugar de negocio en los que usarlos hay transacción distinta modifique valores ya
en este partido un concepto como la muchos, por ejemplo si tenemos que leídos y que estos cambien entre dos eje-
concurrencia. calcular el crédito inicial disponible para cuciones de la misma sentencia dentro
Mientras mi transacción está abierta y un cliente, pero los recursos necesarios de la misma transacción.
me voy desplazando por los objetos de la para hacerlo están muy usados y gene- El lector encontrará en el CD-ROM una
base de datos ¿Qué está sucediendo con ran fuertes bloqueos. Podemos usar un aplicación C# que demuestra las dife-
las demás conexiones? Si estoy sólo en la savepoint para intentar calcular ese cré- rencias entre dos de los niveles de ais-

SOLO PROGRAMADORES 38
BASES DE DATOS
Acceso a datos con ADO.NET (y III)

Figura 6.
Aplicación que utiliza lecturas repetibles y lecturas confirmadas para demostrar las diferencias.

lamiento. En esa aplicación podemos ver el número de transacciones que se desee.


cómo, a costa claro está de menor concu- Solamente hay que tener en cuenta un prin-
rrencia, el nivel de aislamiento Repeatable cipio, una validación de una transacción
Reads no tiene problemas de lecturas no anidada no implica la validación completa
repetibles. Este nivel sigue teniendo proble- de la transacción superior, sin embargo un
mas de lecturas fantasmas (registros que rollback si implica que ninguna transacción
pueden aparecer que antes no estaban), que de las anidadas se ejecutará.
no tiene el nivel serializable. Sin embargo,
el nivel serializable es muy agresivo con la Conclusiones
concurrencia generando frecuentes blo-
queos y abrazos mortales. Y ahora, ¿qué nos queda? Quizá les resulte
No tener un control sobre todos estos curioso que me haga esta pregunta en el últi-
métodos puede llevarnos a situaciones bas- mo número de esta serie, pero es cierto, aun
tante desagradables, por ejemplo si basa- queda mucho de ADO.NET, sin embargo hemos
mos toda nuestra estrategia de códigos en tocado los asuntos fundamentales, el trata-
instrucciones del tipo Select max(), es muy miento de comandos, conexiones, adaptadores Dado que la
probable que tengamos muchos problemas. y DataSets.
Si más de un usuario a la vez usa ese Hemos visto también algo del comporta- mayoría
comando obtendrán códigos iguales y al ir a miento frente a XML, un poquito de todo.
realizar las inserciones obtendremos errores Podríamos seguir profundizando en un futuro de aplicaciones
por claves duplicadas. Una estrategia alter- sobre implementaciones específicas sobre
nativa podría consistir en claves que no se cualquiera de estos objetos. Hay por ejemplo necesitan
repitan (campos autonuméricos o guids), una implementación del MVP en .NET Jesús
aunque también tienen importantes incon- López sobre un DataAdapter que contempla acceso a datos,
venientes, o tablas de códigos, cada proyec- algunos mecanismos más de tratamiento de
to y cada caso nos llevará a uno u otro la concurrencia. Trata por ejemplo cómo conocer ADO-NET
mecanismo. hacerlo mediante campos timestamp. Se
Otra cuestión que es muy importante tener pueden implementar objetos CommandBu- resulta
en cuenta son las transacciones anidadas. ilder específicos que generen comandos de
Es muy frecuente que unos procesos de acuerdo a los parámetros de nuestro equipo imprescindible
negocio invoquen a otros y que cada uno de desarrollo.
tenga su control transaccional. En SQL- Sin embargo creo que esta visión a vista de
Server, (igual que en otros motores transac- pájaro sobre ADO.NET y el detalle de algunos
cionales), el tema de las transacciones ani- asuntos como el tratamiento de imágenes van
dadas está contemplado, pueden invocarse a resultar muy útiles.

39 SOLO PROGRAMADORES
EL FUTURO

Sólo Programadores y
Mundo Linux en formato
electrónico
REVISTAS PROFESIONALES económicas, de movilidad o de lejanía, las revis-
tas en papel no suponen la mejor solución.
Por fin el deseo de muchos lectores Revistas Profesionales te anima a que envíes
va a hacerse realidad. En poco más un correo electrónico a rpsuscripciones@revis-
tasprofesionales.com, telefonees al 913 048 764
de un mes los contenidos de Sólo o envíes un fax al 913 271 303, indicando cuál
Programadores y Mundo Linux crees que sería el precio justo para la suscripción
digital anual (12 ejemplares) a una de las revis-
podrán descargarse desde la Red en tas. Independiente del lugar de residencia, por
formato PDF. unos pocos euros nuestras revistas serán accesi-
bles. El pago de la suscripción digital se realiza-
rá por los procedimientos habituales, y el sus-
criptor recibirá por correo electrónico un identi-
El mejor servicio para nuestros lectores ficador y una contraseña que le darán acceso a
descargar de la web las revistas a las que se ha
Queremos aprovechar, en este caluroso mes de suscrito. La suscripción digital también incluirá
agosto y a pocos días de iniciar una nueva tem- el acceso al material de apoyo que habitualmen-
porada, el inminente lanzamiento de una nueva te se distribuye en el CD-ROM.
plataforma web que servirá, entre otras cosas,
para ofrecer el servicio de descarga de los conte- Creciendo junto a la Sociedad de la
nidos de las revistas Sólo Programadores y Información
Mundo Linux mediante una suscripción específi-
ca para ello. Las posibilidades de crecimiento que se abren
El funcionamiento de dicho servicio será con una plataforma web de estas características
muy sencillo. El lector, después de formali- son inmensas. Esta plataforma web supondrá un
zar la correspondiente suscripción digital, nuevo activo para nuestras revistas Sólo
podrá descargar los contenidos de cada Programadores y Mundo Linux, un nuevo recurso
número de la revista a la que se haya suscri- que sabremos aprovechar al máximo, siempre
to (Sólo Programadores y/o Mundo Linux), buscando el beneficio de nuestros lectores.
en formato PDF. Este proyecto permitirá impulsar la creación de
Esta modalidad de suscripción permitirá a los comunidades virtuales entre nuestros lectores,
lectores, cualquiera que sea su lugar de residen- habilitar espacios web para el intercambio de
cia, disponer de los contenidos publicados de opiniones sobre los contenidos publicados y faci-
forma inmediata y almacenarlos, conservarlos litar la comunicación entre lectores, autores y
utilizarlos y desplazarlos sin los inconvenientes editorial.
que acarrea el formato en papel. Todos estos objetivos sólo pueden conseguirse
Esta iniciativa se enmarca en el afán de innova- con una apuesta valiente y decidida y, pese al
ción que siempre ha caracterizado a nuestras esfuerzo que supone levantar un proyecto como
publicaciones. Entendemos que uno de los pará- este, se está poniendo toda la ilusión y el empe-
metros que evalúan el servicio que ofrecemos a ño para que el resultado sea un orgullo para los
nuestros lectores es la facilidad de acceso a lectores que hacen posible que Sólo
nuestros contenidos, y creemos que con esta pla- Programadores y Mundo Linux se hayan mante-
taforma web ofreceremos un servicio muy espe- nido en una posición líder en sector a lo largo de
rado y deseado por muchos de vosotros para los tantos años, siendo las más veteranas y, con esta
que, por problemas de espacio o por cuestiones nueva iniciativa, las más innovadoras.

SOLO PROGRAMADORES 40
DISEÑO

Introducción
rodu ión all software
soft a
modernono orientado
or a o
a objetos
b etos
JAVIER SANZ ALAMILLO tra mostrándose como la panacea en la resolu-
ción de problemas. Otros, con un carácter más
En la actualidad, la variedad de técnico y menos ambicioso, se presentan como lo
métodos software para la que son y para lo que se pensaron, si bien estos
suelen ser los menos y desafortunadamente por
construcción de aplicaciones provoca lo general los más prácticos y útiles.
que decidirse por uno sin conocer las También en el mercado nos encontramos los
métodos que sin serlos, se aplican como si lo
bases de los mismos pueda generar fueran.
dudas e incertidumbre en la De todos modos, todos estos mecanismos para
la construcción de aplicaciones orientadas a
consecución de un proyecto. En este objetos se basan en unos conceptos que si bien,
sentido, es importante conocer cómo la bibliografía general no suele presentar por
centrarse más en otros asuntos principales,
encajan los principios teóricos de la resultan de gran interés para el desarrollador,
OOP y los métodos de desarrollo porque gracias a los mismos puede comprobar
la calidad de la metodología que esta aplican-
actuales. do, las facilidades y las carencias que contiene,
con lo que podrá tomar decisiones más afortu-
nadas y precisas. ¿Qué es el software orientado
Introducción a objetos? ¿Qué es un lenguaje orientado a
objetos? Todas estas cuestiones, triviales ini-
El objetivo de este artículo es mostrar al lector cialmente y ciertamente sin respuesta técnica
que existen formalismos sobre el software orien- para la mayoría de los desarrolladores, ayuda-
tado a objetos, y que los métodos y metodologí- rán al lector en las múltiples decisiones que
Las herramientas as que existen en el mercado y que se venden tiene que tomar para afrontar un proyecto soft-
como invenciones de los autores, no son mas que ware orientado a objetos.
que hay en el "implementaciones" de la teoría en hechos con-
cretos, por lo que cada autor/creador interpreta El software moderno orientado a objetos
mercado son los formalismos y los adaptada a sus necesida-
des. UML es un caso claro de ello. El lector debe de estar ciertamente cansado,
implementaciones En estas fechas, el mundo del software orientado aburrido de toda la documentación que existe
a objetos está sufriendo una auténtica revolu- en el mercado sobre la ingeniería del softwa-
concretas de la ción. Los más dispares métodos saltan a la pales- re que tras una lectura inicial acaba en cual-
quier sitio menos en el de trabajo.
teoría de la OOP Lamentablemente, no son muchos los libros
que ayudan en esta tarea y analizar esta cir-
cunstancia nos llevaría por otros caminos,
pero principalmente se debe a que la técnica
propuesta no ha sido bien presentada ni defi-
nida por ninguno de los auténticos gurús de la
informática mundial hasta escasos años.
Esta problemática condujo a que ciertos perso-
najes avezados se aventuraran sin ningún tipo de
complejos a escribir libros tratando conceptos
que no están claros ni para los propios creado-
Sitio web de la OMG.

SOLO PROGRAMADORES 42
DISEÑO
Introducción al software moderno orientado a objetos

res. Y esto pasa aún en la actualidad. Pregunten,


pregunten al trío Rational sobre las definiciones
que acordaron inicialmente para los casos de uso
en la archiconocida, utilizada y sobrevalorada
UML. ¡Vaya tres elementos, al final venden todo
a IBM! Y ya si nos ponemos espinosos, diferen-
cias entre agregaciones y composiciones, en fin,
es un buen ejemplo.
Por supuesto, el lector no tiene que esperar que
este artículo siente cátedra sobre los conceptos.
Ni mucho menos. El objetivo es mencionar, dar a
conocer que existe una estructura, una jerarquía,
unas bases para todos estos mecanismos que a
la mayoría de los desarrolladores no les acaba de
encajar. Desde el software orientado a objetos,
hasta los lenguajes que cumplen estas caracte-
rísticas, se van a mostrar los distintos conceptos
con la esperanza de que el lector, por fin, tenga diseño" y "descentralización". Se habla de IBM y el UML Resource Center.
un marco conceptual de por dónde se mueve el simplicidad de diseño, indicando que los mis-
software orientado a objetos y de quizás hacia mos deben serlo para mejorar la adaptación
dónde puede derivar. sobre la estructura compleja sobre la que
El software orientado a objetos seguramente se asocian. Se habla de descen-
En la actualidad, todos los proyectos software tralización si el software se construye bajo el
utilizan la orientación a objetos. Bien, pero concepto de módulos o servicios, por lo que
¿alguien me puede explicar brevemente y de un cambio afectará a un conjunto de módu-
forma sencilla qué implica esta afirmación? los y no provocará una reacción en cadena.
Vamos a intentarlo. z Reutilización, o la capacidad que tienen los
En la actualidad, se define el software orientado distintos elementos software para construir
a objetos como una "técnica" para la construc- aplicaciones diferentes.
ción de un software marcado por ciertas carac- z Compatibilidad, es la facilidad de combinar
terísticas, que lo llevan a cumplir los siguientes distintos elementos software, así hoy en día
objetivos: tenemos CORBA con EJB, etc.
z Corrección, entendiendo por ello como la z Eficiencia, se define como la capacidad de un
capacidad que tiene el software para realizar sistema software para exigir el mínimo de
las tareas requeridas según las espeficicacio- recursos (hardware, software) en la utiliza-
nes declaradas. Para conseguir este objetivo ción de sus tareas. Se aplica como sinónimo
se usan métodos condicionales, es decir, la de rendimiento.
aplicación de distintos niveles de aplicación z Portabilidad, es la capacidad de utilizar el
confía en la corrección de los anteriores. Así, software en diferentes entornos hardware y
un ejemplo de corrección es el hardware res- software.
pecto del sistema operativo, así respecto de z Facilidad de uso, cubre dos aspectos clara-
una compilación y finalmente una aplicación. mente diferenciados. Por un lado, implica que
Un desarrollador confía en que el compilador el software puede ser utilizado por distintos
no tiene errores, y a su vez el sistema opera- perfiles de usuario, definiéndose procesos de
tivo, etc. instalación, operación y supervisión. Por otra
z Robustez, siendo esta la capacidad del soft- parte, el diseño de interface de usuario debe
ware para reaccionar ante condiciones de asumir que el usuario no conoce la aplica-
excepcionales. Claro que esta parte tiene ción, y por tanto actuar en consecuencia.
muchas cuestiones, por ejemplo, ¿reacción z Funcionalidad, es el conjunto de posibilidades
apropiada? Ampliaremos este aspecto en las que proporciona un sistema. Se suele hablar
próximas líneas. aquí de "featurism", como la pérdida de faci- Los diseños
Estas dos ideas suelen agruparse en el término lidad de uso que implica la aplicación de pro-
"fiabilidad", por lo que tenemos que la correc- piedades versus cualidades. sencillos
ción me define el comportamiento y la robustez z Oportunidad, como la capacidad del software
me complementa con aquello que se sale fuera para ser utilizado cuando se desea. ¿Retrasos son más fáciles
de la corrección. Sigamos con los objetivos del en los lanzamientos de un producto?
software orientado a objetos… z Verificación, es la facilidad de comprobar el de adaptar
z Extensibilidad, como la capacidad de adaptar software.
el software a los cambios en las especifica- z Integridad, es la capacidad del software para
ciones. Se suelen definir dos principios para protegerse de modificaciones y accesos no
mejorar la extensibilidad: "simplicidad de autorizados.

43 SOLO PROGRAMADORES
DISEÑO

Tutorial sobre OO.


La noción de clase debe de ser suficiente para
definir cualquier tipo abstracto de datos, ¿qué
necesidad tenemos de interfaces Java?
Características de la programación orientada a
objetos
Partiendo del elemento básico, clase, se pueden
Se definen las declarar las siguientes propiedades deseadas
para obtener un lenguaje orientado a objetos:
excepciones z Ejecución basada en características, que defi-
ne que toda operación, cálculo o tarea se
como tiene que realizar mediante una característi-
ca (método) de una clase. Si una clase E tiene
mecanismo de una llamada a otra S, se dice que E es cliente
Entorno y lenguaje orientado a objetos de S y la invocación se define como "paso de
robustez mensajes".
Definida ya la técnica de la orientación a z Ocultación y encapsulamiento, por lo que de
objetos, veamos qué características deberían detallan dos tipos de características, las inter-
ofrecer los entornos orientados a objetos para nas, identificadas cuando una requiere de otra
ser considerados como tales. El lector obser- y las externas, definidas a los clientes,
vará que los entornos actuales dejan cierta- ¿Interfaces Java? Gracias a esta distinción, se
mente que desear en algunas propiedades, y puede definir la ocultación como el mecanismo
es ahí justamente, donde por ironías de la que hace que ciertas características no estén
vida, se obtienen todas su debilidades: disponibles para los clientes. Esta propiedad
z Ausencia de discontinuidades, esto es, que está íntimamente ligada por tanto a la compa-
en todo el ciclo de desarrollo software se tibilidad y la reutilización. De ahí se concluye
aplican métodos de diseño, herramientas que la comunicación entre clases debe de estar
orientadas a objetos, etc, de modo que las estrictamente limitada, encapsulada, luego, no
discontinuidades entre las distintas activi- existen variables globales ni similares. El inter-
dades debe ser mínima. cambio de información se realiza mediante
z Clases, la programación orientada a objetos métodos, características o la herencia. ¿Rompe
se basa en la noción de clase. Sin entrar la herencia el encapsulamiento?
con detalle, una clase es un elemento soft- z Excepciones. Una excepción es el resultado de
ware que describe un tipo abstracto, siendo una llamada a una característica que termina
su implementación total o parcial. anormalmente. Claro, ¿qué significa anormal-
Definamos "tipo abstracto de datos" como mente?, por ejemplo, ¿el final de fichero es una
un conjunto de operaciones, características excepción? Cuando uno lee de un fichero, lo
y propiedades. Así, en Java la noción cen- normal es que este tenga un límite, un fin.
tral del lenguaje es la clase. El objetivo de las excepciones es producir soft-
z Aserciones, las propiedades de un tipo abs- ware robusto, fiable. Todo lenguaje debe ofre-
tracto se describen mediante aserciones. cer mecanismos de excepciones para recupe-
Éstas deben de ser independientes de la rarse de situaciones anormales, inesperadas. Se
implementación que se les asigne. Se descri- pueden definir dos tipos principales de excep-
ben como precondiciones, postcondiciones e ciones, de recuperación y de resurrección.
invariantes. Aquí los distintos elementos z Comprobación estática de tipos. Cuando se
demuestran la relación corrección y robustez. llama a un método de un objeto, ¿cómo se
Las clases y los módulos averigua, comprueba que el objeto puede
La orientación a objetos es básicamente una téc- atender esa petición? El lenguaje consta de
nica de arquitectura porque afecta a la estructu- comprobación de tipos y mediante unas
ra modular del software, por lo que se define una reglas de declaración de tipos y compatibili-
Existe clase como unidad modular básica. dad, se garantiza la seguridad de los tipos de
En un enfoque más estricto se suele declarar que ejecución que el software acepta. De aquí se
la posibilidad de las clases deben de ser los únicos módulos, por lo puede definir un lenguaje como fuertemente
que, de estas dos afirmaciones podemos obtener tipado, tipado, etc. Java es un lenguaje tipa-
identificar tipos las siguientes propiedades: do, relativamente fuerte, pero no tanto como
z No hay ni existe noción de programa ADA o Eiffel. Pero, ¿qué elemento realiza esta
en ejecución principal. tarea? Existe definido un verificador de tipos
z No existen subprogramas, rutinas como uni- estáticos, que garantiza que no haya ningún
dades modulares independientes. ¿Se necesi- error del estilo: característica no disponible".
tan por tanto los paquetes Java? En Java, hay reglas entre interfaces, clases,
z La definición de agrupamiento de clases para paquetes, herencia. Las reglas básicas de un
su uso se denominaría clusters. verificador son:

SOLO PROGRAMADORES 44
DISEÑO
Introducción al software moderno orientado a objetos

1 ) Todo objeto que invoca a otro declara z Generalización restringida. La combinación


explícitamente su tipo antes de utilizarse. de la generalización y de la herencia determi-
2 ) Toda llamada a una característica debe na la generalización restringida mediante la
estar disponible cumpliendo la regla de cual se especifica una clase con un paráme-
ocultación. tro genérico que representa no un tipo abs- Existen entornos
3 ) La asignación y paso de parámetros esta- tracto sino a un tipo arbitrario (¿lo podemos
rán sometidos a reglas de compatibilidad considerar como otro tipo más?). y lenguajes que
(agrupación de tipos, herencia, etc.). z Redefinición. Cuando una clase hereda de
z Generalización. Para que se puedan realizar otra puede cambiar la implementación o pro- no cumplen
comprobaciones de tipos se deben poder piedades de algún método heredado, es decir,
definir clases genéricas parametrizables redefinirse. todas las pro-
con tipos arbitrarios, lo que se denominan z Polimorfismo, definido como la capacidad que
plantillas. En Java no se han definido aun tiene una "entidad" (nombre que se le asigna piedades de la
los procesos de generalización, aunque a un valor durante una ejecución, lo cual es
parece que están ya a punto de añadirlo a una generalización del concepto de variable) OOP
la especificación del lenguaje. Casi 10 años para poder conectarse a objetos de varios
después de su creación, no está mal. El len- tipos. En un entorno estático la comprobación
guaje intenta parchear está carencia requerida se controla por el mecanismo de
mediante interfaces. Sin comentarios. Este herencia. ¿Pero qué ocurre con el mecanismo
tipo de comprobación o capacidad se deno- de downcasting? O necesitamos un casting
mina no restringida. Una facilidad restrin- explícito o se añaden complejos mecanismos
gida de generalización determina el con- automáticos de actuación. Todo esto nos lleva
cepto de "herencia". ¿A que nunca le habí- a definir…
an dicho que la herencia era esto y sólo z Sobrecarga. La sobrecarga es un mecanismo
esto, y no el discurso de la clase base y la que amplía las posibilidades sobre la invoca-
clase derivada? ción a características. Se distinguen dos tipos
z Herencia. Existen variadas clasificaciones, de sobrecarga:
tipos de herencia. Así, se tiene: a ) La sobrecarga sintáctica, es la capacidad
1 ) Herencia simple. en las que el desarrollo de asociar más de un significado a un
de clases implica variantes mínimas de mismo nombre. Así se tiene la sobrecarga
unas a otros, por lo que se requiere de un de variables, en diferentes módulos se uti-
mecanismo de clasificación que se deno- lizan con el mismo nombre, o la sobrecar-
mina herencia. Se dice que una clase ga de métodos, cuando los métodos tie-
hereda de otra si incorpora todas las nen el mismo nombre, pero distinta signa-
características de la otra más las suyas ture (definición completa, tipo, número de
propias. Se les etiqueta de base, derivada, parámetros y excepciones... ¿y el valor de
padre, hija, superior, inferior, ascendente, retorno, la covariante?). Se define aquí el
descendente, etc. principio de no engaño, por lo que dife-
2 ) Herencia múltiple. A veces se suelen com- rentes semánticas deben reflejarse en
binar varias abstracciones en una deter- diferentes textos, es decir, aplicar distintos
mina, por ejemplo, supongamos una abs- métodos con objetivo de mejorar la com-
tracción hijo que hereda de padre y madre. presión del software y minimizar el riesgo
Necesitamos de una comprobación que se de errores. También se tiene la sobrecarga
aplique mediante herencia múltiple de de operadores, que utiliza operadores para Tratamiento de la herencia múltiple
clases. Esto implica problemas técnicos,
conflictos de nombres. Para resolver estos
dilemas, se procede al simple cambio de
nombre.
3 ) Herencia repetida. La herencia múltiple
puede implicar herencia repetida.
Cuando existe una clase base superior
única, de la que derivan dos hijas, y estos
a su vez, en conjunto son clases base de
otra de tercer nivel hija, el tercer nivel
constará de múltiples características
repetidas. Los lenguajes deben resolver
estas colusiones mediante reglas, deter-
minado el ámbito de acceso. Se suele
determinar a su vez la herencia repetida
discreta como la determinada por una
relación de transitividad directa.

45 SOLO PROGRAMADORES
DISEÑO

realizar distintas funciones. ¿Es estén organizados en arquitecturas estables.


necesario? Todos estos requerimientos redefinen el concep-
b ) Ligadura dinámica o sobre- to de módulo. Un modulo tiene como objetivo
carga semántica. Partiendo de los construir elementos autónomos basados en
conceptos de redefinición y poli- estructuras simples y coherentes. Pero, ¿cómo se
morfismo tenemos la ligadura integran los módulos en la orientación a obje-
dinámica (LD). Cuando se llama a tos?
una característica mediante una Criterios de modularidad
entidad base polimórfica, cuyos Un diseño es modular si cumple las siguientes
descendientes han redefinido propiedades:
algún método, debe de existir un z Descomposición modular, si el problema soft-
mecanismo de invocación del ware se divide en un número determinado de
La JVM respecto a medios avanzados. método llamado para el tipo derivado, con subproblemas menos complejos, estos se
independencia de la declaración de la interconectan de forma sencilla y son inde-
entidad. Esto se denomina LD. Gracias a la pendientes, por tanto, pueden ser reutiliza-
LD, se evita tener que hacer manualmente dos. Es un proceso iterativo, de subdescompo-
comprobaciones de tipos. siciones.
z Identificación de tipos en tiempo de ejecu- z División de tareas, el proceso se ha realizado
ción (RTTI). La LD nos ofrece unas posibilida- bien si éste se puede asignar a distintos gru-
des, pero no es completa. ¿Qué ocurre cuan- pos de trabajo.
do no sabemos nada sobre el tipo del objeto z Cohesión temporal. ¿Cómo se realiza la ini-
a recibir? En este caso se requiere de un acce- cialización de los módulos? En un método
so al objeto que sea seguro, que no viole las orientado a objetos cada módulo es responsa-
restricciones sobre los tipos. Es aquí donde ble de la inicialización de sus estructuras.
tenemos la RTTI, como un mecanismo que z Composición modular. Se dice que un diseño
determina si se puede asociar una entidad satisface la composición modular si en la cre-
con un objeto siendo el tipo determinado ación y uso de nuevos elementos se combinan
estático. con otros para producir nuevos sistemas
z Clases y características diferidas. ¿Qué pasa si resultantes, diferentes a los que fueron ini-
la característica a invocar no esta redefinida? cialmente creados.
Es necesario definir un tipo de clase cuyas z Compresibilidad modular, define que el soft-
características pueden o no estar implemen- ware debe de crear módulos tal que se pue-
tadas. Incluyen características y aserciones den entender de forma independiente y en el
para definir sus propiedades pero su imple- peor de los casos, examinar un poco otros
mentación se deja a las clases descendientes, módulos. ¿Mantenimiento?
por tanto: z Continuidad modular, determina que un cam-
1. Una "clase diferida" o abstracta es aquella bio pequeño en la especificación provoca sólo
que especifica sus características, propie- cambios en un módulo o en un conjunto
dades pero no las implementa totalmente. reducido de módulos. Así tenemos las cons-
Las clases abstractas tienen como misión tantes en los programas, definir una única
representar los aspectos esenciales, las notación de acceso a los objetos.
características principales del sistema z Protección modular, que determina que una
dejando que las clases descendiente situación anormal en un módulo debe afectar
implementen los detalles. sólo a dicho módulo o en el peor de los casos,
2. Las clases que implementan todas sus propagarse a módulos vecinos. Así se tienen
características se denominan "clases efec- mecanismos como aserciones y excepciones.
tivas". Este criterio aborda la propagación sin definir
z Recolección de memoria. Un lenguaje orien- su tratamiento, por lo que hay que verificar la
tado a objeto debería de hacer posible la ges- entrada de datos en el origen de datos.
tión automática de la memoria. La implemen- Reglas de modularidad
La recolección tación debe de ofrecer un administrador De los criterios descritos se obtienen las reglas:
automático capaz de llevar a cabo esta tarea. z Correspondencia directa, por lo que debe
de basura existir una correspondencia clara y directa
La modularidad entre la estructura del problema (modelo) y la
es hoy en día estructura de la solución software. Por tanto
La modularidad (extensibilidad y reutilización) es continuidad y descomposición.
indispensable requerida en arquitecturas flexibles, autónomas. z Pocos canales de comunicación, los módulos
La programación modular genera programas deben comunicarse con el menor número de
como resultado de subrutinas, etc., que no per- módulos, mejor cuando menos canales de
miten la extensibilidad y reutilización a menos comunicación.
que se gestionen de forma autocontenida y z Intercambio de información. La comunicación

SOLO PROGRAMADORES 46
DISEÑO
Introducción al software moderno orientado a objetos

entre módulos debe de intercambiar la menor Por tanto, un fracaso es un fallo,


información posible. y de ahí que una excepción tam-
z Comunicación explícita. La comunicación bién es a menudo un fallo, pero
entre módulos debe de ser clara y perfecta- no si es posible recuperarse del
mente definida, puesto que determina el aco- mismo. Como lema se obtiene
plamiento de éstos. que un fracaso de una rutina
z Ocultación de información. Se debe diferen- causa una excepción en quién lo
ciar claramente en un módulo la parte públi- llama.
ca y la parte privada. Tratamiento de excepciones
z Criterio de continuidad, por lo que un cambio Las excepciones se suelen clasifi-
en la parte privada del módulo no debe afec- car en disciplinadas e indiscipli-
tar a la parte pública y por tanto al resto del nadas:
módulo. z Las excepciones indisciplinadas, por ejemplo, Utilizando la herencia múltiple
las de Java, son las que se definen como aco- con Eiffel.
Por fin, modulo orientado a objetos pladas en el código (se insertan mediante
try/catch/finally) y pueden ayudar a propagar
La construcción de software orientado a objetos el error, por lo que rompen la protección
es un método de desarrollo software que se basa modular.
en el uso de módulos deducidos de los tipos de z Las excepciones disciplinadas, que se clasifi-
objetos que se manipulan, en lugar de basarse en can en:
las funciones. Como nota al lector, ésta es la idea 1 . De reintento, por lo que intentan cambiar
más importante en veinte años de orientación a las condiciones que condujeron a la
objetos, y es una pena, porque la mayoría de los excepción y ejecutar de nuevo la rutina
desarrolladores actuales aún no lo entienden y lo desde el comienzo.
que es peor, no quieren entenderla. 2 . Fracaso (pánico organizado), trata sobre
Se deduce un lema importantísimo que tira a la cómo limpiar el entorno, terminar la lla-
papelera un gran porcentaje de diseños: "No pre- mada e informar sobre el fallo a quién
guntes qué hace el sistema, pregunta a qué se lo hizo la llamada.
hace." Objetos, claro. 3 . Respuesta justificada, cuando la excep-
ción es como resultado de una señal del
Sobre las excepciones sistema operativo, se determina si la
excepción es o no dañina y se retorna a la
Antes de finalizar, detallaremos más sobre este ejecución desde donde comenzó, por
elemento que parece tan novedoso a los des- ejemplo, ¿disco lleno?
arrolladores, las excepciones. ¿Alguien utiliza Existe el denominado "principio de simplicidad
con provecho las excepciones en Java? de una excepción" que determina que todo pro-
Informalmente, una excepción es un suceso cesamiento que se haga en una cláusula de res-
anormal que rompe la ejecución de un sistema. cate (en Java, bloque catch/finally) debe de ser
Bien, esto es algo claro. Pero no es muy preciso. simple y centrarse en el único objetivo de volver
Tenemos que definir algunos términos para lle- a poner al objeto sobre el que se ejecuta la
gar a nuestro destino, por lo que tenemos: característica en un estado válido, estable, per-
z Éxito y fracaso. Una llamada a una caracte- mitiendo así un posible reintento.
rística tiene éxito si termina su ejecución en Una reflexión, ¿las excepciones son verdadera-
un estado en el que satisface el contrato. Por mente objetos?
tanto, fracasa si no tiene éxito.
Así, podemos volver a describir excepción como Conclusiones
un suceso en tiempo de ejecución que puede
causar que una característica fracase. Pero tene- El lector que haya tenido en sus manos múlti-
mos que seguir aún más detalladamente. ples libros sobre la ingeniería del software u
Definimos contrato de una rutina como aquello orientación a objetos es probable que este La modularidad
que debe satisfacer la postcondición y la inva- desconcertado. Si bien todas estas definicio-
riante de la clase (y no debe causar una señal del nes siempre han estado al alcance de todos, como elemento
sistema operativo). Se habla por consiguiente de: las simplificaciones, los resúmenes, el aisla-
z Error, como decisión equivocada durante el miento de determinados conceptos que clave en la
desarrollo software. supuestamente no caben en la práctica
z Defecto, es la propiedad de un sistema soft- (¿quién decide eso?) ha hecho que los funda- evolución del
ware que puede causar que el sistema se apar- mentos sobre orientación a objetos se estén
te del comportamiento que tiene previsto. revelando actualmente como una herramienta software
z Fallo, es el evento de un sistema que lo parta de producción, mucho tiempo después de la
de su comportamiento previsto durante una supuesta puesta en práctica por la gran mayo-
de sus ejecuciones. ría de los desarrolladores.

47 SOLO PROGRAMADORES
ALGORITMOS

Direct3D 9.0 avanzado (II)


ARISTÓTELES DOMÍNGUEZ GONZÁLEZ transformación. A partir de los vértices que reci-
be en la entrada, se encarga de calcular y aplicar
La evolución de la arquitectura de las matrices de transformación, es decir, la
matriz de mundo, de vista y de proyección, sobre
Direct3D ha ido acompañada de un los vértices. El motor de transformación también
crecimiento en el número de realiza los cálculos para aplicar iluminación a
cada vértice. Podríamos decir que ésta es la sec-
funciones fijas y programables ción que engloba las funciones básicas dentro de
acorde a las posibilidades de los Direct3D. Todas las técnicas avanzadas las
encontramos englobadas en la tubería progra-
últimos procesadores gráficos. mable. La tubería programable está basada en
un modelo procedural que permite una sintaxis
más generalizada para las operaciones comunes.
Introducción Es decir, si un modelo de trabajo está basado en
funciones fijas, tiene que ir incrementando el
En la arquitectura de las tarjetas graficas acele- número de funciones, modos e información adi-
radoras, es común implementar dos técnicas cional a medida que aumenta la potencia del
para optimizar el rendimiento de los gráficos hardware. En un modelo programable sólo es
generados. La primera técnica consiste en cana- necesario conocer la arquitectura del sistema y
lizar los algoritmos a ejecutar o pipelining y la especificar el algoritmo que necesitemos para
segunda técnica consiste en realizar los cálculos obtener los mismos resultados que con funcio-
en procesos paralelos. Si nos centramos en la nes fijas. Es obvio que la diferencia está en que
canalización de los algoritmos, el flujo de proce- un modelo de trabajo programable es más versá-
so de Direct3D conocido como pipeline o tube- til. Direct3D permite que se trabaje con los dos
ría, se puede ver como un conjunto de algorit- modelos, pero está claro que la tubería progra-
mos que se aplican sobre vértices y primitivas. mable ofrece mejores resultados. En el artículo
El propósito principal de la tubería de Direct3D anterior ya se comentaron técnicas que están
es convertir los datos geométricos que se le incluidas en la tubería programable como el
suministran en imágenes que serán renderizadas Bump Mapping o el Environment Mapping. En
por la tarjeta de video del PC. A su vez, la tube- este artículo comentaremos la división en dos
ría se divide en dos secciones, la tubería de fun- que se produce en la tubería programable, la
ción fija y la tubería programable. tubería de Vertex y la tubería de Píxel.
En la arquitectura de Direct3D, la tubería de fun-
ción fija se puede considerar como el motor de Vertex Pipeline
Recordamos que un vertex es un conjunto de
números en coma flotante que representan un
punto en un entorno, que en nuestro caso será
en tres dimensiones. De manera simplificada,
mediante la tubería de Direct3D, un vertex es
procesado para calcular cuál será su posición
como píxel en la pantalla.
La tubería de Vertex permite aplicar diferentes
efectos en la etapa de proceso de un vertex. Las
técnicas empleadas son programadas y calcula-
das a nivel de vertex, con lo que debemos de
tener en cuenta que los cálculos realizados se
Figura inicial y final. harán antes de que se obtenga el valor del píxel

SOLO PROGRAMADORES 48
ALGORITMOS
Direct3D 9.0 avanzado (II)

LISTADO 1 Declaración del vertex


D3DVERTEXELEMENT9 shader[] =
Todas las técnicas
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
avanzadas
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
{1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 },
las encontraremos
{1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 1},
D3DDECL_END()
englobadas
};
en la tubería
que será renderizado. Estos efectos se pueden
programable
Posición = pos_uno*(1.0-factor_tween)+pos
programar para conseguir diferentes resultados _dos*factor_tween
a partir de una técnica básica. Algunas de las
técnicas que podemos aplicar son Displacement Con esta fórmula se calcula la posición de un
Mapping, Vertex Blending o Point Sorites (partí- vértice y su normal a partir de la posición ini-
culas). cial (pos1), la posición final (pos2) y el factor
Geometry Blending, Vertex Tweening de interpolación entre las posiciones (fac-
La técnica Geometry Blending permite realizar tor_tween). El primer paso para activar esta
cálculos entre dos vertex para obtener valores técnica es ajustar el valor D3DRS_VERTEX-
intermedios. Cuando esta técnica se aplica sobre BLEND a D3DVBF_TWEENING. Es prudente
secciones de una figura o sobre figuras comple- comprobar que la tarjeta grafica soporta este
tas, se pueden obtener los puntos intermedios modo comprobando el flag D3DVTXPC
entre secciones o podemos obtener las figuras APS_TWEENING. Para usar esta técnica es
intermedias entre dos figuras. necesario construir una estructura de vertex
Por ejemplo, si estamos dibujando el brazo de que incluya una segunda posición y una
una figura nos permite obtener la difuminación segunda normal. Esto se realiza construyendo
entre articulaciones y que no aparezcan seccio- una declaración que gestione la estructura de
nes rotas de la figura. A esta técnica se la cono- vertex creada anteriormente. En el listado 1 se
ce como Vertex Blending. Este tipo de efecto se puede estudiar la declaración del vertex.
puede aplicar de diversas maneras en Direct3D. A continuación, debemos crear la declaración del
Para conocer su funcionamiento estudiaremos vertex shader usando el método apropiado. El
una de las aplicaciones de este efecto denomi- paso siguiente es indicar la declaración del ver-
nado Vertex Tweening. Este es un efecto que se tex shader que usaremos para trabajar. Después
usa en animación básica de figuras. En nuestro se activará el estado de render que permitirá que
caso, en vez de generar la animación mediante se realice Vertex Tweening, para lo que se indi-
técnicas tradicionales dibujando una secuencia cará el factor de tween y la cadena fuente de
de figuras con un pequeño cambio en su postu- vértices a procesar. Cuando tenemos varias figu-
ra para simular movimiento, se utilizará un pro- ras a procesar, tendremos varias cadenas de vér-
grama de diseño. Cada modelo contiene una tices a indicar. No debemos olvidar que mientras
pose de la acción. El proceso comenzaría por la esté activado el efecto de Tweening, para cual-
lectura de cada una de las poses y se generarían quier llamada a una función de render, automá-
las poses intermedias usando interpolación line- ticamente se le aplicará el efecto de Tweening.
al entre dos figuras, o dicho de otra manera, Gracias a dicha técnica es posible implementar
entre dos grupos de vértices. Este proceso provee efectos de animación entre figuras sin necesidad
un grado de optimización elevado ya que el pro- de realizar grandes esfuerzos en programación.
gramador puede decidir el número de pasos Este efecto se puede usar para estudiar procesos
intermedios que se usarán para desarrollar la de transformación entre figuras sin necesidad de
animación. Esta técnica aporta al diseñador o
dibujante la ventaja de que sólo tiene que gene-
rar las secuencias básicas y el programa realiza-
ra el resto y es muy fácil de implementar para el
programador. También tiene sus desventajas,
como la necesidad de consumir memoria para
almacenar todas las poses de cada modelo que
se vaya a animar. Además, esta técnica no es fle-
xible ya que si queremos realizar cambios en las
animaciones durante la ejecución del programa,
tendríamos que modificar los modelos cargados
previamente.
Para calcular la diferencia entre dos figuras se Ejemplo de Vertex Tweening entre
utiliza la formula de cálculo de una posición: dos figuras.

49 SOLO PROGRAMADORES
ALGORITMOS

estar calculando matrices de transformación o mos realizar un efecto de transición, donde una
aplicar scripts de animación. También es útil imagen va desapareciendo gradualmente y va
para entornos virtuales, como el de videojuegos, apareciendo otra, seguiríamos los pasos que
donde tengamos figuras que realizan siempre los vamos a comentar. En principio, renderizariamos
mismos movimientos, con lo que el proceso gana las dos imágenes. A continuación, usaríamos el
Stencil Buffer en rendimiento ya que es el procesador grafico el buffer Stencil para controlar los píxeles de cada
encargado de calcular los cambios en la figura. imagen que se dibujarían en la superficie de des-
hace referencia a Si el lector estudia el material de apoyo adjunta- tino. A la hora de definir el proceso de transición,
do en el CD-ROM comprobará la facilidad de se podrían definir una serie de máscaras para el
un nuevo buffer aplicar esta técnica. buffer Stencil y copiarlas sucesivamente en el
buffer. Otra posibilidad podría ser definir una
que incorporan las Píxel Pipeline máscara base para la primera imagen que se iría
modificando gradualmente.
tarjetas gráficas La tubería de píxel se encarga de aplicar diferen- Para realizar este efecto, al principio de la
tes efectos en la etapa de proceso de un píxel. transición se deben fijar las funciones que
mas actuales Las técnicas empleadas son programadas y cal- indican el comportamiento del buffer Stencil
culadas a nivel de píxel, con lo que debemos de y de la mascara, con lo que se indica que la
tener en cuenta que los cálculos se realizarán mayoría de los píxeles de la imagen inicial
cuando se obtenga el valor del píxel que será pasan el test del buffer Stencil. Esto permite
renderizado. La tubería de píxel sigue esta que la imagen inicial ocupe prácticamente
secuencia de operaciones: toda la superficie dibujada. Obviamente, la
1 . Ajuste de triángulos. mayoría de los píxeles de la imagen final no
2 . Aplicación de Pixel Shader. Esta operación pasan el test, con lo que no se dibujarían. El
reemplaza a la aplicación de formatos fijos de proceso continuaría en sucesivos frames,
multitextura. Se realiza la aplicación de colo- modificando la mascara que se ha estableci-
res, coordenadas de textura, texturas, trans- do en el buffer, con lo que poco a poco, van
parencias, etc. disminuyendo el numero de píxeles de la pri-
3 . Niebla mera imagen que pasan el test. De esta
4 . Chequeo de valores alfa, stencil, profundidad. manera iría desapareciendo la imagen inicial
5 . Transparencias en el Frame-Buffer. e iría apareciendo la imagen final. Este efec-
En el artículo del mes anterior ya abordamos el to se podría aplicar también para hacer fun-
estudio de técnicas avanzadas que se aplican en didos o "fades", ya que podríamos usar el
esta tubería de proceso como Bump Mapping y buffer Stencil para realizar una transición
Environment Mapping. A continuación, analiza- desde un fondo negro o blanco a una imagen
remos más técnicas que se pueden usar en la final lo que se conoce también como "fade
tubería programable de píxel. in", o al revés, desde la imagen, hacer una
Stencil Buffer transición a un fondo en blanco o negro, lo
Al usar la expresión Stencil Buffer estamos que se conoce como "fade out".
haciendo referencia a otro buffer que incorpo- Otro efecto que se usa es aplicar siluetas y líne-
ran los últimos modelos de tarjetas graficas. as de resalte sobre figuras en tres dimensiones.
Podríamos decir que el Stencil Buffer es otro Si queremos conseguir que una figura aparezca
plano que contiene información de píxeles. La remarcada con una línea de resalte, aplicamos
funcionalidad básica de este buffer es la de una máscara a la figura con su mismo diseño
enmascarar píxeles en una imagen. Para usar pero con un tamaño menor. De esta manera
este buffer se deben establecer unas funciones conseguimos que aparezca sólo una línea que
de control de una plantilla y de enmascara- marca la forma de la figura. Si ahora rellena-
miento, que establecen un test de control que mos esa área de un color, conseguimos que
se realizará sobre la imagen a renderizar. Según aparezca nuestra figura con una línea de resal-
sea el tipo de test, se dibujarán los píxeles de la te, dando el aspecto que tienen las figuras que
imagen. Al poder controlar las funciones de aparecen en películas de dibujos animados. Si
stencil y el tipo de enmascaramiento, se pueden lo que queremos conseguir es la silueta de una
realizar diversos tipos de efectos especiales figura, lo que haríamos seria aplicar una más-
como los que se emplean en video para realizar cara con el mismo diseño que el de la figura y
diferentes transiciones entre escenas o se pue- el mismo tamaño. Si este espacio lo rellenamos
den añadir imágenes fijas sobre imágenes ani- de color, conseguimos la silueta de la figura.
madas. Otro efecto a aplicar puede ser el tratar Estos son varios ejemplos de cómo usar el buffer
una escena en la que se van a representar obje- Stencil. Ahora nos centraremos en estudiar el
tos con reflejos o que al iluminar objetos apa- proceso de programación del uso del buffer
rezcan también sus sombras. Stencil y profundizaremos en tres ejemplos,
Analicemos algunos efectos para ver cómo se enmascarar una escena 3D con una imagen fija,
podrían realizar con el buffer stencil. Si quisiéra- creación de reflejos y creación de sombras.

SOLO PROGRAMADORES 50
ALGORITMOS
Direct3D 9.0 avanzado (II)

LISTADO 2 Aplicando un marco a la escena


//PRIMERA PARTE
//Se desactiva el zbuffer. No se escribe nada en el zbuffer o en el frame buffer
device_d3d->SetRenderState(D3DRS_ZENABLE,FALSE);
device_d3d->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
device_d3d->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
Enmascarar una
device_d3d->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);
device_d3d->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
escena 3D con
//Test sobre el canal alpha
device_d3d->SetRenderState( D3DRS_ALPHATESTENABLE,TRUE);
una imagen fija es
device_d3d->SetRenderState( D3DRS_ALPHAREF,0);
device_d3d->SetRenderState( D3DRS_ALPHAFUNC,D3DCMP_GREATER);
un recurso muy
//Se activa el buffer stencil y se establece función de comparación
device_d3d->SetRenderState( D3DRS_STENCILENABLE,TRUE);
utilizado por los
device_d3d->SetRenderState( D3DRS_STENCILFUNC,D3DCMP_ALWAYS);
device_d3d->SetRenderState( D3DRS_STENCILPASS,D3DSTENCILOP_INCR);
programadores
//SEGUNDA PARTE
de vídeojuegos
device_d3d->SetRenderState( D3DRS_STENCILREF,1);
device_d3d->SetRenderState( D3DRS_STENCILFUNC,D3DCMP_EQUAL);
device_d3d->SetRenderState( D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);

//TERCERA PARTE
device_d3d->SetRenderState( D3DRS_STENCILREF,0);
device_d3d->SetRenderState( D3DRS_STENCILFUNC,D3DCMP_EQUAL);
device_d3d->SetRenderState( D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);

Programación del Stencil Buffer comienza limpiando el zbuffer y el buffer Stencil.


El proceso comienza estableciendo el test que se En el primer paso, la máscara se dibuja desacti-
va a realizar sobre los píxeles. El test se realiza- vando el zbuffer y activando los estados de ren-
rá para cada píxel de la superficie de render der. Con estos estados, impedimos que se escri-
usando tres valores: el valor correspondiente en ba información en el zbuffer y en el frame buf-
el buffer Stencil, un valor de referencia del fer. Establecemos un test sobre el canal alpha
Stencil y un valor de máscara de Stencil. Si se donde el valor de referencia es el cero y estable-
supera el test, se realiza la acción correspon- cemos una función de comparación donde cada
diente. Los pasos que resumen el proceso son los píxel tiene que ser mayor que el valor de refe-
siguientes: rencia. Activamos el buffer Stencil y establece-
1 . Se realiza una operación AND del valor de mos que la función de comparación siempre se
referencia del Stencil con el valor de la más- cumpla y para el caso en el que la función se
cara de Stencil. cumpla, vaya incrementando su valor. Estas ope-
2 . Se realiza una operación AND del valor del raciones se pueden estudiar en el listado 2 (pri-
buffer Stencil del píxel que está tratando con mera parte).
el valor de la máscara de Stencil. A continuación, renderizamos un polígono en el
3 . Se comparan los dos resultados usando una buffer Stencil con una textura aplicada que es la
función de comparación establecida. Si el test
para el píxel se pasa, es dibujado, de otra Escena con un marco
aplicado.
manera es ignorado. Como ya se ha comenta-
do, en un programa podemos establecer la
función de comparación, la máscara de
Stencil y el valor de referencia del Stencil.
Contador
El primer ejemplo que vamos a abordar es el que
se usa para establecer un marco o un contador
superpuesto a la escena. Haciendo un resumen
de su funcionamiento, el programa en el primer
paso dibuja una mascara en el buffer Stencil. En
el segundo paso se dibuja la imagen que va a
permanecer fija y que es el contador o marco
que establecemos en la escena y en el tercer
paso se dibuja la escena completa. El proceso

51 SOLO PROGRAMADORES
ALGORITMOS

Escena con reflejos de la superficie reflectante en el buffer Stencil.


y transparencias. El buffer Stencil se usaría como una máscara y
se renderizaría la escena otra vez, pero ahora la
geometría de la escena se habría trasladado y se
habría renderizado sobre la superficie reflectan-
te donde aparecería como el reflejo. Para mos-
trar la escena completa, primero se renderizaría
la escena sin reflejos y después la superficie
reflectante con el reflejo calculado. Para calcular
el reflejo se usaría un plano de recorte para que
sólo los objetos que están sobre la superficie
reflectante aparezcan. Es importante recordar
que a la hora de aplicar el reflejo en el buffer
stencil, debemos cambiar el orden de renderiza-
do de los polígonos ya que el reflejo está al revés
máscara. De esta manera establecemos un de la figura original, como es obvio. En el listado
marco blanco con un fondo negro. El segundo 3 se puede estudiar todo el proceso.
paso establece una función de comparación Sombras
donde el píxel debe ser igual que el valor de refe- Para la creación de sombras comentaremos una
rencia. El valor de referencia se establece a uno. técnica de generación que permite crear som-
La acción que se establece si la comparación es bras en tiempo real. A partir de objetos comple-
válida es la de mantener el valor del buffer jos se usa un método modelador que nos da
Stencil. Estas operaciones también se pueden como resultado las sombras. En cada frame o
estudiar en el listado 2 (segunda parte). Como el cuando en una escena los objetos o las luces se
marco que está establecido en la máscara es de mueven, se calculan los volúmenes de cada som-
color blanco o valor uno y al resto del buffer se bra. Si se llama volumen de sombra, es debido a
le aplica un test sobre el canal alpha evaluando que una sombra es un objeto 3D calculado a par-
sólo el color negro, lo único que se dibuja en este tir del objeto original y de la luz que lo ilumina,
paso es el marco, permaneciendo el resto trans- pero del que sólo se muestra su silueta. Lo que se
parente. En el tercer paso, la función de compa- hace es moldear las sombras en un plano.
ración y de acción es la misma que en el segun- Comenzamos el proceso a partir de la silueta
do paso. Estas operaciones se pueden estudiar en donde se detectan los filos. Esto se puede reali-
la tercera parte del listado 2. Sólo cambia el zar debido a que las normales de los polígonos
valor de referencia que se establece a cero. De adyacentes tendrán normales opuestas con res-
esta manera el test se cumple para la parte de la pecto al vector de la fuente de luz. Así obtene-
escena que está en negro, con lo que la escena mos una lista de filos, es decir, la silueta, que es
queda encuadrada dentro de un marco. Este tipo el resaltado del objeto 3D lejos de la fuente de
de efecto se usa en determinados videojuegos luz. Este objeto calculado es conocido como un
para mostrar los contadores que informan de los volumen de sombra, donde cada punto dentro
niveles de vida y energía que le quedan al perso- del volumen pertenece a la sombra. Con el volu-
naje protagonista. men de sombra calculado, lo renderizamos dos
Reflejos veces en el buffer Stencil. Primero, sólo se ren-
El buffer Stencil se puede usar para reproducir derizan los polígonos de la cara delantera.
superficies reflectantes como espejos o agua. El Entonces, se incrementa el valor del buffer
proceso comenzaría renderizando la geometría Stencil. A continuación, se renderizan los polígo-
nos de la parte trasera del volumen de sombra y
se decrementa el valor del buffer Stencil. Como
la escena estaba ya renderizada con la geome-
tría inicial, en nuestro ejemplo la tetera y la
superficie, algunos píxeles fallan el test del zbuf-
fer cuando se renderiza el volumen de sombra.
Cualquier valor que permanezca en el buffer
Stencil es en realidad la lista de píxeles que for-
man la sombra. Para concluir el proceso de ren-
derizado de la escena, ese grupo de píxeles que
permanecen en el buffer stencil se usan como
una máscara que se dibuja en la escena en un
cuadrado negro con transparencia. Como el buf-
fer Stencil actúa como una máscara, sólo los
Ejemplo de volumen de sombra. píxeles que están incluidos en la sombra apare-
cen oscuros, permaneciendo el resto transparen-

SOLO PROGRAMADORES 52
ALGORITMOS
Direct3D 9.0 avanzado (II)

LISTADO 3 Reproducción de reflejos


Con efectos
void pintar_reflejo()
{ como reflejos
//Se activa el buffer stencil
device_d3d->SetRenderState(D3DRS_STENCILENABLE,TRUE); y sombras
device_d3d->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);
device_d3d->SetRenderState(D3DRS_STENCILREF,0x1); nuestras escenas
device_d3d->SetRenderState(D3DRS_STENCILMASK,0xFFFFFFFF);
device_d3d->SetRenderState(D3DRS_STENCILWRITEMASK,0xFFFFFFFF); se aproximarán
device_d3d->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
device_d3d->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_KEEP); más a la realidad
device_d3d->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE);
//Se desactiva el buffer Z y activa el buffer stencil
device_d3d->SetRenderState( D3DRS_ZENABLE,FALSE);
device_d3d->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
device_d3d->SetRenderState(D3DRS_LIGHTING,FALSE);
device_d3d->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);
device_d3d->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
device_d3d->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
//Se dibujan las superficies reflectantes
sup_reflejo();
sup_reflejo2();
//Se guarda la matriz de vista
D3DXMATRIX matViewSaved;
device_d3d->GetTransform(D3DTS_VIEW,&matViewSaved);
//Se calcula el reflejo. Normal al plano de la superficie reflectante
D3DXMATRIX matView, matReflect;
D3DXPLANE plane;
D3DXPlaneFromPointNormal( &plane, &D3DXVECTOR3(0,1,0),&D3DXVECTOR3(0,1,0) );
D3DXMatrixReflect( &matReflect, &plane );
D3DXMatrixMultiply( &matView, &matReflect, &matViewSaved );
device_d3d->SetTransform( D3DTS_VIEW, &matView );
//Se establece un plano de recorte. Sólo aparecen los elementos encima
de la superficie
device_d3d->SetClipPlane(0,plane);
device_d3d->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x01 );
//Se renderiza la escena sobre la superficie reflectante.
//Recordar cambiar el orden de generación de polígonos. Es un reflejo.
device_d3d->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
device_d3d->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_EQUAL );
device_d3d->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
device_d3d->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
//Se borra el zbuffer el frame buffer y el buffer stencil no se borran.
device_d3d->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xFFFFFFFF,1.0f,0L );
pintar_escena();
//Se restauran los valores iniciales para la escena
device_d3d->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
device_d3d->SetRenderState( D3DRS_STENCILENABLE, FALSE );
device_d3d->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
device_d3d->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00 );
device_d3d->SetTransform( D3DTS_VIEW, &matViewSaved );

tes. Tanto esta como las anteriores técnicas pue- necesitar un tiempo elevado de desarrollo. Las
den ponerse en práctica estudiando el material escenas realizadas con estos efectos se apro-
de apoyo incluido en el CD-ROM. ximan cada día mas a la realidad que nos
rodea. Pero en el siguiente artículo concluire-
Conclusiones mos con el estudio de lo que se vislumbra
como el futuro inmediato en el proceso de
La tubería programable nos amplia el numero diseñar efectos, ya que abordaremos el análi-
de posibilidades de creación de efectos sin sis de vertex shaders y píxel shaders.

53 SOLO PROGRAMADORES
ALGORITMOS

Acceso a código nativo


con JNI (y II)
GABRIEL DOS SANTOS DÁVILA lar para los vectores, define el tipo jarray y varios
subtipos como jbooleanArray o jbyteArray. En el
cuadro "Tipos de datos para vectores" podemos
JNI no es sólo una forma de ejecutar ver la lista completa de declaraciones C++ de
código nativo desde Java. Es una tipos JNI para vectores. Al igual que ocurre con
las cadenas de caracteres, la representación
especificación que define una interna de un vector en Java no es equivalente a
completa interacción en ambos la de uno en C y por esa razón no podemos utili-
sentidos entre un tipo de código y el zarlos de forma directa sino que debemos hacer-
lo a través de funciones de acceso especiales.
otro. Acceso a vectores de tipos primitivos
Dentro de los vectores que contienen un tipo de
datos primitivo, hay dos variantes de uso distin-
Introducción tas. La primera consiste en copiar los elementos
del vector a un vector C normal cuya memoria
En la entrega anterior hicimos una introducción debe ser asignada previamente, trabajar con
a los aspectos más elementales de JNI que nos éstos elementos (modificándolos si fuera nece-
permitió trabajar con tipos de datos simples y sario) y luego, si fueron modificados, copiar los
hacer invocaciones desde Java al código nativo. elementos modificados al vector Java original.
En esta segunda entrega aprenderemos cómo
trabajar con vectores y objetos, invocar métodos Tipos de datos para vectores
y ejecutar la máquina virtual desde código escri- class _jarray : public _jobject {};
to en C/C++. typedef _jarray *jarray;

Acceso a vectores de Java class _jbooleanArray : public _jarray {}


typedef _jbooleanArray *jbooleanArray;
JNI trata a los vectores de tipos primitivos y los
de tipos por referencia de forma diferente. class _jbyteArray : public _jarray {};
Independientemente del tipo de datos de los ele- typedef _jbyteArray *jbyteArray;
mentos que contenga, un vector es siempre en sí
mismo una variable de tipo por referencia. JNI class _jcharArray : public _jarray {};
typedef _jcharArray *jcharArray;
posee una jerarquía de definiciones de tipos de
Utilidad javap. objetos que tiene a jobject como raíz. En particu- class _jshortArray : public _jarray {};
typedef _jshortArray *jshortArray;

class _jintArray : public _jarray {};


typedef _jintArray *jintArray;

class _jlongArray : public _jarray {};


typedef _jlongArray *jlongArray;

class _jfloatArray : public _jarray {};


typedef _jfloatArray *jfloatArray;

class _jdoubleArray : public _jarray {};


typedef _jdoubleArray *jdoubleArray;

class _jobjectArray : public _jarray {};


typedef _jobjectArray *jobjectArray;
SOLO PROGRAMADORES 54
ALGORITMOS
Acceso a código nativo con JNI (y II)

Supongamos que deseamos crear un méto- LISTADO 1 Modificando un vector Java desde C/C++, opción 1
do nativo que reciba un vector con diez JNIEXPORT jvoid JNICALL
números enteros e incremente en uno cada Java_TestClass_sumarUno (JNIEnv *env, jobject obj, jIntArray enteros){
uno de ellos. El código necesario para jint tmpA[10];
implementarlo puede verse en el listado 1. env->GetIntArrayRegion(enteros,0,10, tmpA);
for(int i=0;i<10;i++) tmpA[i]++;
La función GetIntArrayRegion recibe como env->SetIntArrayRegion(enteros,0,10, tmpA);
parámetros el vector Java, el índice del ele- }
mento inicial, la cantidad de elementos a
copiar y el vector C de destino (como un LISTADO 2
puntero a jint) el cual ya debe tener su Modificando un vector Java desde C/C++, opción 2
memoria reservada. Puesto que la función JNIEXPORT jvoid JNICALL
no asigna memoria, no devuelve ningún Java_TestClass_sumarUno (JNIEnv *env, jobject obj, jIntArray enteros){
jint *pEnteros;
código de error. Como resultado tendremos jboolean *pEsCopia;
copiados en tmpA todos los elementos del pEnteros =env->GetIntArrayElements(enteros, pEsCopia);
vector. Luego incrementamos el valor de if(pEnteros=NULL) return;
jint iElementos= env->GetArrayLength(enteros);
cada uno dentro de un bucle y finalmente for(jint i=0;i< iElementos;i++) pEnteros[i]++;
actualizamos los cambios en el vector origi- env-> ReleaseIntArrayElements(enteros,pEnteros,0);
nal por medio de la función SetIntArrayR- }
egion. Hay variantes de éstas dos funciones
para todos los tipos de datos primitivos. En LISTADO 3 Modificación de la función Java_SortFiles_sort
el cuadro "Funciones de copia de vectores
de tipos primitivos" podemos ver la lista JNIEXPORT jint JNICALL
Java_SortFiles_sort (JNIEnv *env, jobject obj, jobjectArray jarchivos, jint
completa. jorden, jstring jSufijo){
Esta técnica es buena para acceder a vec- const char *chSufijo= env->GetStringUTFChars(jSufijo, 0);
tores pequeños cuyo tamaño es fijo y se string sufijo(chSufijo);
env->ReleaseStringUTFChars(jSufijo,chSufijo);
conoce de antemano. La otra forma de uti- jint arraySize=env->GetArrayLength(jarchivos);
lizar vectores de tipos primitivos consiste cout << "sufijo: " << sufijo << " orden:" << jorden << " cant archivos:"
en obtener un puntero directo a sus ele- << arraySize << endl;
mentos, trabajar con ellos y luego liberar la for(int i=0;i<arraySize;i++){
jstring jstrArchivo = (jstring) env->GetObjectArrayElement(jarchivos, i);
referencia. Para que esto sea posible, la const char *chArchivo= env->GetStringUTFChars(jstrArchivo, 0);
máquina virtual debe ser capaz de indicar- sortfile(chArchivo,string(string(chArchivo) + sufijo).c_str());
le al recolector de basura que hay una refe- env->ReleaseStringUTFChars(jstrArchivo,chArchivo);
}
rencia externa a los elementos de ese vec- return 0;
tor por lo cual no deben ser movidos de su }
lugar en memoria. A este procedimiento se
lo conoce con el nombre de pinning y no
necesariamente es soportado por cualquier Acceso a vectores de objetos explicadas en la entrega anterior. Una vez obte-
máquina virtual. En el caso de que la El acceso a estos vectores se hace de elemen- nido el nombre de cada archivo a ordenar, lla-
máquina virtual no soporte pinning, reser- to a elemento usando las funciones GetOb- mamos a la función sort pasándole como pará-
va memoria, hace una copia de los elemen- jectArrayElement y SetObjectArrayElement. metros el nombre de archivo de entrada y el de
tos en esa memoria y devuelve una refe- Veremos cómo hacerlo modificando nuestra salida. Recordemos que el ordenamiento se
rencia a la copia. Luego, cuando el progra- aplicación de ejemplo para que lea el vector de hace, según se definió el ejemplo en la entrega
ma libera la referencia, actualiza el vector objetos de tipo string que contiene los nombres anterior, por edad. Luego debemos agregar a
original. El listado 2 presenta el mismo caso de los archivos a procesar. Modificaremos el SortFiles.cpp la función sort, cuyo código puede
del listado 1 pero esta vez obteniendo una código de la función Java_SortFiles_sort tal verse en el listado 4.
referencia directa. como indica el listado 3.
La función GetIntArrayElements devuelve una El código para leer el sufijo permanece
referencia a los elementos del vector. En el caso igual y se agrega una llamada a Funciones de copia de vectores de tipos
en que necesite reservar memoria para crear una GetArrayLength, que sirve tanto para vec- primitivos
copia de los mismos, podría devolver NULL si no tores de tipos primitivos como por referen-
hubiera memoria suficiente por lo cual verifica- cia, para obtener la cantidad de elementos GetBooleanArrayRegion() SetBooleanArrayRegion()
mos el valor de pEnteros antes de utilizarlo. En el del vector. Una vez que conocemos la can- GetByteArrayRegion() SetByteArrayRegion()
segundo parámetro devuelve un boolean indi- tidad de elementos iteramos sobre cada
cando si lo que devuelve es una copia o una refe- uno de ellos obteniendo una referencia por GetCharArrayRegion() SetCharArrayRegion()
rencia directa. Hay un par de funciones medio de GetObjectArayElement. Como GetShortArrayRegion() SetShortArrayRegion()
GetArray<tipo>Elements y SetArray<tipo>E- sabemos que el vector está formado por
ements para cada tipo de datos primitivo. objetos de clase string asignamos esta GetIntArrayRegion() SetIntArrayRegion()
También existen funciones GetPrimitiveA- referencia a una variable de tipo jstring. A GetLongArrayRegion() SetLongArrayRegion()
rrayCritical y SetPrimitiveArrayCritical que deben continuación leemos el contenido de esta
usarse con la misma precaución que las que se cadena usando las funciones GetS- GetFloatArrayRegion() SetFloatArrayRegion()
utilizan con cadenas de caracteres. tringUTFChars y ReleaseStringUTFChars GetDoubleArrayRegion() SetDoubleArrayRegion()

55 SOLO PROGRAMADORES
ALGORITMOS

LISTADO 4 Código de la función sortfile olvidarnos de agregar en la ruta de búsque-


int sortfile(const char* strArchEntrada, const char* strArchSalida){ da de archivos #include la ruta correspon-
vector<Empleado> ve; diente a JNI y de establecer las variables de
ifstream entrada (strArchEntrada); entorno adecuadamente.
copy(istream_iterator<Empleado> (entrada),
istream_iterator<Empleado>(),(back_inserter(ve)));
Para no complicar la lógica de la parte C++
entrada.close(); no se ha implementado la posibilidad de
sort(ve.begin(),ve.end()); seleccionar un ordenamiento ascendente o
ofstream salida(strArchSalida); descendente. El único objetivo del paráme-
copy(ve.begin(),ve.end(),ostream_iterator<Empleado>(salida));
salida.close(); tro de ordenamiento es demostrar cómo
return 0; pasar por parámetro una variable de tipo
} primitivo. La secuencia para compilar en
Windows es la siguiente:
LISTADO 5 Contenido del fichero Empleado.h C:\>set PATH=%PATH%;<ruta_Visual_Stu
dio>\VC98\Bin
#include <iostream>
#include <string>
C:\>set LIB=<ruta_Visual_Studio>\VC98
#include <sstream>
#include <fstream> \Lib
const char SEPARADOR_DATOS=',';
const char SEPARADOR_REG='\n'; C:\>set INCLUDE=<ruta_Visual_Studio>
class Empleado {
std::string m_nombre; \VC98\Include;<ruta_JDK>\include;<rut
std::string m_edad; a_JDK>\include\win32
public:
virtual void enviarA (std::ostream& dest) const; C:\>cl -ML
virtual void leerDe (std::istream& origen);
friend bool operator<(const Empleado& i, const Empleado& d) {return Para compilar en Linux, haremos esto:
(i.m_edad<d.m_edad);} $ gcc -shared -I<ruta_JDK>/include/ \
};
-I<ruta_JDK>/include/linux \
LISTADO 6 Contenido del fichero Empleado.cpp SortFiles.cpp Empleado.cpp -o libSortF
#include "Empleado.h" iles.so
using namespace std;
void Empleado::enviarA(std::ostream& dest) const { Y para compilar en Solaris haremos lo
dest << m_nombre << SEPARADOR_DATOS; siguiente:
dest << m_edad << SEPARADOR_REG;
} $ cc -G -I<ruta_JDK>/include/ -I<ruta_
void Empleado::leerDe (std::istream& origen){ JDK>/include/solaris \
getline(origen,m_nombre,SEPARADOR_DATOS);
getline(origen,m_edad,SEPARADOR_REG); SortFiles.cpp Empleado.cpp -o libSort
}
Files.so

LISTADO 7 Modificación del fichero SortFiles_i.h Para poder probar debemos crear archivos
#include <algorithm>
de datos que contengan en cada línea ape-
#include <vector> llido y edad de un empleado separados por
#include <string> coma. Por ejemplo así:
#include <sstream>
#include <iterator> López,44
#include <fstream>
#include "Empleado.h" Pérez,35
int sortfile(const char* strArchEntrada, const char* strArchSalida);
std::ostream& operator << (std::ostream& strm, const Empleado& f) { González,65
f.enviarA(strm);
return strm; Al ejecutar la clase Java, los archivos que-
} darán ordenados en una copia cuyo nombre
std::istream& operator >> (std::istream& strm, Empleado& f) { será el del archivo más el sufijo indicado.
f.leerDe (strm);
return strm;
} Acceso a variables miembro de objetos
Java
Para comprender el tema que nos ocupa ro llamado Empleado.cpp cuyo contenido se
basta con saber de esta función que ordena muestra en el listado 6. La función de esta El acceso a una variable miembro o campo
los datos de cada archivo utilizando iterado- clase es la de leer los datos de un empleado de un objeto Java desde el código nativo se
res y una clase Empleado que debemos crear. desde y hacia el archivo de datos. Por último hace por medio de los siguientes pasos:
Para declararla agregaremos un fichero de modificaremos el archivo SortFiles_i.h, al 1 . Obtener una referencia a la clase a la
nombre Empleado.h en el que escribiremos el cual le agregaremos las líneas del listado 7. cual pertenece el campo usando la fun-
contenido del listado 5. La implementación Una vez concluidas estas modificaciones, ción GetObjectClass.
de la clase Empleado la haremos en un fiche- debemos compilar y ejecutar el ejemplo, sin 2 . Obtener el identificador del campo a

SOLO PROGRAMADORES 56
ALGORITMOS
Acceso a código nativo con JNI (y II)

partir de su nombre y de un descriptor LISTADO 8 Modificación de la clase SortFiles.java


que indica su tipo de dato. La función public void informarProgreso(int procesados, int pendientes, String procesando){
que se utiliza depende del tipo de campo System.out.println(
al que se desea acceder. Para variables "Actualmente procesando " + procesando +
de instancia se usa la función GetFieldID ". Total procesado: " + procesados + ". " +
pendientes + " pendientes de procesar.");
y para variables estáticas de la clase }
(definidas con la palabra clave static) se
usa GetStaticFieldID. Más adelante
veremos qué es exactamente un des-
criptor de campo y cómo crear uno. LISTADO 9 Modificación del archivo SortFiles.cpp
3 . Una vez obtenido el identificador del for(int i=0;i<arraySize;i++){
campo, se lee su valor usando la familia jstring jstrArchivo = (jstring) env->GetObjectArrayElement(jarchivos, i);
de funciones Get<tipo>Field() que reci- jclass cls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(cls, "informarProgreso",
be como parámetros el identificador de "(IILjava/lang/String;)V");
campo y una referencia al objeto cuyo if (mid == NULL) return 1; /* método no encontrado */
campo se quiere leer o GetStatic<ti- env->CallVoidMethod(obj, mid,i,arraySize-i,jstrArchivo);
po>Field() que recibe como parámetro el const char *chArchivo= env->GetStringUTFChars(jstrArchivo, 0);
sortfile(chArchivo,string(string(chArchivo) + sufijo).c_str());
identificador de campo y una referencia env->ReleaseStringUTFChars(jstrArchivo,chArchivo);
a la clase cuyo campo se quiere acceder, }
según sea éste static o no. Para modifi-
car el valor de un campo utilizaremos las
funciones Set<tipo>Field() y SetSta-
tic<tipo>Field().

Ejecutar métodos de objetos Java


Al igual que los campos o variables miem-
bro, los métodos también pueden ser de
instancia o estáticos y la forma de invocar-
los será diferente.
Invocación de métodos de instancia y
estáticos
EL procedimiento es similar al utilizado
para el acceso a campos: Estructura final de la aplicación ejemplo. Indicador de progreso.
1 . Obtener la referencia a la clase usando
la función GetObjectClass. usamos para invocar a un método Java que obligatorios. Todos estos parámetros adiciona-
2 . Obtener el identificador del método a recibe parámetros, éstos irán como paráme- les los enviará al método que invoca. Hay dos
partir del descriptor de método usando tros adicionales a la función de invocación. variantes de la familia Call<tipo>Method()
las funciones GetMethodID o GetStat- Veamos un ejemplo. Nuestra aplicación debe que utilizan otras técnicas para pasar paráme-
icMethodID según se trate de un método notificar al objeto Java de cada archivo pro- tros al método Java. Sus nombres son Call<Ti-
de instancia o estático respectivamente. cesado, informando cantidad de procesados po>MethodA() y Call<tipo>MethodV respec-
3 . Una vez que tenemos el identificador del y de pendientes. Esto lo haremos por medio tivamente y utilizan punteros y vectores para
método podemos invocarlo. Para métodos de un callback, es decir, un método Java que los parámetros adicionales.
de instancia lo haremos con la función será invocado desde el código nativo cada También podemos ver en el ejemplo cómo
Call<tipo>Method() que recibe como vez que se procese un archivo. En primer se implementa la búsqueda del identifica-
parámetro la referencia al objeto cuyo lugar, agregaremos la función de notificación dor de campo.
método deseamos invocar. En el caso de a la clase Java SortFiles. Para ello, en el archi- Ya estamos listos para compilar nuevamente
los métodos estáticos debemos usar vo SortFiles.java agregaremos dentro de la nuestra clase Java y la librería C++. Una vez
CallStatic<tipo>Method() y pasarle como declaración de la clase el código del listado 8. hecho esto podemos lanzar la ejecución y vere-
parámetro la referencia a la clase. El Luego modificaremos el bucle for de la fun- mos que para cada archivo procesado aparece
<tipo> incluido en el nombre de estas ción Java_SortFiles_sort en el archivo en pantalla la información de progreso.
funciones se refiere al tipo devuelto por el SortFiles.cpp tal como muestra el listado 9.
método a invocar. Hay una versión para Como podemos ver, el método informarPro- Descriptores de campo y de método
cada tipo primitivo, una para métodos que greso recibe tres parámetros, los cuáles se
no devuelven ningún valor (es decir, que el pasan desde C++ como parámetros adiciona- Los descriptores utilizados por GetMetho-
tipo de datos devuelto es void) y otra para les a CallVoidMethod. Ésto es porque esta fun- dID y GetFieldID son cadenas de caracteres
métodos que devuelven una referencia. ción está declarada en <jni.h> como void que representan el tipo de dato en el caso
Las funciones de invocación de métodos, CallVoidMethod(jobject obj, jmethodID de los campos y la declaración en el caso de
tanto estáticos como de instancia, están defi- methodID, ...) y puede recibir cualquier núme- los métodos.
nidas con una cantidad indeterminada de ro de parámetros ademas de la referencia al Un descriptor para un campo de tipo de
parámetros opcionales. De esta manera, si las objeto y el identificador de método que son datos primitivo consiste en una letra que

57 SOLO PROGRAMADORES
ALGORITMOS

LISTADO 10 Detección y control de excepciones Control de errores


...
1. jthrowable e; Cuando desarrollamos código nativo debe-
2. env->CallVoidMethod(obj,mid1); mos tener especial precaución al invocar
3. e=env->ExceptionOccurred(); funciones JNI o métodos de objetos Java.
4. if (e){
5. e->ExceptionDescribe(); Muchas de las funciones JNI devuelven un
6. e->ExceptionClear(); valor que indica si se produjo un error pero
7. } esto no siempre es así, además es muy
8. env->CallVoidMethod(obj,mid2);
9. e=env->ExceptionOccurred(); común que los métodos que invoquemos
10. if (e){ lancen una excepción si encuentran algún
... error. Esta es una excepción de Java y como
tal no será detectada por el mecanismo de
LISTADO 11 manejo de excepciones de C++. Las funcio-
Lanzando una excepción desde un método nativo
nes y tipos que luego de llamar a una función
jclass e=env->FindClass("FileNotFoundException"); JNI nos permiten detectar si se produjo algu-
if (e!=NULL){
env->ThrowNew(e,"No se encontró el archivo");
na excepción y en tal caso manejarla, son:
return; z jthrowable, referencia a un objeto de
} excepción.
z env->ExceptionOccurred, devuelve una
LISTADO 12 referencia jthrowable a la última excep-
Capturando la excepción ción ocurrida. La forma de detectar si se
... produjo una excepción es llamar a esta
void probar(){ función inmediatamente después de
try{
metodo("c:\datos.dat"); cada función JNI y si devuelve un valor
}catch(Exception e){ distinto de NULL indica que hubo una
System.out.println("Excepción en el método nativo."); excepción. Luego de manejar la excep-
}
}
ción hay que llamar a ExceptionClear, de
... lo contrario ésta quedará activa y si
native void metodo(String archivo) throws FileNotFoundException; luego volvemos a ejecutar Excep-
... tionOccurred seguirá informando que
hubo un error.
LISTADO 13 Función main del fichero StartVM.cpp z ExceptionDescribe, muestra información
sobre la excepción.
#include <jni.h>
z ExceptionClear, desactiva la excepción
int main(int argc, char* argv[]){
JNIEnv* env; para que sucesivas invocaciones a Excep-
JavaVM* jvm; tionOccurred no reporten un error a
jclass cls; menos que otra función lance una nueva
jmethodID mid;
if (StartVM(jvm,env)<0) return 1; excepción.
if((cls=env->FindClass(argv[1]))==NULL) return 1; En el extracto de código del listado 10 pode-
if ((mid=env->GetStaticMethodID(cls,"main","[Ljava/lang/String"))==NULL) mos ver cómo debemos detectar y controlar
return 1;
env->CallStaticVoidMethod(cls,mid); las excepciones. Si la función en la línea 2
return 0; lanza una excepción, la ejecución entrará en
} el primer if. Si en la línea 6 omitiéramos la
llamada a ExceptionClear, el if de la línea 10
identifica el tipo de dato. En el caso de los paréntesis de los descriptores de cada uno daría verdadero aún cuando la llamada de la
campos de tipo por referencia que sean ins- de sus parámetros (esta lista no va separa- línea 8 no genere ninguna excepción.
tancias de alguna clase, el descriptor estará da por comas ni espacios sino un descriptor Otra cosa que podríamos necesitar es lan-
formado por una letra L seguida del nombre a continuación del otro). Por último, luego zar una excepción desde un método nativo
completo (fully qualified name) de la clase y de la lista, aparece el descriptor del tipo de para que sea capturada desde el código
punto y coma. Los campos de tipo vector dato que devuelve el método. En el cuadro Java. Para eso usaremos FindClass para
tendrán asociado un descriptor que co- "Descriptores de campos y métodos" pode- obtener una referencia a la clase de la
mienza con el carácter '[' seguido del des- mos ver también ejemplos de descriptores excepción que queremos lanzar y luego la
criptor correspondiente al tipo de dato que de método. La utilidad javap incluída en el lanzaremos con ThrowNew. El lector puede
el vector almacena. En el cuadro "Descrip- SDK de Java nos ayuda a crear éstos des- ver cómo hacerlo en el listado 11.
tores de campos y métodos" podemos ver criptores, para obtener los correspondientes Lanzar una excepción de esta forma no inte-
varios ejemplos de declaraciones de campos a la clase SortFiles escribiremos: rrumpe el flujo de ejecución del método nati-
y su descriptor asociado. javap -s -p SortFiles vo; para que sea manejada en el código Java,
Los descriptores de método representan la debemos devolver el control inmediatamen-
cabecera del mismo, identificando los tipos En la salida estándar obtendremos los iden- te al mismo y por eso el return justo después
de todos sus parámetros y su valor de retor- tificadores para todos los métodos y cam- de ThrowNew. La forma de capturar la excep-
no. La sintaxis consiste en una lista entre pos (si los hubiera) de la clase. ción del lado de Java es la normal, usando try

SOLO PROGRAMADORES 58
ALGORITMOS
Acceso a código nativo con JNI (y II)

y catch. La única consideración que debemos tener LISTADO 14 Creando la instancia de la JVM
en cuenta es, como vemos en el listado 12, que la int StartVM(JavaVM*& jvm,JNIEnv*& env){
declaración del método nativo debe incluir la cláu- JavaVMInitArgs jvmargs;
sula throws. JavaVMOption opts[1];
opts[0].optionString="-Djava.class.path=.";
Invocación de la Máquina Virtual Java jvmargs.version=0x00010002;
jvmargs.options=opts;
jvmargs.nOptions=1;
Las diferentes versiones de la Máquina Virtual de jvmargs.ignoreUnrecognized=true;
return JNI_CreateJavaVM(&jvm,(void**)&env,&jvmargs);
Java están implementadas como librerías nati- }
vas. En este apartado veremos un programa
ejemplo que nos permitirá ejecutar el método
estático main de una clase de manera similar a LISTADO 15 Código del archivo StartVM.java
la aplicación java del SDK. La diferencia con los class claseStartVM{
ejemplos que hemos visto hasta ahora es que public static void main(String[] args){
estábamos implementando métodos nativos que System.out.println("Hola desde Java!");
}
se ejecutan desde Java con la Máquina Virtual ya }
iniciada. En cambio el próximo ejemplo se puede
ejecutar desde la línea de comando y creará su
propia instancia de la Máquina Virtual, o sea que Esquema que describe la invocación
de la Máquina Virtual.
veremos ahora cómo hacer el camino inverso y
utilizar funcionalidad implementada en clases
Java desde aplicaciones nativas. Los pasos a
seguir por nuestro programa son:
1 . Establecer las opciones a utilizar, como la
variable CLASSPATH si fuera necesario.
2 . Establecer los argumentos de inicialización.
3 . Crear una instancia de la Máquina Virtual
usando JNI_CreateJavaVM. Esta función nos
devuelve un puntero a la Máquina Virtual y
otro al entorno (el puntero a JNIEnv que estu- Conclusiones
vimos utilizando para acceder a todas las
funciones JNI). Con esta entrega concluye la serie sobre JNI.
4 . A partir de aquí procedemos de la manera Hemos repasado los aspectos básicos de ésta
normal para invocar un método Java desde tecnología y algunas de sus posibilidades más
código nativo, es decir, debemos obtener una avanzadas. Como recomendación para quiénes
referencia a la clase, luego el identificador de deseen profundizar en el tema, es muy impor-
método y por último invocarlo con alguna de tante para los usos más avanzados y para opti-
las funciones que hemos visto. mizar las aplicaciones el conocer a fondo las
Para este ejemplo crearemos un nuevo archivo interacciones entre el administrador de memoria
C++ llamado StartVM.cpp en el cual crearemos de la Máquina Virtual y el código nativo, los
la función main que se muestra en el listado 13. tipos de referencias que existen y cómo debe ser
A continuación agregamos la función del listado administrada cada una.
14 para crear la instancia de la Máquina Virtual.
Sólo nos falta escribir la clase java de prueba
para lo cual debemos crear el archivo Descriptores de campos y métodos
StartVM.java y escribir en él el código del lista-
do 15. Campo int iCount; "I"
Para probar el programa debemos compilar la Campo float fPrecio; "F"
clase Java y el archivo StartVM.cpp, el cual enla-
zaremos con la biblioteca estática de la Máquina Campo Integer iCount; "Ljava/lang/Integer;"
Virtual de Java. En la distribución Windows del Campo boolean bFound; "Z"
SDK de Sun debemos enlazar con jvm.lib y copiar
Campo int[] bCounts; "[I"
jvm.dll en un directorio que aparezca en la
variable PATH como por ejemplo la ruta de siste- Campo String strTmp; "Ljava/lang/String;"
ma de Windows. Finalmente, desde la línea de Campo String[] strFiles; "[Ljava/lang/String;"
comandos ejecutamos:
StartVM claseStartVM Método void mimetodo() "()V"
Método void metodo2(int i1, float f1) "(IF)V"
Si todo va bien veremos en la salida estándar el
mensaje "Hola desde Java!". Método String metodo3(String str1, "(Ljava/lang/String;IZ)
int i1,boolean b1) Ljava/lang/String;"

59 SOLO PROGRAMADORES
DUDAS

Preguntas y respuestas
ADOLFO ALADRO GARCÍA Este mismo mecanismo, que se emplea en las
hojas XSLT, puede utilizarse para hacer que-
Trabajo con documentos XML que tienen más ries una vez que el documento XML se ha
o menos la estructura del listado 1. interpretado.
Quisiera saber cómo puedo hacer queries con- En primer lugar se utiliza un parser para obte-
tra este tipo de documentos de forma que ner el DOM del origen de datos XML. Véase el
obtenga la citas que hay entre dos determina- listado 3.
das fechas o todas aquellas que tienen un La propiedad async indica si se desea que el
determinado estado, por citar dos ejemplos. En proceso de carga del documento XML se haga
la actualidad estos documentos se visualizan de forma síncrona (false) o asíncrona (true). En
en IE6 con ayuda de XSLT. el primer caso después de llamar al método
load no se ejecuta la siguiente línea de código
hasta que los datos no ha sido completamente
La forma más sencilla de hacer consultas contra cargados o se produce un error. El objeto
un origen de datos XML es empleando expresio- parseError proporciona información acerca de
nes XPath. Este tipo de expresiones se emplean la carga. Si el valor de la propiedad errorCode
normalmente en el lenguaje XSLT para seleccio- es igual a cero significa que no se han produci-
nar y filtrar los nodos que van a procesarse. do errores. Por último, se llama al método nor-
Obsérvese el listado 2. malize, sobre el nodo principal del origen de
El elemento xsl:for-each se emplea para hacer datos XML, para ignorar los espacios en blanco
un bucle y el valor del atributo select es la y saltos de línea que no son útiles.
expresión XPath que indica qué nodos del ori- El siguiente paso consiste en indicar qué tipo
gen de datos se van a recorrer. En este ejemplo de expresiones se van a emplean para hacer
concreto se recorrerán todos aquellos elemen- queries. Esto se lleva a cabo con el método
tos etiquetados como appointment que tengan setProperty:
un atributo llamado status cuyo valor sea igual oDOMDocument.setProperty("SelectionLanguag
a 1. El elemento xsl:sort se emplea para orde-
e", "XPath");
nar el resultado de forma que los elementos
appointment se muestran empezando por la De esta forma se le indica al motor de XML
fecha más reciente y terminando por la fecha que el lenguaje empleado será XPath.
más antigua. Finalmente el elemento xsl:value- Para hacer una query se pueden emplear dos
of se emplea para mostrar la cadena de texto métodos: selectNodes y selectSingleNode. El
Documentación del método selectNodes que que contienen los elementos appointment de la primero devuelve una lista de nodos mientras
permite hacer queries contra los orígenes de
datos XML. fuente de datos XML. que el segundo devuelve un único nodo. Así
por ejemplo, si se quieren seleccionar todos
los elementos que se encuentran entre dos
determinadas fechas se puede hacer lo sugeri-
do en el listado 4.
La expresión XPath indica que se selecciona-
rán todos aquellos nodos del origen de datos
XML etiquetados como appointment cuyo
atributo timemillis tenga un valor mayor o
igual que el devuelto por la expresión
d1.getTime() y menor o igual que el devuelto
por la expresión d2.getTime().
El objeto devuelto selectNodes es una lista de
nodos que puede recorrerse como se muestra en
el listado 5.
La propiedad length devuelve el número de
nodos que se han seleccionado. El método
item permite acceder a cada nodo indivi-
dualmente.

SOLO PROGRAMADORES 62
DUDAS
PREGUNTAS Y RESPUESTAS

request.getHeader("user-agent")
Finalmente, el método selectSingleNode fun-
ciona de forma equivalente. La única diferencia Como puede verse en el listado 6, además de
es que se emplea cuando el número de nodos este método que permite obtener una cabe-
que se van a devolver se sabe que es 1. cera en concreto, es posible recorrerlas
todas.
El método getHeaderNames devuelve un obje-
¿De qué forma se puede saber desde el servi- to de tipo Enumeration con la lista de los
dor cuál es el navegador que está empleando el nombres de cabeceras HTTP que se han encon-
usuario al hacer la correspondiente llamada trado en el mensaje correspondiente a la peti-
HTTP contra un servlet o una página JSP? ción. Basta con recorrer esta colección y
emplear con cada uno de los nombres el
Lo único que hay que hacer es consultar la método getHeader para obtener los valores
correspondiente cabecera HTTP de la petición: correspondientes a las cabeceras.

LISTADO 1 Estructura de mis documentos XML


<?xml version="1.0" encoding="ISO-8859-1"?>
<appointments>
<appointment id="1" status="1" priority="0" proyect="1"
timemillis="1088281477234"><![CDATA[Este es el texto...]]></appointment>
<appointment id="2" status="0" priority="0" proyect="1"
timemillis="1088281477234"><![CDATA[Este es el texto...]]></appointment>
...
</appointments>

LISTADO 2 Recorriendo el documento XML


<xsl:for-each select="appointment[@status=1]">
<xsl:sort data-type="number" order="descending" select="@timemillis"/>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:for-each>

LISTADO 3 Obteniendo el DOM del origen de datos XML


var oDOMDocument = null;
try {
oDOMDocument = new ActiveXObject("MSXML2.DOMDocument");
oDOMDocument.async = false;
oDOMDocument.load("data.xml");
if (oDOMDocument.parseError.errorCode == 0) {
oDOMDocument.documentElement.normalize();
...
}
} catch (e) {
}

LISTADO 4 Seleccionando elementos


var d1 = new Date(2004, 1, 1);
var d2 = new Date(2004, 6, 1);
var query = "appointment[@timemillis >= " + d1.getTime() + " and @timemillis <= " +
d2.getTime() + "];
var oNodeList = oDOMDocument.documentElement.selectNodes(query);

LISTADO 5 Recorriendo el objeto selectNodes


if (oNodeList!=null) {
var nodeListLength = oNodeList.length;
for(var i=0; i<nodeListLength; i++) {
alert(oNodeList.item(i));
}
}

LISTADO 6 Recorriendo todas las cabeceras


for (Enumeration e = request. getHeaderNames ; e.hasMoreElements() ;) {
El método getHeaderNames permite
String sHeaderName = (String)e.nextElement(); obtener la lista de cabeceras HTTP.
String sHeaderValue = (String)request.getHeader(sHeaderName);
System.out.println(sHeaderName + "=" + sHeaderValue)
}

63 SOLO PROGRAMADORES
LIBROS

J2EE: Desarrollo de aplicaciones web


AUTOR: Benjamin Aumaille
EDITORIAL: Ediciones ENI

ISBN: 2-7460-1912-4

PÁGINAS: 357

LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2002


IDIOMA: Castellano

DESCRIPCIÓN:
Esta obra proporciona un soporte de referencia en la utilización del lenguaje Java para su versión
J2EE (Java 2 Enterprise Edition) para el desarrollo de aplicaciones web.
Tras descubrir la plataforma J2EE, este libro muestra cómo diseñar aplicaciones web dinámicas
basadas en componentes Java, como los Servlets y las Java Server Pages (JSP's).
Dado que la mayor parte de las aplicaciones web realizan llamadas a un sistema de gestión de
bases de datos relacionales, este libro dedica todo un capítulo al API JDBC (Java DataBase
Connectivity).
Cuando el lector se haya familiarizado con las diferentes tecnologías implicadas en el desarrollo,
se abordará el despliegue de la aplicación tomando como descriptor de despliegue un archivo
web.xml.
Obviamente todos estos puntos están acompañados de ejemplos que permitirán asimilar rápida-
mente todos estos conceptos.

Visual Basic .NET


AUTOR: Jorge Serrano Pérez
EDITORIAL: Anaya Multimedia

ISBN: 84-415-1445-3

PÁGINAS: 416

LUGAR Y FECHA DE PUBLICACIÓN: Madrid, 2002


IDIOMA: Castellano
OBSERVACIONES: Incluye CD-ROM con los ejemplos del libro

DESCRIPCIÓN:
La comunidad de programadores de Visual Basic es una de las mayores entre todas las dedicadas
a la programación. Visual Basic es un lenguaje orientado a objetos, con el que se pueden crear
aplicaciones Windows, aplicaciones web, servicios Windows, servicios web y aplicaciones para
otros dispositivos, como los de tercera generación o PDA.
Visual Basic .NET es una renovación y actualización absoluta respecto la versión anterior. Visual
Basic .NET está pensado para satisfacer cualquier exigencia, soportando todas las característi-
cas típicas del desarrollo de aplicaciones e incorporando las nuevas herramientas que debe tener
un lenguaje moderno.
El acceso a datos ha sido renovado, por ejemplo se utiliza ADO.NET para acceder a fuente de
datos. Además, la manipulación gráfica 2D es ahora más enriquecedora gracias a la posibilidad
de integrar y utilizar GDI+ en nuestras aplicaciones gráficas.
Todas estas características están respaldadas por el uso de librerías que nos permiten dar valor
añadido al desarrollo de aplicaciones, como el uso de métodos de seguridad, encriptación y des-
encriptación de información, gestión de errores depuración, etc.

SOLO PROGRAMADORES 64
n116_cdRom.qxd 20/06/2004 11:59 Página 66

CD-ROM

Contenido CD-ROM
Fuentes Esperamos que con ellos el
„Fuentes
„
z Ejemplo JAXB

Tratamiento de XML desde Java (y III):


un caso práctico
Los autores del artículo han preparado
lector coja una idea de
hasta dónde puede llegar
una aplicación con JNI.
116 z XML con Castor
z ADO.NET
z Técnicas Direct3D
z JNI
„Programación
„

un ejemplo completísimo que servirá Programación REVISTAS


PROFESIONALES, S.L.
z Castor 0.9.5.3
z NetBeans IDE 3.6
para practicar todo lo relacionado con VALENTÍN
ALENTÍN BEATO
EATO, 42 - 3.ª z Cooktop 2.5
Castor 0.9.5.3
28037 MADRID
el acceso a datos XML desde Java. Se
ADRID
DEPÓSITO LEGAL:: M
DEPÓSITO LEGAL M-26827-
-26827- 1994
1994
z Cygwin
ISSN:
ISSN: 1134-4792
1134-4792
z WiX
trata de la aplicación Agenda que se ha Castor resulta imprescindible
desarrollado en esta última entrega. para poder compilar los ejemplos
Enlace de datos XML con Castor del artículo "Enlace de datos XML y además...
Los ejemplos ofrecidos se ajustan exac- con Castor". La instalación de este Ofimática, navegadores y clientes de correo,
tratamiento de imágenes, visualizadores,
tamente al contenido del artículo. Con paquete es sumamente sencilla. Simple- compresores, grabadores, Internet y
el código de apoyo que se encuentra en mente habrá que descomprimir el .zip y multimedia.
esta sección, el lector podrá hacer copiar el directorio "castor-0.9.5.3" a
Marshall, Unmarshall, Mapping y gene- nuestro disco (por ejemplo, en C:\) y
ración automática de código. luego añadir a la variable CLASSPATH
Acceso a datos con ADO.NET y III) todos y cada uno de los 17 archi-
El material de apoyo de este artículo vos .JAR que se
servirá para mostrar al lector cómo tra- encuentran
bajar con transacciones, actualizacio- en el directo-
nes, inserción de archivos de gran rio "castor-
tamaño en la base de datos y cómo 0.9.5.3\lib".
recuperarlos por la web. NetBeans IDE 3.6
Direct3D 9.0 avanzado (II) NetBeans IDE 3.6 es un entorno de des- z La plataforma NetBeans
En este apartado se ofrecen varios arrollo escrito en Java, que puede ayudar- La plataforma NetBeans ofrece soporte a
ejemplos con sus fuentes y el ejecuta- nos a desarrollar en este y otros lenguajes. los desarrolladores para crear aplicaciones
ble. Hay que destacar que si nuestra NetBeans IDE 3.6 pertenece al proyecto de escritorio. Además cuenta con gran can-
tarjeta gráfica no dispone de una NetBeans, que es mucho más que un entor- tidad de plug-ins que hacen que su creci-
buena aceleración, los ejecutables pue- no de desarrollo. El proyecto NetBeans fue miento sea constante.
den no funcionar. impulsado por Sun en Junio de 2000 y se Cooktop 2.5
Acceso a código nativo con JNI (y II) caracteriza por ser Open Source. Este pro- Cooktop es una herramienta orientada a
Para completar la segunda parte de yecto, básicamente, puede definirse con facilitar el uso de las tecnologías XML.
nuestra introducción a JNI, ofrecemos dos productos: Ofrece las funciones más clásicas de este
los ejemplos discutidos en el artículo. z El IDE NetBeans tipo de herramientas y además nos permi-
tirá saber si nuestros documentos XML
están bien formados y si son válidos, entre
otras cosas.
Cygwin
Tal como podemos leer en la página de
este proyecto, debemos diferenciar en
Cygwin dos partes. Por un lado Cygwin
ofrece una API para desarrollar en
Windows como si estuviéramos en Linux.
Por otra parte, encontraremos algunas
herramientas que representarán el "Look
& Feel" de Linux.
WiX
Esta herramienta, más allá de su utilidad,
destaca por ser un producto de Microsoft
liberado con licencia de Open Source. WiX
(Windows Instaler XML) sirve para crear los
paquetes de instalación de nuestras aplica-
ciones para Windows.

SOLO PROGRAMADORES 66

You might also like