59
Precio: 6 (España) (IVA incluido) AÑO XI. 2.ª ÉPOCA Nº 124 UNA PUBLICACIÓN DE: REVISTAS PROFESIONALES S.L. Y ADEMÁS… GRATIS CD INCLUIDO ENTREGA DEL COLECCIONABLE ACTUALIDAD Enrique Martín, de BEA Systems, nos cuenta los secretos del proyecto Da Vinci Certifícate como arquitecto J2EE de Sun DISPOSITIVOS MÓVILES J2ME avanzado: envía un SMS y accede a la cámara de tu móvil MIDDLEWARE Programación distribuida en .NET… con .NET Remoting Acceso a orígenes de datos desde interfaces XAML DISEÑO Together Architect, el enlace entre el problema y la solución Implementación de patrones de diseño con C++ y ACE CANAL PANDA Pharming, nueva técnica de fraude Noticias, javaHispano y Opinión, Libros, Preguntas y Respuestas 8 4 1 3 0 4 2 3 0 3 2 9 9 0 0 1 2 4

Revista Solo Programadores #124

Embed Size (px)

Citation preview

Page 1: Revista Solo Programadores #124

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

Y ADEMÁS…

GRATIS

CD INCLU

IDO 8ª ENTREGA DEL COLECCIONABLE

ACTUALIDADEnrique Martín, de BEA Systems, nos cuenta los secretos del proyecto Da Vinci

Certifícate como arquitecto J2EE de Sun

DISPOSITIVOS MÓVILESJ2ME avanzado: envía un SMS y accede a la cámara de tu móvil

MIDDLEWAREProgramación distribuidaen .NET… con .NET Remoting

Acceso a orígenes de datos desde interfaces XAML

DISEÑOTogether Architect, el enlace entre el problema y la solución

Implementación de patrones de diseño con C++ y ACE

CANAL PANDAPharming, nueva técnica de fraude

Noticias, javaHispano y Opinión, Libros, Preguntas y Respuestas 8 413042 303299

0 0 1 2 4

Page 2: Revista Solo Programadores #124

Número 124 - Mayo 2005

Edita: REVISTAS PROFESIONALES [email protected]

C/ Valentin Beato 42, 3ª. 28037 - Madrid.

http://www.revistasprofesionales.comhttp://digital.revistasprofesionales.com

EditorAgustín Buelta

••••••••••••••••••••••••••••••••••Coordinación Técnica-Redacción

Carlos Laparra••••••••••••••••••••••••••••••••••

MaquetaciónRaúl Clavijo

••••••••••••••••••••••••••••••••••Asesoría de Publicidad

Felipe RibagordaTel.: 91 304 87 64

BarcelonaC/ Rocafort, 241/243, 5º 1ª

Mariano SánchezTel.: 93 322 12 38

••••••••••••••••••••••••••••••••••Suscripciones

Tel: 91 304 87 64Fax: 91 327 13 03

•••••••••••••••••••••••••••••••••••Impresión

Ideas de Impresión•••••••••••••••••••••••••••••••••••

DistribuciónMotorpress Ibérica

Distribución MexicoDIMSA - Angel Bosch

[email protected]ón, números atrasados y suscripciones

Renacimiento, 180. Col. San Juan TlihuacaAzcapotzalco. 02400 México D.F.

Distribución ArgentinaCapital Federal: DistrimachisaInterior: York Agency, S. A.Tel. (005411) 43 31 50 51

••••••••••••••••••••••••••••••••••La revista Sólo Programadores no tiene por qué

estar de acuerdo con las opiniones escritas por suscolaboradores en los artículos firmados.

El editor prohibe expresamente la reproduccióntotal o parcial de los contenidos de la revista

sin su autorización escrita.

Depósito legal: M-26827-1994PRINTED IN SPAIN

COPYRIGHT 30-04-2005P.V.P. 6,00 Euros

Precio en Canarias, Ceuta y Melilla: 6,15 Euros

EEDDIITTOORRIIAALLNuevamente, la actualidad nos llega en forma de siglas. En efecto, la conversación

mantenida con Enrique Martín (Director de Tecnología de BEA Systems) ha servido,entre otras cosas, para entender que una nueva guerra de estándares emergentes seavecina. Como el lector podrá comprobar en la entrevista publicada en este númerode Sólo Programadores, los nuevos estándares sobre los que “correrán” los próximosservicios y aplicaciones de red serán: SIP, Parlay y JAIN.

La aceptación de JAIN por parte de la industria está aún por comprobar, sin embar-go tanto SIP como Parlay parece que ya se han hecho un hueco entre los puestos másimportantes. De hecho, hablamos aquí de estándares “nuevos” y “emergentes” peroesto no es cierto al 100%. SIP, por ejemplo, es un protocolo cuyo objetivo es permitirel tratamiento de los servicios de voz como una aplicación más de la red, y el primerborrador de este protocolo surgió en febrero de 1996 (SIPv1), sin embargo en el mesde diciembre de ese mismo año se publicó la segunda versión (SIPv2). En febrero de1999 SIP se convirtió ya en un estándar, publicado como RFC 2543, aunque en juniode 2002 se publicaba una nueva versión, RFC 3216, que reemplazaba a la anterior.

Sin embargo, pese a que estos protocolos tengan ya algunos años de vida, pareceque es ahora cuando las empresas proveedoras de infraestructuras software como BEASystems están empezando a darles soporte, para conseguir de una vez por todas la tanansiada integración de voz en las redes de datos.

SUMARIO

ACTUALIDAD12 BEA entra en la red con Da Vinci16 Sun Certified Enterprise Architect for J2EE

DISPOSITIVOS MÓVILES20 Juegos de calidad comercial en J2ME (III)

MIDDLEWARE28 Programación distribuida en .NET (II)36 XAML (IV)

REDES42 Sistemas de mensajería con Java Message Service (I)

DISEÑO50 Together Architect, el enlace entre el problema y la solución54 Diseño multiplataforma para aplicaciones C++ (y III)

Y además…

04 Noticias08 javaHispano: jH.com, joda-time, columna de opinión y más10 Canal Panda: Pharming, nueva técnica de fraude60 Preguntas y respuestas64 Libros: Desarrollo web con PHP66 Contenido del CD-ROM

Otra “sopa de letras”

Asociación Española de Editorialesde Publicaciones Periódicas

Page 3: Revista Solo Programadores #124

NOTICIAS

MICROSOFT

Microsoft desarrolla un nuevo servicio de asesoría y soporte para sus partners ISVs

Microsoft ha puesto en marcha una nueva herramienta enfocada a con-seguir el éxito de sus partners ISVs (fabricantes independientes de softwa-re) y ayudarles a mejorar la satisfacción de sus clientes. Se trata de un ser-vicio de consultoría telefónica diseñado para ayudarles en la creación ydesarrollo de nuevos programas a partir de las tecnologías de la compañía. Con esta consultoría especializada Microsoft mejora notablemente elservicio habitual que se proporciona en concepto de mantenimiento desoftware con una ayuda pro-activa gestionada por un técnico expertoen desarrollo de aplicaciones y nuevos programas, migración de pro-ductos y gestión de códigos.

Este nuevo beneficio forma parte del Partner Program y permite a losISVs seleccionar aquellos servicios que se ajustan a sus necesidadesdentro de una amplia oferta de asesoramiento. En función del nivelalcanzado por el partner dentro del programa, Microsoft ofrece distin-tas horas de asesoramiento: 10 a los partners suscritos al programaEmpower, 15 a los Certified y 20 a los Gold Certified. Los partners quequieran ampliar información sobre este nuevo servicio pueden visitar laweb http://www.microsoft.com/spain/partner/isv/default.asp.Para Susana Núñez, responsable del Programa de Partners en MicrosoftIberica, “este nuevo servicio es un importante valor añadido del que pue-den beneficiarse todos los ISVs. Forma parte del compromiso de perma-nente colaboración que tenemos con todos nuestros partners y nos per-mite mejorar y avanzar juntos en el desarrollo de tecnologías que ayudena mejorar la productividad de las empresas.”

BUSINESS OBJECTS

Crystal Reports XI y Crystal Server XI, la generación de informes rápida y eficaz

Business Objects, proveedor de soluciones de business intelligence, haanunciado dos nuevos productos: Crystal Reports XI y Crystal ReportsServer XI, ambos orientados a dar solución a la generación de informes.

Crystal Reports XILos desarrolladores y otros profesionalesinformáticos necesitan poder accederrápidamente a los datos, integrar confacilidad la funcionalidad de reportingdentro de sus aplicaciones empresariales,y gestionar el formateo y distribución deinformación a través de la web. Para aten-der esta demanda, Crystal Reports XIofrece nuevas funciones, como por ejem-plo mejores controladores de conectivi-dad para acceder con facilidad a cualquierfuente de datos, creación de plantillaspara personalizar informes, herramientasde diseño intuitivas, un banco de trabajo

virutal sobre el que organizary decidir la manera de progra-mar la generación de losinformes, etc.

Crystal Reports Server XI,Crystal Reports Server XI esuna versión orientada a laspequeñas y medianas empre-sas, ya que supone una solución de generación de informes empa-

quetada que incluye todo lo que lasorganizaciones de mediano tamañopueden necesitar para crear, distribuir ygestionar informes a través de la web,integrando las funciones de reportingdentro de sus aplicaciones ofimáticas.Crystal Reports Server XI pone a dispo-sición de las organizaciones las mismasfuncionalidades de generación de infor-mes que las que poseen las grandesempresas, pero sin el coste ni la comple-jidad de esas implantaciones. Además,cuenta con un año de mantenimiento yasistencia técnica.

BEA SYSTEMS

BEA Systems y Eclipse unen sus fuerzas para potenciar la Comunidad Java

BEA Systems y la Fundación Eclipse, una comunidad de código abiertoque centra su actividad en la oferta de una plataforma de desarrollo uni-versal, anuncian que BEA se ha integrado en Eclipse como miembro delConsejo de Dirección y Desarrollador Estratégico de esta organización.Una de las primeras funciones de BEA dentro de Eclipse va a ser el lide-razgo del proyecto WTP (Web Tools Platform). Además, BEA va a propo-ner un nuevo proyecto sobre el Lenguaje de Herramientas de Desarrollo

y también va a fusionar su proyecto decódigo abierto AspectWerkz con el proyec-to AspectJ de Eclipse, como ya adelantó elmes pasado Sólo Programadores en la sec-ción de la comunidad javaHispano.

Actualmente la Fundación Eclipse cuenta con 91 miembros, pero sóloocho de estas compañías figuran como desarrolladores estratégicos.BEA ha sido también elegida para liderar el proyecto WTP (Web ToolsPlatform), que desarrolla herramientas de infraestructura para soportarJ2EE y desarrollo de aplicaciones Web. BEA planea incorporar capacida-des WTP dentro de futuros lanzamientos de BEA WebLogic Workshop.Además de demostrar su compromiso con la Fundación Eclipse desdeel punto de vista corporativo, BEA también tiene previsto anunciarfuturos desarrollos que vendrán a reforzar el compromiso desde elpunto de vista tecnológico. Bajo la denominación de código“Daybreak,” BEA va a diseñar la próxima versión de BEA WebLogicWorkshop, el entorno de desarrollo integrado de la compañía, quesoportará el framework de Eclipse. Daybreak ofrecerá un amplio entor-no de desarrollo que comprende características de Workshop de fáciluso, así como un framework de alta productividad para el desarrollo dearquitecturas orientadas a servicios, además de frameworks de Eclipsey un abanico de plug-ins, también de Eclipse.

http://digital.revistasprofesionales.comSOLO PROGRAMADORES nº 124 4

Page 4: Revista Solo Programadores #124
Page 5: Revista Solo Programadores #124

NOTICIAS

http://digital.revistasprofesionales.comSOLO PROGRAMADORES nº 124 6

BORLAND

Borland presta un mayor soporte a Eclipse

Borland ha ampliado significativamente susoporte a Eclipse, comunidad de código abierto,a la vez que plataforma de desarrollo universalque soporta múltiples lenguajes y tecnologías.

Borland se ha incorporado como desarrollador estratégico a la JuntaDirectiva de la Fundación Eclipse desde donde desempeñará un papelimportante en el progreso de esta tecnología, mediante la aportación deun equipo de desarrollo para ampliar la plataforma Eclipse.Borland fomentará el uso de Eclipse como plataforma a lo largo detoda su línea de productos de gestión del ciclo de vida de las aplica-ciones (ALM). De este modo, junto con el creciente soporte deBorland a Microsoft Visual Studio, la compañía continuará ofrecien-do a los clientes la posibilidad de elegir la tecnología para sus solu-ciones ALM corporativas, mientras contribuye a reducir la crecientecomplejidad de los entornos de TI heterogéneos. Eclipse y VisualStudio se han convertido en dos de las plataformas de desarrollolíderes en la actualidad y Borland ayudará a sus clientes a estrechar

la distancia entre ambas con el fin de que puedan aprovechar mejorlas inversiones que ya han realizado.En este sentido, y para impulsar los avances ALM de la plataformaEclipse, Borland liderará la propuesta para un nuevo marco de modela-do gráfico que se sumará a la tecnología de modelado actual en lacomunidad Eclipse. Y es que no hay que olvidar que el modeladocomienza a cobrar más protagonismo entre las empresas, como vía parareducir la complejidad de TI, mejorar la eficiencia y colaboración de losequipos y acercar los requisitos de TI y de negocio. Como fiel defensor de los sistemas abiertos, de las plataformas inde-pendientes y de la libre elección del cliente, Borland continuará sopor-tando productos y servicios, tanto en Eclipse, como en el marco de tra-bajo Microsoft Visual Studio, mientras también avanza las característi-cas y funcionalidades de su IDE Java JBuilder.

BEA SYSTEMS

BEA Systems ofrece formación permanente y gratuita a sus partners a través de Webinars

BEA Systems ha puesto en marcha un programa de formación continuay gratuita, dirigido a sus partners, que tendrán lugar cada martes hasta elpróximo mes de junio. El plan de formación se imparte a través de

Webinars, seminarios online quetienen como objetivo cualificar alos mejores partners de BEA eincrementar el número de exper-tos en las soluciones de BEA, utili-

zadas actualmente por más de 15.000 empresas de todo el mundo. Lospartners de BEA que quieran participar en los webinars podrán ele-gir entre más de 15 cursos diferentes que analizan contenidoscomo la creación de portales, desarrollos en J2EE, integración deaplicaciones empresariales o estándares de servicios web, entreotras temáticas. También se ofrece información a los partners sobrelas últimas soluciones que BEA lance al mercado, como la nuevaversión de su servidor de aplicaciones BEA WebLogic 9.0 o acerca desu proyecto de código abierto Apache Beehive. Los partners de BEA que quieran participar en su programa de forma-ción pueden consultar la agenda en la URL http://es.bea.com/even-tos/webinars/index.jsp o dirigirse por teléfono al departamento demarketing de BEA Systems (91 384 65 34).

MICROSOFT

Microsoft y Telefónica Móviles firman un acuerdo dirigidoa ofrecer apoyo a los desarrolladores de software

Mauricio Ulargui, director de la División de Desarrolladores dePlataforma de Microsoft Ibérica y José María Soler, director deAplicaciones y MovilForum de Telefónica Móviles España, han firmadoun acuerdo de colaboración por el que ambas compañías se compro-meten a poner en marcha una serie de actividades dirigidas a ofrecersu apoyo a la comunidad técnica de des-arrolladores de software.La importancia que este colectivo haadquirido en el campo de las nuevastecnologías ha llevado a Microsoft yTelefónica Móviles España a crear pro-gramas específicos orientados a losdesarrolladores. MSDN (Microsoft Developer Network) sefundó a principios de 1992 y desdeentonces se ha convertido en el principalvehículo de comunicación que mantienela compañía con esta comunidad. Por su parte, con una antigüedad de másde cuatro años, MovilForum es el foro

que Telefónica Móviles pone a disposición de sus partners para pro-porcionarles la ayuda y los conocimientos necesarios con el fin defomentar el desarrollo de aplicaciones móviles sobre la red MoviStar.El acuerdo alcanzado por Microsoft y Telefónica Móviles España inclu-ye una serie de acciones de colaboración mutua, entre las que cabríadestacar la participación de la operadora en DevDay, el principal even-to que anualmente celebra Microsoft con los desarrolladores de soft-ware, el patrocinio de Microsoft en la Feria MovilForum, dando aconocer la aplicación de su tecnología en el área de la movilidad, lacolaboración de Telefónica Móviles en las sesiones sobre Smart Client

de los eventos MSDN Workshopque se celebren en Madrid yBarcelona, y la incorporación de loselementos de movilidad real pro-pios de Telefónica MoviStar en ISVWalqa Lab, el principal laboratoriotecnológico de Microsoft a disposi-ción de los ISVs españoles. Mauricio Ulargui, director de laDivisión de Desarrolladores dePlataforma de Microsoft Ibérica(izquierda) y José María Soler,director de Aplicaciones yMovilForum de TelefónicaMóviles España (derecha),durante la firma del acuerdo decolaboración.

Page 6: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124 8

JAVAHISPANO

http://digital.revistasprofesionales.com

Actualidad Java de la mano de javaHispanoActualidad Java de la mano de javaHispano

Hasta el presente javaHispano mantenía dosportales, uno dedicado a informar sobre lasúltimas novedades, dar apoyo, formar y, engeneral, servir de cauce para compartir cono-cimiento entre los desarrolladores Java(javaHispano.org); y otro orientado a darsoporte y fomentar el desarrollo de solucio-nes libres en torno a las tecnologías Java(javaHispano.net). En javaHispano estamos convencidos de quelas empresas pueden realizar inestimablescontribuciones a la plataforma Java en gene-ral, y a los desarrolladores y al Software Libreen particular: conocimiento, experiencia,innovaciones, servicios, soluciones, etc. Por

ello hemos decidido crear un portal orientado a todas aquellas empresas que, teniendo líneas de negocio en torno a plataforma Java, ten-gan presencia en países de habla hispana.Este portal podrá ser empleado por las empresas como escaparate y punto de encuentro, sirviéndoles para darse a conocer y presentar losservicios y productos que ofrecen. Para aquellas que lo deseen, javaHispano.com también les permitirá colaborar activamente para incre-mentar el valor del portal mediante la publicación de casos de éxito, informes, noticias y comparativas, así como con cualquier otra inicia-tiva que convierta al portal en una herramienta más útil.Desde el portal se podrán realizar búsquedas entre las empresas registradas por el sector al que pertenecen, por los servicios que ofertan ypor su localización geográfica; así como búsquedas entre los productos ofertados por las empresas por categoría, tecnología y licencia. Enacorde con la filosofía altruista que guía a nuestra organización, darse de alta en el portal y acceder a todos sus servicios es completamen-te gratuito, si bien, dados los gastos de mantenimiento del portal, javaHispano aceptará donativos de las empresas registradas.

javaHispano lanza un nuevo portal dedicado a empresas: javaHispano.com

Una de las clases Java que menos simpatías crea entre los desarrolladores es, sin duda, “java.util.Date”. Susmétodos son poco intuitivos, a menudo no existe un método que nos proporcione la funcionalidad que nece-sitamos y, en la actualidad, la mayor parte de ellos se encuentran "deprecated". A esto se añade el hecho deque las fechas no son inmutables, para muchos una mala decisión de diseño. Joda-time (http://joda-time.sourceforge.net) es una librería Open Source con licencia Apache 2.0 parael manejo de fechas y horas de una manera sencilla y eficiente. Soporta los calendarios Gregoriano,Gregoriano-Juliano, Budista, Copto e ISO8601 y posee un excelente soporte de franjas horarias y loca-lidad. Aunque hace bastante tiempo que el proyecto es funcional recientemente han liberado la ver-sión 1.0. Junto a estas líneas podéis observar un pequeño código de ejemplo, y en el CD-ROM se inclu-ye la propia librería:DateTime dt = new DateTime();

int year = dt.getYear();

String monthText = dt.monthOfYear().getAsText(Locale.ENGLISH);

String monthInFrench = dt.monthOfYear().getAsText(Locale.FRENCH);

String dateAsISO8601Format = dt.toString();

Librería alternativa para el procesado de fechas

Page 7: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 1249

JAVAHISPANOjavaHispano

http://digital.revistasprofesionales.com

Jetbrains, compañía desarrolladora de uno de los principales IDE Java, IntelliJ IDEA, haanunciado que apoyará al movimiento del Sofware Libre regalando licencias de su IDE alos desarrolladores que participen en proyectos libres. Las condiciones para acceder a estaslicencias son participar en un proyecto que: se distribuya bajo una licencia aprobada porla OSI, tenga una web propia y cuente con una comunidad activa. Las peticiones puedenrealizarse desde http://www.jetbrains.com/idea/opensource/application.htm.

IntelliJ IDEA gratis para desarrolladores de sofware libre

Sobre el autorAbraham Otero ([email protected]) es responsable de calidad y miembro de la junta de javaHispano.

JBenchmark (http://www.jbenchmark.com) es una aplicación Java para dispositivos móvi-les que permite medir su rendimiento ejecutando una serie de tests sobre él. Hasta hacepoco JBenchmark constaba de dos versiones, una para MIDP 1.0 y otra para MIDP 2.0.Ahora se añade JBenchmark3D, del cual vemos varias capturas de pantalla junto a estaslíneas, orientado a medir el rendimiento gráfico de los terminales móviles.JBenchmark3D mide la potencia gráfica del dispositivo realizando tests relaciona-dos con el manejo de triángulos, texturas, escenas de bajas calidad para juegosbasados en motores 3D, y escenas de alta calidad para dispositivos con aceleración3D por hardware. Al igual que sus hermanos, JBenchmark3D se descarga gratuita-mente, y los resultados se pueden enviar a la web para ser considerados en las esta-dísticas que, de prácticamente todos los terminales móviles del mercado, se mues-tran en el portal de JBenchmark.

JBenchmark3D: mide la potencia gráfica de tu móvil OPINIÓN

XML: uso y abusoEl XML es un estupendo formato para estructu-rar información jerárquica o en árbol en textoplano, gracias a esta cualidad y a ser una “len-gua franca” independiente de las plataformas,se está usando casi para todo: representaciónvisual (XHTML), descriptor de contenidos (RDF),comunicación de datos y acciones (SOAP), con-figuración y almacenamiento de datos a medi-da, descriptor de tareas en desarrollo (Ant),generación de código (JAXB), descriptor “orto-gonal” entre el lenguaje de programación ymundos paralelos: HTML y código en los frame-works web, descriptores de tablas/clases enEJBs, vínculos con aspectos en AspectWerkz,serialización en XStream etc, por citar ejemplosJava. Parece que tendremos XML para rato.

Sin embargo existe la fuerte tendencia de usarXML como “metalenguaje de programaciónsecuencial”, con ejemplos relevantes como Ant(con gran éxito), algunos frameworks web y el“modelado y coreografía de procesos de nego-cio” en WebServices (BPML, BPEL, CDL etc.). Lasintaxis en ocasiones puede llegar a ser tancompleja que son necesarias herramientas, yadolecen de un gran problema: pobre expresivi-dad. XML presenta grandes dificultades para“expresar” comportamiento que fácilmentepuede expresarse en un lenguaje normal con unbuena API, de hecho, más reutilizable y extensi-ble. Teniendo en cuenta la enorme influenciasintáctica que ha tenido el C/C++ en los len-guajes modernos no sería difícil inventar unanueva lengua franca multiplataforma teórica, laOMG lo hizo con el IDL para declaraciones, elW3C lo usa con éxito para el DOM, ¿Por qué noañadir también comportamiento? ¿Un BehaviorDefinition Language? Más clases, interfaces yherencia y quizás menos XML por favor.

Jose María Arranz Santamaría (jmarranz).Profesor Asociado de la Universidad

Politécnica de Madrid.

Page 8: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Si hasta ahora uno de los fraudes más extendidosera el phishing, consistente en engañar a los usua-rios para que efectúen operaciones bancarias enservidores web con el mismo diseño que un bancoon-line, el pharming entraña aún mayores peligrosque el phishing.Básicamente, el pharming consiste en la mani-pulación de la resolución de nombres enInternet, llevada a cabo por algún código mali-cioso que se ha introducido en el equipo.Cuando un usuario teclea una dirección (comopuede ser www.pandasoftware.com), ésta debeser convertida a una dirección IP numérica,como 62.14.63.187. Esto es lo que se llama reso-lución de nombres, y de ello se encargan los ser-vidores DNS, siglas que corresponden a “DomainName Server”. En ellos se almacenan tablas conlas direcciones IP de cada nombre de dominio. Auna escala menor, en cada ordenador conectadoa Internet hay un fichero en el que se almacenauna pequeña tabla con nombres de servidores y

direcciones IP, de manera que no haga faltaacceder a los DNS para determinados nombresde servidor, o incluso para evitarlo.El pharming consiste en modificar este sistema deresolución de nombres, de manera que cuando elusuario crea que está accediendo a su banco enInternet, realmente está accediendo a la IP de unapágina web falsa.El phishing debe su éxito a la ingeniería social,aunque no todos los usuarios caen en estos trucosy su éxito está limitado. Y además, cada intento dephishing se debe dirigir a un único tipo de serviciobancario, por lo que las posibilidades de éxito sonmuy limitadas. Por el contrario, el pharming puedeatacar a un número de usuarios de banca muchí-simo mayor.Además, el pharming no se lleva a cabo en unmomento concreto, como lo hace el phishingmediante sus envíos, ya que la modificación de DNSqueda en un ordenador, a la espera de que el usua-rio acceda a su servicio bancario. De esta manera, elatacante no debe estar pendiente de un ataquepuntual, como hemos mencionado antes.La solución para esta nueva técnica de fraudepasa, de nuevo, por las soluciones de seguridadantivirus. Las acciones necesarias para llevar acabo el pharming necesitan efectuarse por algu-na aplicación en el sistema a atacar (puede serun fichero exe, un script, etc.). Pero antes depoder ejecutarse esta aplicación, debe llegar alsistema objetivo, evidentemente. La entrada delcódigo en el sistema puede ser a través de múl-tiples vías, tantas como entradas de informaciónhay en un sistema: el e-mail (la más frecuente),descargas por Internet, copias desde un disco oCD, etc. En todas y cada una de estas entradas deinformación, el antivirus debe detectar el ficherocon el código malicioso y eliminarlo, siempre quese encuentre detectado como una aplicacióndañina dentro del fichero de firmas de virus delantivirus.Desgraciadamente, hoy en día nos movemos en unescenario en el que el malware ha adquirido unavelocidad de propagación muy elevada, y los crea-dores son más y ofrecen al resto de la comunidadhacker los códigos fuente para que introduzcanvariaciones y puedan crear ataques nuevos. Los

10

CANAL PANDA

Pharming, nueva técnicade fraudePharming, nueva técnicade fraudeFERNANDO DE LA CUADRA

http://digital.revistasprofesionales.com

Los hackers están intentando, cadavez más, obtener beneficioseconómicos de sus actuaciones y delmalware que crean.

Esquema del proceso deresolución de nombres cuandoaccedemos a los servicios delservidor de Panda Software.

Page 9: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 12411

CANAL PANDAPharming, nueva técnica de fraude

http://digital.revistasprofesionales.com

laboratorios de virus no tienen tiempo sufi-ciente para efectuar la detección y elimina-ción del malware para todos los nuevos códi-gos antes de que lleguen a propagarse enunos pocos PCs. A pesar de los esfuerzos y lamejora de los laboratorios, es humanamenteimposible que se elabore una solución ade-cuada y a tiempo para algunos códigos quese propagan en cuestión de minutos.La solución para este tipo de amenazas nodebe ser, al menos en un primer frente deprotección, una solución reactiva, sino quedeben instalarse sistemas mediante los cualesse detecten no los ficheros en función de fir-mas víricas, sino las acciones que se llevan acabo en el ordenador. De esta manera, cadavez que se intente realizar un ataque al siste-ma de DNS del ordenador (como es el caso delas aplicaciones para pharming), sea recono-cido el ataque y detenido, así como el progra-ma que lo ha llevado a cabo, bloqueado.Sin embargo, existe un peligro añadido aesta nueva técnica de pharming, que resideen los servidores proxies anónimos. Muchosusuarios desean ocultar su identidad (sudirección IP) a la hora de navegar, por lo queutilizan servidores proxy instalados enInternet que llevan a cabo la conexión con laIP del servidor en lugar de la IP del cliente. Enel peor de los casos, uno de estos servidoresproxy puede tener la resolución de nombresalterada, de manera que los usuarios queintenten entrar en su página bancaria (apesar de que su sistema local está perfecta-mente asegurado) sean redirigidos por elproxy a una página con el mismo diseño yapariencia de su banco, pero falsa. Tambiénpodríamos pensar, siendo más positivos, queel servidor proxy ha sufrido algún tipo deataque que altere su sistema de resoluciónde nombres de dominio.En cualquiera de los casos, el problema delpharming se plantea como peligroso, aunquede muy fácil solución. Únicamente con siste-mas capaces de detectar los cambios en laresolución de nombres de Internet en elordenador y con sistemas para su bloqueo,podremos hacer frente a la avalancha decódigos maliciosos que nos espera y queintentan estafar a los usuarios.

Sobre el autorFernando de la Cuadra ([email protected]) es editor técnico internacional dePanda Software (http://www.pandasoftware.com).

El laboratorio anti-virus de Panda Software(PandaLabs) ha detectado recientemente laaparición de Searchmeup, el primer adware (oprograma que muestra publicidad) que utili-za una vulnerabilidad de Microsoft para sus-traer información de los usuarios.Los usuarios de banca on-line se ven expues-tos a esta amenaza simplemente al navegarpor Internet. Este adware se introduce en lasmáquinas sin el consentimiento del usuarioutilizando una vulnerabilidad denominadaExploit/LoadImage.Una vez introducido en el ordenador cambia lapágina de inicio del navegador, dejando en sulugar la de un buscador que, cada vez que secarga, muestra popups que instalan spyware ydialers en el equipo como el troyano Tofger.AT,los dialers Dialer.BB y Dialer.NO, y otro adwaredenominado Adware/TopConvert.Infectado el ordenador, cuando el usuario abreInternet Explorer, Tofger.AT se activa y si elusuario visita uno de los 15 bancos on-linemás importantes de España (páginas conconexiones seguras HTTPS) Tofger.AT captura-rá la contraseña utilizada para acceder a lassiguientes entidades bancarias: cajamadrid,bpinet, millenniumbcp, hsbc, barclays,lloydstsb, halifax, autorize, bankofamerica,bancodevalencia, cajamar, portal.ccm, bancaja,caixagalicia, caixapenedes, ebankinter, caixasa-badell, bes, banif, millenniumbcp, totta, banco-mais, montepiogeral, bpinet, patagon, lacaixa,citibank, bbvanet, banesto, e-trade y unicaja.El usuario infectado no es consciente de laexistencia de Searchmeup a menos que:� Observe el cambio de la página de inicio de

su navegador.� Si se genera un error y se reinicia el orde-

nador en un minuto (lo cual puede noocurrir siempre).

� También puede mostrar pantallas de errorde sistema (pantallazos azules).

La vulnerabilidad Exploit/LoadImage de la quese aprovecha Searchmeup afecta a ordenado-res con sistema operativo Windows 2003/XP/

2000/NT/Me/98, y permite ejecutar código arbi-trario en el sistema. Puede ser aprovechada porun atacante alojando un cursor o icono espe-cialmente creado en una página web maliciosa,o en un mensaje de correo electrónico en for-mato HTML. Para corregir este problemaMicrosoft ha publicado la correspondienteactualización, cuya instalación se recomienda.Para más información, puede visitarse la direc-ción http://www.microsoft.com/spain/technet/seguridad/boletines/MS05-002-IT.mspxAnte el peligro que representa Searchmeup yel troyano Tofger.AT, Panda Software reco-mienda extremar las precauciones y mante-ner actualizado el software antivirus. Losclientes de Panda Software ya tienen a su dis-posición las correspondientes actualizacionespara la detección y desinfección de estosnuevos códigos maliciosos.Asimismo, los clientes de Panda Software yatienen disponibles las actualizaciones parainstalar las nuevas Tecnologías TruPreventjunto con su antivirus y estar, así, protegidosde forma preventiva frente a nuevos códigosmaliciosos. Por otro lado, para usuarios quecuenten con otros antivirus del mercado,Panda TruPrevent Personal es la solución idó-nea, ya que es compatible y complementaria aéstos y proporciona una segunda línea dedefensa y una protección preventiva queactúa mientras el antivirus es actualizado, dis-minuyendo el riesgo de ser infectados. El lec-tor puede conocer más sobre las tecnologíasTruPrevent en http://www.pandasoftware.es/truprevent.Para la detección y desinfección gratuita delos ordenadores, los usuarios pueden utilizarel antivirus on-line Panda ActiveScan, dispo-nible en http://www.pandasoftware.es.

Los usuarios de banca on-line amenazados por un nuevo ladrón de contraseñas

Page 10: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

En el número anterior de Sólo Programadores sepublicaba una noticia que seguramente habrá gene-rado una larga lista de interrogantes en el lector. Endicha noticia, cuyo título fue “El proyecto Da Vinci”,se informaba del lanzamiento de un innovador con-junto de productos por parte de BEA Systems, agru-pados todos ellos bajo el nombre en clave “Da Vinci”.Tal como se informaba en dicha noticia, esta nuevagama de productos va dirigida a la industria de lasTelecomunicaciones, y su objetivo es permitir a lascorporaciones de este sector ampliar el actual abani-co de servicios e incrementar sus beneficios median-te la creación, la gestión y la entrega de serviciosmóviles de una forma ágil y eficaz.Intrigados por este nuevo lanzamiento, y viendo quepuede ser la piedra angular de cambios importantesen la forma de diseñar, implementar y desplegar nue-vos servicios basados en las infraestructuras deTelecomunicaciones, hemos considerado de interés elmantener una charla con Enrique Martín, Director deTecnología de BEA Systems, quien muy amablemen-te no ha dudado en responder a todas nuestras cues-tiones. Esperemos que esta entrevista pueda servirpara que el lector entienda el giro que está a puntode producirse en el sector de las Telecomunicacionesy, por lo tanto, las nuevas tecnologías que la gente deTecnologías de la Información (TI) tendrá que asimilaren sus proyectos futuros.

Sólo Programadores. Tradicionalmente, BEAha ofrecido plataformas de software orienta-das a todos los mercados e industrias. ¿Porqué estamos presenciando ahora el lanza-miento de un producto específico para elmercado de las Telecomunicaciones?Enrique Martín. BEA siempre ha perseguido unaoferta horizontal de middleware orientada a servi-dores de aplicaciones y control de proceso. Con Da

Vinci seguimos en esa visión horizontal pero parti-cularizando en el mundo de las Telecomunicaciones.En realidad sigue siendo la misma filosofía, es decir,BEA sigue siendo un proveedor de infraestructura.Lo que ocurre es que en el mundo de las TI existenestándares muy sólidos como por ejemplo J2EE; encambio, el mundo de las Telecomunicaciones carecede ello, y por eso se construye sobre una tecnologíadistinta en cuanto al propósito, pero muy parecidaen cuanto a la filosofía horizontal. BEA ha queridodar el salto y, sin salir del mundo de la oferta deinfraestructura, ahora queremos ofrecer un produc-to de infraestructura muy particular para el sectorde las Telecomunicaciones.

S.PP. ¿Por qué, desde el punto de vista de BEA,el sector de las Telecomunicaciones necesitaesta infraestructura particular que has men-cionado?E.M. Como te he comentado, el objetivo que persi-guen las corporaciones del sector de lasTelecomunicaciones es llegar a estándares para eldesarrollo de aplicaciones y servicios sobre sus redes,del mismo modo que en el sector de las TI se hanalcanzado estándares del nivel de J2EE. En este sen-tido, la oferta de BEA particularizada en el sector delas Telecomunicaciones consiste en proveer a estasempresas de una infraestructura que ofrezca unaconvergencia total entre los protocolos estándaresde la red y los estándares típicos del mundo de las TI.Aquí es importante entender que cuando menciona-mos “red”, estamos haciendo referencia a toda lainfraestructura de la red de Telecomunicaciones (redde telefonía, de GSM, de UMTS, etc.).

S.PP. ¿Por qué es necesaria esa convergencia?E.M. El sector de las Telecomunicaciones ha llega-do a un punto de inflexión en el que es necesarioun cambio de estrategia. Uno de los factores que hallevado a este punto al propio sector es el hecho deque los servicios se han construido pensando en lapropia estructura de la red, quedando éstos locali-zados y aislados en los propios nodos de la red (ser-vicios de voz, videoconferencia, gestión de tonos,etc.). En la medida en que los operadores de telefo-nía pretendan aumentar su facturación con servi-cios alternativos al de voz, como por ejemplo con

12

ACTUALIDAD

BEA entra en la red con Da VinciBEA entra en la red con Da Vinci

Hablamos con Enrique Martín,Director de Tecnología de BEASystems, sobre el proyecto Da Vinci y el mercado de las Telecomunicaciones.

CARLOS LAPARRA

http://digital.revistasprofesionales.com

Enrique Martín atendió muyamablemente la llamada deSólo Programadores.

Page 11: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

aplicaciones de datos, van a experimentarunos costes altísimos al implantar estos nue-vos servicios con la filosofía actual, es decir,localizándolos en los nodos de la red.En estos momentos ya todos tenemos teléfo-no móvil, por ejemplo. Esto hace muy difícil elque una operadora pueda seguir creciendocon los servicios de voz, lo cual nos lleva a laconclusión de que los servicios y las aplicacio-nes de datos son el nuevo camino a explorar.Pero si la implantación de estos nuevos servi-cios tiene unos costes tan altos... ¿cuál es elfuturo? La solución a esta tesitura pasa poraislar la capa de red (transporte) de la capa deservicio (aplicaciones) y en esta última poderdesarrollar y desplegar aplicaciones con lavelocidad y agilidad que las necesidadescomerciales lo requieran.Con esto se conseguirá tener aplicaciones quepodrán ser usadas por miles de empresas,puesto que se basarán en tecnologías de servi-dor estándares huyendo del carácter propieta-rio de este tipo de redes. Retomando el hilo dela pregunta, la convergencia entre los estánda-res del mundo de las Telecomunicaciones y delmundo de las TI resulta necesaria para poderdesarrollar aplicaciones que obtengan lo mejorde ambos sectores y poder ofrecer así al usua-rio los servicios que está demandando: voz,vídeo y datos.

S.PP. Me ha llamado la atención estoúltimo. ¿A qué te refieres cuando hablasdel carácter propietario de las redes deTelecomunicaciones?E.M. La realidad actual es que si desarrolla-mos una aplicación de datos para una opera-dora (por ejemplo para ofrecer un servicio dedatos a sus usuarios finales), será práctica-mente imposible que esta aplicación pueda seradquirida por otra operadora, dado que cuan-do se desarrolla una aplicación de este tipo,puesto que se debe usar la infraestructura dela red de Telecomunicaciones, es necesario“descender” hasta los niveles de protocolos yestos, efectivamente, son propietarios. Por lotanto, podemos afirmar que la naturaleza delas redes de Telecomunicaciones actualessupone un problema para la nueva orienta-ción del mercado que comentaba antes.

S.PP. ¿Cómo es posible superar esta difi-cultad?E.M. Precisamente en esta línea es en la queestamos trabajando. Es necesario evolucionaresta red, introduciendo interfaces estándares

que permitan el uso de la propia infraestruc-tura de la red con el objetivo de que los servi-cios que se desarrollen sobre ella no le seandependientes.

S.PP. ¿Podrías poner un ejemplo, paraentender claramente el problema quesupone tener una red propietaria?E.M. Sí, y para ello vamos a tomar como refe-rencia la simple acción de enviar un SMS.Tanto si el SMS es enviado desde un teléfonomóvil como si es enviado desde una aplica-ción web, a la postre ambos medios deberánconsumir el servicio de una operadora deTelecomunicaciones. Efectivamente, el opera-dor exhibe un interfaz mediante el cual noso-tros podremos darle el mensaje y éste serviciolo convertirá en un SMS. Pero este operadordeberá mandar el mensaje a través de unhardware que es propietario, puesto que hasido subministrado por alguna de las princi-pales empresas proveedoras de este tipo deequipos. Cada modelo de cada fabricante rea-liza esta acción de una manera distinta, luegoestamos ante un problema únicamente solu-cionable mediante estándares. En este senti-do, haré un paralelismo que será entendidorápidamente por cualquier programador.¿Qué sucedía cuando no había APIs estánda-res para el acceso a bases de datos? Pues sen-cillamente que una aplicación escrita para unSGBD no podía de ninguna manera conectar-se a otro SGBD. Así pues, lo que se consiguióentonces con la estandarización del acceso abases de datos es algo parecido a lo que seestá persiguiendo en la actualidad, pero apli-cado a la infraestructura de las redes deTelecomunicaciones.

S.PP. A lo largo de la entrevista está que-dando clara la importancia que van atener los estándares en la nueva orienta-ción que va a tomar el mercado de las

Telecomunicaciones. ¿Qué estándaresson esos?E.M. Efectivamente, son tres los estándaresmás prometedores del mundo de lasTelecomunicaciones, aquellos que permitenla comunicación de voz y multimedia: SIP,Parlay y JAIN.SIP (Session Initiation Protocol) es el protoco-lo de señalización para voz sobre IP, principal-mente. Simplificando mucho diremos que, enel mundo de la telefonía, al establecer una lla-mada telefónica se están empleando dos cir-cuitos de información. Uno se encarga de laseñalización y el control de la llamada y elotro se encarga puramente de streaming delaudio. Por lo tanto, en el mundo IP SIP será elprotocolo encargado de establecer la llamada.Parlay es un protocolo cuyo objetivo es lahomogeneización de la infraestructura de red,independientemente de quién sea el fabrican-te de esa infraestructura. Retomemos denuevo el ejemplo del envío del SMS propues-to anteriormente. La problemática de haceresto en una red propietaria desaparecería sipudiéramos usar la infraestructura de dichared mediante interfaces estándares. En efec-to, éste es el objetivo de Parlay.Y, por último, comentar de forma muy resu-mida que JAIN representaría un servidor deaplicaciones situado dentro de la propiainfraestructura de la red y que permitiríaconseguir una “red inteligente”.

S.PP. En este escenario, ¿qué soluciónofrece BEA para las empresas del sectorde las Telecomunicaciones?E.M. Básicamente, y de forma resumida,desde BEA se hace una apuesta firme por laconvergencia a la que hacíamos alusión alprincipio de esta conversación. En este senti-do, BEA pretende integrar en su oferta deinfraestructura a los tres estándares delmundo de las Telecomunicaciones (SIP, Parlay

13

ACTUALIDADBEA entra en la red con Da Vinci

http://digital.revistasprofesionales.com

En la figura adjunta puede verse la posición que ocupa el protocolo SIP en la pila deprotocolos.

Page 12: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

y JAIN), ofreciendo así una plataforma opti-mizada para las empresas de este sector. En laactualidad, BEA ya tiene una oferta completapara las compañías de Telecomunicaciones,conocida bajo el nombre de WebLogic ServiceDelivery, que incluye BEA WebLogicCommunications Platform, BEA WebLogicPlatform (Portal, Integration, App Server,Liquid Data Security & Workshop), BEATuxedo, BEA MobileAware Interaction Server,soporte especializado para servicios y soportede empresas de Telecomunicaciones, etc.

S.PP. Entonces, ¿qué es el proyecto DaVinci?E.M. Da Vinci es el nombre en clave de un pro-yecto interno de doce meses de duración deBEA. Da Vinci representa, precisamente, el com-promiso de BEA para suministrar una familia deproductos integrados, que deben facilitar eldesarrollo y despliegue de aplicaciones basadasen las redes de Telecomunicaciones y a la vez enlas Tecnologías de la Información. Más concre-tamente, el producto que da sentido al proyec-to Da Vinci y que BEA ha lanzado recientemen-te es BEA WebLogic Communications Platform.En efecto, BEA WebLogic CommunicationsPlatform es una suite de tecnologías integradasbasada en estándares, diseñada para ayudar alas compañías de Telecomunicaciones a incre-mentar la productividad de sus negocios, mejo-rando su capacidad para crear, distribuir y ges-tionar voz convergente para innovadoras redesde Telecomunicaciones.

Es importante entender que BEA WebLogicCommunications Platform se compone dedos productos: BEA WebLogic SIP Server yBEA WebLogic Network Gatekeeper.BEA WebLogic SIP Server es un servidor deaplicaciones J2EE con soporte de SIP. Esto sig-nifica que podremos seguir desplegandonuestra aplicación en BEA WebLogic SIPServer, puesto que como servidor J2EE, sopor-ta HTTP, servicios web, EJBs, etc. Pero, además,también incluye un contenedor de SIP Servlet,que es el estándar de Java para el uso del pro-tocolo SIP. Existen otras soluciones para el usode SIP, pero la de BEA es la única que funcio-na encima del servidor de aplicaciones, demodo que con esta solución es posible mante-ner la infraestructura de aplicaciones de lacorporación (EJBs, servicios web, etc.) paramantener nuestra lógica de negocio, y agregaraquí los servicios consumibles de la red deTelecomunicaciones mediante el protocoloSIP. Queda claro entonces que es aquí dondeobtenemos la tan famosa convergencia entrela lógica de la aplicación y los servicios queofrece la red de Telecomunicaciones.Por su parte, BEA WebLogic NetworkGatekeeper es una infraestructura que per-mite ofrecer los servicios de red de laempresa (expuestos por BEA WebLogic SIPServer) a los agentes consumidores, peroagregando un componente restrictivo basa-do en políticas de seguridad y de acceso, enfunción de nuestras reglas de negocio.

S.PP. ¿Sería posible apuntar algún ejemplodel tipo de aplicaciones que podríamosdesplegar en BEA WebLogic SIP Server?E.M. Por supuesto. Es necesario entender queel protocolo SIP está pensado para tener uncontrol de la llamada (señalización y estableci-miento). Veamos, técnicamente, cómo esto esposible. En el mundo de la web, cuando desdeun navegador invocamos “http://www...” esta-mos accediendo a un servidor web, el cual nosenviará un documento HTML. En el mundo SIP,bastará con marcar desde nuestro teléfono IP

el número con el que queremos establecer lallamada y el propio terminal enviará algo delestilo “sip://numero_de_telefono”, viajandoesto por la red de Telecomunicaciones como side una petición HTTP se tratara. Lo que ocurrees que esta petición nunca será tratada por unservidor web, sino por un servidor SIP. En efec-to, aquí entrará en acción nuestro Servlet eje-cutándose desde nuestro contenedor de SIPServlet. Desde él, podremos acceder a la infor-mación del número que realiza la llamada, elnúmero destino, etc.Por lo tanto, si podemos tener en nuestroservidor de aplicaciones el control de la lla-mada que desea efectuar el cliente, lasacciones a realizar pueden ser tantas comoseamos capaces de ingeniar.Por ejemplo, imaginemos que queremosconstruir un servicio de prepago. Únicamen-te tendremos que recibir la llamada, identifi-car a nuestro cliente, comprobar si disponede crédito para efectuar la llamada y proce-der en consecuencia, es decir, establecer lallamada o denegarla. De igual modo, podríamos construir un ser-vicio de redirección de llamadas en caso deque la llamada se efectúe a una hora deter-minada o, por ejemplo, establecer que si enel momento de producirse la llamada el telé-fono destino se encuentra ocupado, se debe-rá realizar la llamada inversa cuando la líneaquede libre, etc.Pasando a temas más avanzados, podríamospensar en la construcción de centralitas vir-tuales alojadas en nuestro servidor de apli-caciones o, por ejemplo, en incluir en los for-mularios de nuestra aplicación web unbotón que sirviera para que el usuario pudie-ra solicitar una llamada por parte de laempresa para aclarar cualquier duda sobre elpropio formulario, todo esto en tiempo real.Como ha podido verse, BEA WebLogic SIPServer es capaz de unir el mundo de lasTelecomunicaciones con el mundo de TI,ofreciendo una variedad de servicios y apli-caciones realmente curiosas.

14

ACTUALIDAD

http://digital.revistasprofesionales.com

Un SIP Servlet muy básicopublic class EjemploServlet extends SipServlet {

public void doInvite(SipServletRequest a_Request) throws ServletException, java.io.IOException

{ try {

a_Request.send();} catch (IOException e) {

throw new ServletException(“No se ha podido enviar la request”, e);}

} }

Enrique Martín explicó con toda clase dedetalles los objetivos que persigue elproyecto Da Vinci.

Page 13: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

El objetivo de la certificación como arquitecto J2EEes la evaluación de los conocimientos del aspiranteacerca del diseño de arquitecturas software en elámbito de los sistemas empresariales, especialmen-te centrados en entornos Internet/intranet y sobrela plataforma J2EE. Esta certificación evalúa unaserie de aspectos teóricos y prácticos que veremosmás adelante, como pueden ser modelado conUML, patrones, EJBs o seguridad, entre otros. Tal y como se define en el libro de preparación deesta certificación de Mark Cade y Simon Roberts,el objetivo fundamental de una arquitectura soft-ware es la de cumplir los requerimientos de nego-

cio y los requerimientos de nivel de servicio. Estosúltimos son: rendimiento, escalabilidad, fiabilidad,disponibilidad, extensibilidad, seguridad, etc.Esta certificación forma parte del conjunto de certi-ficaciones ofertadas por Sun dentro de la plataformaJava. La obtención de esta certificación no presentaningún requisito previo, es decir, no es necesarioobtener ningún otro certificado Sun ni haber realiza-do ninguno de los cursos recomendados. De hecho,no es necesario un conocimiento exhaustivo de lasAPIs J2EE aunque si es recomendable el tener ciertaexperiencia como desarrollador en la plataforma.Otras certificaciones ofertadas por Sun son:� Sun Certified Java Programmer (SCJP).� Sun Certified Java Developer (SCJD).� Sun Certified Web Component Developer

(SCWCD).� Sun Certified Business Component Developer

(SCBCD).� Sun Certified Developer for Java Web Services

(SCDJWS).� Sun Certified Mobile Application Developer

(SCMAD).Estas certificaciones se agrupan según su entorno deejecución. SCJP y SCJD están orientadas a la platafor-ma básica Java o J2SE. En el caso de las certificacio-nes SCWCD, SCBCD, SCDJWS junto con la certifica-ción SCEA, que es la que nos ocupa, están centradasen la plataforma J2EE. En último lugar, la certificaciónSCMAD se orienta a dispositivos móviles o J2ME. Paratodas las certificaciones, excepto para la de arquitec-to (SCEA), es requisito imprescindible la obtenciónprevia del certificado como Programador Java (SCJP).Desde un punto de vista profesional, la obtenciónde la certificación SCEA puede resultar beneficio-sa tanto para la empresa como para el empleado.En el caso de la empresa, podrá incluir entre susrecursos disponibles un arquitecto certificadomientras que en el caso del empleado, supone unsalto cualitativo en su historial profesional.Esta certificación se compone de tres partes, que sedetallan en los apartados siguientes, una primeraparte teórica sobre diferentes conceptos, un ejerci-cio práctico y una última prueba teórica acerca denuestro ejercicio práctico. Es importante resaltarque todas las pruebas, tanto las teóricas como lasprácticas, han de realizarse en inglés.

16

ACTUALIDAD

Sun Certified EnterpriseArchitect for J2EESun Certified EnterpriseArchitect for J2EE

En este artículo vamos a tratar dedetallar en qué consiste lacertificación como arquitecto J2EEde Sun, las distintas pruebas que lacomponen, proceso de inscripción yposibles fuentes de documentaciónpara prepararnos este examen.

JAVIER CANO MEDINA (Arquitecto J2EE SCEA)

http://digital.revistasprofesionales.com

Página web en la que Sun informa sobre las notas de las certificaciones.

Page 14: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

SCEA parte I: prueba teórica

La primera parte de la certificación es unaprueba teórica tipo test, compuesta por 48preguntas. Es necesario obtener una notaigual o superior a un 68% para superar esteexamen, disponiéndose de 78 minutos parasu realización. Es importante comentar queen todas las preguntas que componen el testse indica el número de respuestas correctas,lo que a la hora de realizar la prueba suponeuna ayuda bastante importante.Esta prueba, al igual que la tercera parte dela certificación, se realiza en un centroPrometric autorizado, utilizando su equipa-miento hardware y, lógicamente, sin poderutilizar ningún tipo de documentación parala realización del mismo.Una vez finalizada esta primera prueba, sucorrección y la entrega de la nota es inmedia-ta en el propio centro Prometric. Al mismotiempo Sun proporciona una web (http://www.certmanager.net/sun_assignment) donde po-demos consultar las notas de esta y otras cer-tificaciones Sun. Tal y como se comenta en estaweb, la actualización de los resultados se reali-za transcurridos dos o tres días.Los objetivos del examen son:� Conceptos básicos: En este apartado se

trata de evaluar conceptos relacionadoscon la orientación a objetos y el lenguajede modelado UML. Impacto de la heren-cia, encapsulado de funcionalidad y utili-zación de interfaces en la definición dearquitecturas software, así como dibujo einterpretación de diagramas UML.

� Arquitecturas: Los conceptos a evaluaren este apartado están relacionados con laidentificación de las diferentes caracterís-ticas de las arquitecturas en dos capas, trescapas y n-capas, así como su impacto enlos requerimientos a nivel de servicio quecomentábamos anteriormente. Reconocerel impacto de una arquitectura J2EE enestos mismos requerimientos de nivel deservicio e identificar posibles puntos débi-les de una arquitectura software dada.

� Conectividad con sistemas heredados:El objetivo de esta sección es evaluar lacapacidad de determinar cuál es el méto-do más adecuado de acceso a un sistemaheredado (Sistema Mainframe, ERP, etc.)desde una aplicación J2EE.

� Tecnología EJB: Los objetivos a evaluar eneste apartado están relacionados con la uti-lización de Enterprise JavaBeans: clases e

interfaces que componen la definición deun EJB, diferencias entre Stateful y StatelessSession Bean, así como entre Entity Beans ySession Beans, beneficios y coste de la utili-zación de la Persistencia Manejada por elContenedor (CMP) frente a la PersistenciaManejada por el Bean (BMP), descripcióndel comportamiento transaccional de unEJB, seguridad y utilización de DAOs en elacceso a datos desde EJBs.

� Contenedor EJB: Comportamiento delcontenedor EJB a la hora de definir el ciclode vida de los EJB, así como los diferentesmecanismos utilizados por el contenedorpara aumentar la escalabilidad y rendi-miento de las aplicaciones J2EE comopuede ser la definición de pools de instan-cias o la activación/pasivación de EJBs.

� Protocolos: Definir las diferentes carac-terísticas de los protocolos HTTP, HTTPS,IIOP y JRMP, así como identificar el pro-tocolo más apropiado en un escenarioconcreto y determinar los posibles pro-blemas derivados de la presencia de unfirewall en un entorno concreto y utili-zando un protocolo determinado.

� Aplicación de tecnologías J2EE:Definir los aspectos de una aplicaciónsusceptibles de ser implementadosmediante la tecnología J2EE, así comomediante la utilización de EJB.

� Patrones de diseño: Seleccionar elpatrón de diseño (GoF) más adecuadopara ser utilizado en un escenario con-creto, reconocer los beneficios de la utili-zación de los patrones y determinar elpatrón a partir del diagrama UML corres-pondiente.

� Mensajería: En este apartado se evalúa lacorrecta identificación de los escenarios enlos que la utilización de la mensajeríaresuelta adecuada, así como reconocer los

beneficios de la mensajería síncrona yasíncrona. Determinar, dado un escenario,si la utilización de la mensajería resultaadecuada.

� Internacionalización de aplicaciones:Determinar los tres aspectos específicosde una aplicación que resulta necesariomodificar para lograr su internacionaliza-ción. Conocer las clases fundamentalesinvolucradas en este proceso.

� Seguridad: Conocer las restricciones deseguridad aplicadas a la ejecución deApplets en los navegadotes web y dado unescenario específico, determinar la localiza-ción correcta de la implementación de lascaracterísticas de seguridad, así comoseleccionar la tecnología más adecuada.Algunos conceptos importantes en esteapartado son SSL, Certificados y FirmaDigital, Firewalls y DMZ, etc.

Ejemplos de preguntasA continuación se muestran algunos ejem-plos de preguntas de esta primera parte de lacertificación. Además en el libro de MarkCade/Simon Roberts también se incluyenejemplos de preguntas de esta primera parte:1. When should you use CMP? (A) When performance is essential and you

are storing standard data types. (B) When performance is not essential and

you are storing standard data types. (C) When performance is essential and you

are storing complex data types. (D) When performance is not essential and

you are storing complex data types.

2. To create an Enterprise JavaBean youneed the following components:(A) A Home interface, A Remote Interface

and a class that implements either theSessionBean or EntityBean interfaces.

17

ACTUALIDADSun Certified Enterprise Architect for J2EE

http://digital.revistasprofesionales.com

Esquema con las certificaciones de Sun.

Page 15: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

(B) A Home interface and a class thatimplements either the SessionBean orEntityBean interfaces.

(C) A Remote interface and a class thatimplements either the SessionBean orEntityBean interfaces.

(D) A Remote interface and a class thatimplements the EnterpriseBean interface.

3. Which statements are true? (A) ejbPassivate() is called prior to passiva-

tion. (B) ejbPassivate() is called immediately after

passivation. (C) ejbActivate() is called prior to activation. (D) ejbActivate() is called immediately after

activation.

4. JMS provides a full implementation ofclasses for Messaging. (A) TRUE (B) FALSE

5. What are the benefits of asynchro-nous messaging? (A) Less coupling between the sender and

receiver. (B) Network doesn’t have to be available. (C) Does not block the sender. (D) Good for transaction processing.

En el apartado de bibliografía, se citan unaserie de libros y direcciones web que puedenresultar de ayuda en la preparación de estaprimera parte de la certificación.

SCEA parte II: ejercicio práctico

El objetivo de este ejercicio práctico es, unavez demostrados una serie de conocimientosteóricos sobre arquitecturas software y J2EEmediante la superación de la primera partede la certificación, comprobar si el aspirantees capaz de aplicar estos conocimientos a laresolución de un supuesto práctico.Una vez superada la primera parte de la cer-tificación y realizado el pago de este ejerci-cio práctico, podemos descargar la pruebadesde la web http://www.certmanager.net/sun_assignment. No existe restricción encuanto al tiempo que puede transcurrir entrela realización de la primera parte y el abonode la matrícula de esta segunda prueba.En el fichero JAR descargado se incluye enformato HTML la descripción del problemaplanteado, la documentación necesaria parasu resolución así como el formato de la solu-ción a entregar y los distintos aspectos atener en cuenta en su corrección.Esta solución debe presentarse también enformato HTML. Es obligatorio que al soluciónesté compuesta por diagramas de clases,diagramas de componentes y diagramas desecuencia y/o colaboración, no especificán-dose el número de diagramas de cada tipoque debe presentarse. También es recomen-dable que se incluya documentación expli-cando los planteamientos previos quehemos tenido en cuenta a la hora de resol-ver el ejercicio, así como una explicacióndetallada de nuestra solución.

Según se especifica en la documentaciónque acompaña al ejercicio práctico, los dia-gramas de clases tienen un peso igual a 44en la nota final, donde la correcta utilizacióndel lenguaje UML tiene una nota máxima de10 mientras que la resolución de los reque-rimientos expresados en el ejercicio tieneuna nota máxima de 34.En el caso de los diagramas de componentesla proporción es la misma, 10 frente a 34para un total de 44.En el caso de diagramas de secuencia/colabo-ración la nota total máxima es 12, otorgándo-se una nota máxima de 3 a la correcta utiliza-ción del lenguaje UML, mientras que el cum-plimiento de los requerimientos del sistemase puntúa como máximo con una nota de 9.Una vez que demos por concluido nuestroejercicio, para la entrega de la solución nosdirigiremos a la web de Sun ya comentadadonde deberemos tener habilitado un botón“Upload” que nos permitirá enviar la soluciónpara su evaluación. Esta solución debe enviar-se en formato JAR y el nombre del fichero aenviar debe contener el identificador del can-didato, suministrado por Sun al realizar unprimer examen de certificación Java.Para la preparación de esta segunda parte dela certificación, puede resultar especialmen-te interesante el libro “Designing EnterpriseApplications with the J2EE Platform “, asícomo los libros relacionados con patrones,tanto de diseño como J2EE.

SCEA Parte III

Después de enviar el ejercicio práctico, seránecesario realizar la tercera y última prueba.Se trata de una prueba teórica consistente en4 preguntas sobre la forma en que hemosresuelto el ejercicio práctico de la segundaparte, siendo necesario argumentar nuestrasdecisiones a la hora de definir la arquitecturade nuestra solución.El tiempo disponible para su realización esde 90 minutos y, al igual que la primeraparte de la certificación, esta prueba se tieneque realizar en un centro Prometric, previaadquisición del vouncher correspondiente yconcertada la prueba en dicho centro.La nota obtenida en esta tercera parte es lacombinación de la evaluación del ejerciciopráctico y de esta tercera prueba. El procesode corrección dura entre cuatro y seis sema-nas, pudiéndose consultar el resultado de lamisma en la web anteriormente citada.

18

ACTUALIDAD

http://digital.revistasprofesionales.com

Página web de Sun con información de las certificaciones Java.

Page 16: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

A la hora de afrontar esta última prueba, noexiste ninguna bibliografía que debamos revi-sar, siendo importante, por supuesto, haberresuelto el ejercicio práctico por nuestros pro-pios medios y que no haya transcurrido dema-siado tiempo entre la finalización del ejerciciopráctico y la realización de esta última prueba.Una vez superadas las tres pruebas y trans-curridas algunas semanas, Sun se encargade enviar el certificado como arquitecto J2EEmediante envío postal.

Proceso de Inscripción

El proceso de inscripción en cada uno de losexámenes es siempre el mismo. Como primerpaso, debemos ponernos en contacto con Sunpor teléfono (902 210 412) o por correo elec-trónico ([email protected]) para confirmar lascantidades a abonar para cada una de laspruebas ya que éstas pueden cambiar, ademásen el caso de particulares no es necesario elpago del IVA de cada una de las pruebas.Una vez confirmadas las cantidades, proce-deremos a realizar la transferencia de la can-tidad correspondiente a la cuenta indicadapor Sun y haremos llegar el justificante delpago mediante fax o correo electrónico.En el caso de la primera y tercera prueba, reci-biremos en la dirección que indiquemos elvouncher que utilizaremos para concertar elexamen en un centro Prometric autorizado.En el caso del ejercicio práctico no recibimosvouncher ya que no debemos realizarlo enningún centro autorizado. En los tres exáme-nes sí recibiremos la factura correspondiente.A la hora de concertar el examen con el centroPrometric, se nos solicitará el vouncher envia-do por Sun, siendo recomendable que confir-

memos que no es necesario abonar ningunacantidad extra para la realización de la prueba.En el caso de no superar la segunda/terceraparte del examen, existe la posibilidad devolver a enviar el ejercicio práctico para quevuelva a ser evaluado, no siendo necesaria larealización de la tercera parte del examen.

Bibliografía

Algunos libros recomendables para la prepa-ración de esta certificación se detallan acontinuación:� Sun Certified Enterprise Architect for

J2EE Technology: Study Guide, porMark Cade/Simon Roberts. SunMicrosystems Press.

� Designing Enterprise Applicationswith the J2EE Platform, SecondEdition, por Inderjeet Singh, BethStearns, Mark Johnson, and theEnterprise Team. Disponible en la web deSun (http://www.sun.com).

� UML Distilled, por Martin Fowler,Kendall Scott. Addison Wesley.

� Applying UML and Patterns: An Introto OOA/D and the Unified Process, porCraig Larman. Prentice-Hall.

� Enterprise JavaBeans, por RichardMonson-Haefel, O’Reilly & Associates.

� Dessign Patterns: Elements ofReusable Object-Oriented Software,por Gamma et Al. Addison-Wesley.

� Core J2EE Patterns: Best Practices andDesign Strategies, por Deepak Alur, JohnCrupi, Dan Malks. Sun MicrosystemsPress.

� EJB Design Patterns, por Floyd Marinescu.Wiley Computer Publishing, disponible enla web http://www.theserverside.com.

Por otro lado, en Internet existen multitudde páginas donde es posible obtener infor-mación relativa, especialmente, a la primeraparte de la certificación como arquitecto, asícomo simuladores de esta primera parte.Páginas de Preparación SCEA y Foros:� http://www.stormpages.com/jnagal/index

.html� http://www.leocrawford.org.uk/work/jcea

/part1/index.html� http://prasks.webahn.com/� http://saloon.javaranch.com/cgi-bin/

ubb/ultimatebb.cgi?ubb=forum&f=26Páginas con Simuladores del Examen SCEAparte I:� http://www.ianswebpage.com/cert/scea/

scea.htm� http://prasks.webahn.com/� http://www.javacoding.net/certification/

mocks/index.html

19

ACTUALIDADSun Certified Enterprise Architect for J2EE

http://digital.revistasprofesionales.com

Códigos de las pruebas que componen la certificación de arquitecto J2EENombre de la prueba Código

Sun Certified Architect for J2EE – Part I CX-310-051

Sun Certified Ent Architect for Java J2EE tech., Assignment CX-310-300A

Sun Certified Architect for J2EE – Part III CX-310-061

Sun Certified Enterprise Architect for J2EE Technology,Assignment Resubmission CX-310-300R

Página web con información sobre la plataforma J2EE. Buscador de centros Prometric.

Page 17: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

En la entrega anterior de este curso terminamospresentando la API propietaria de Nokia, centrán-donos en todo lo que a nivel gráfico hacía referen-cia. En esta tercera entrega del curso continuare-mos profundizando en esta importante API paradescubrir qué más aporta a MIDP 1.0. Concluiremoseste artículo con otras dos APIs opcionales, laMobile Media API (veremos un MIDlet que accede ala cámara de nuestro teléfono), y la WirelessMessaging API (con la que haremos un envío de unSMS desde nuestro programa).

Continuando con la Nokia UI API

Detección de tecladoPara detectar las pulsaciones de teclado a bajo nivelno necesitamos usar explícitamente la Nokia UI API,ya que MIDP 1.0 (véase la referencia 1) nos propor-ciona funcionalidad suficiente en este sentido. Sinembargo, vamos a ver en este apartado algunasaportaciones de esta API a la detección de teclado.Para este fin, empezaremos viendo el uso de laclase “Canvas”, que es la que en MIDP 1.0 incorpo-ra las funciones relacionadas con este aspecto:� keyPressed(int keyCode): Evento que se

levanta al pulsar una tecla (o detecta la pulsa-ción continuada de la misma).

� keyRepeated(int keyCode): Evento que selevanta mientras mantengamos pulsada unatecla. No lo utilizaremos porque se consigueuna respuesta muy lenta del teclado. Comoveremos en breve, usaremos otro enfoquepara detectar una pulsación continuada deteclado.

� keyReleased(int keyCode): Evento que selevanta al dejar de pulsar una tecla.

� pointerPressed(int x, int y): Evento que selevanta en terminales con pantalla táctil al pul-sar con el lápiz.

� pointerDragged(int x, int y): Evento que selevanta en terminales con pantalla táctil alarrastrar el lápiz por la pantalla. Se levantasiempre, como es lógico, después de un evento“pointerPressed”.

� pointerReleased(int x, int y): Evento que selevanta en terminales con pantalla táctil allevantar el lápiz.

Como no estamos programando para terminalescon pantalla táctil no hablaremos de los tres últi-mos métodos, que, por otra parte, no entrañanninguna dificultad en su uso.Observaremos que los tres métodos de detecciónde teclado reciben un parámetro llamado“KeyCode”. Para facilitar la portabilidad de las apli-caciones J2ME, la clase “Canvas” tiene un métodoque nos traduce ese “KeyCode” a teclas relaciona-das con una acción típica de un juego; las llama-das “Game Actions”. Con esto se consigue que unterminal al ejecutar nuestro juego se encargue de“mapear” las teclas por nosotros y que, por ejem-plo, un usuario use en nuestro juego la tecla queel fabricante ha estimado más oportuna para dis-parar, o las teclas de dirección para mover al per-sonaje. El método que nos provee esta traducciónes:public int getGameAction(int keyCode)

Este método nos devuelve un entero que debere-mos comparar con las constantes de la clase“Canvas” para saber qué tecla se pulsó tal y comose aprecia en el listado 1.En el código de este primer listado podemosobservar cómo estamos detectando la pulsación

20

DISPOSITIVOS MÓVILES

Como se está viendo a lo largo deeste curso, el API de Nokia ofreceun conjunto muy avanzado deposibilidades. En esta tercera entregaestudiaremos, entre otras cosas, elcontrol de la luz de la pantalla, lagestión del sonido, el acceso a lacámara de fotos del teléfono y elenvío de SMS.

ALBERTO GUTIÉRREZ MARTÍNEZ (Ingeniero en Informáticay co-fundador de Flag Solutions)FRANCISCO JOSÉ GARCÍA PEÑALVO (Profesor titular deldepartamento de Informática y Automática de laUniversidad de Salamanca)

http://digital.revistasprofesionales.com

Juegos de calidad comercial en J2ME (III)Juegos de calidadcomercial en J2ME (III)Uso de APIs adicionalesUso de APIs adicionales

Hacer una fotoo enviar un SMS

son accionesfáciles de hacer

con el API de Nokia

Page 18: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

simultánea de la tecla de disparo y de unatecla de dirección. No tiene sentido detectarla pulsación simultánea de dos teclas dedirección porque en los terminales telefóni-cos no se pueden pulsar a la vez (salvo en elnuevo Nokia N-Gage QD). Como vemos,aunque recogemos las pulsaciones en loseventos “keyPressed” y “keyReleased”, norespondemos a su pulsación hasta el méto-do “moverJugador”, que forma parte denuestro “game loop” del que hablaremos enpróximos artículos.Si, como es nuestro caso, queremos usar laclase “FullCanvas” de Nokia que vimos en elartículo anterior para poner nuestros juegos apantalla completa, como ya sabemos no pode-mos usar ni “addCommand” ni“setCommandListener”. Esto implica que ahoralas teclas que normalmente se usaban paramanejar estas órdenes en la clase “Canvas” (lasllamadas “soft keys” de Nokia), se puedandetectar con la clase “FullCanvas” (con las“Game Actions” de la clase “Canvas” no es posi-ble). Nuestro juego necesitará ser capaz desaber cuándo el usuario pulsa las “soft keys” porejemplo para pausar el juego y mostrar el típi-co menú que permita salir del juego o cambiarconfiguraciones mientras el juego ya estáempezado. La clase “FullCanvas” añade nuevasteclas a las “Game Actions” adicionales a las dela clase Canvas (que también se pueden usar).La figura 1 muestra las constantes de la clase“FullCanvas” y las teclas con las que se mapean.

Si no vamos a necesitar que nuestro juegodetecte las “soft keys” podemos usar sin pro-blemas el mismo código que hemos visto en

el listado 1. En cambio si, como es usual,estamos obligados a detectarlas, es muyrecomendable cambiar nuestro código por elque se presenta en el listado 2.Hay un par de cosas a resaltar en el código deeste segundo listado. En primer lugar, ya noestamos usando la función “getGameAction()”.Si la usáramos comprobaríamos que no detec-tamos en el switch ninguna tecla correspon-diente a las constantes definidas en la clase“Canvas”. Por otro lado, también debemosfijarnos en que para detectar el disparo esta-mos usando la constante “KEY_NUM2”,correspondiente a la tecla del número 2 denuestro teléfono. La razón es que, salvo en laN-Gage, en el resto de teléfonos de la serie 60no se puede simultáneamente pulsar la teclade disparo y una dirección. Si nos queremosolvidar del problema de teclados tan distintosentre sí, es recomendable incorporar a nuestrojuego un módulo de configuración de tecladopara que el usuario lo ponga a su gusto, yalmacenar su configuración mediante RMS(Record Management System, véase el artícu-lo “Persistencia de datos con J2ME” en elnúmero 119) en el teléfono.

21

Juegos de calidad comercial en J2ME (III)DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 1 Detección de teclas con MIDP 1.0 estándar

public void keyPressed(int keyCode) { if (Canvas.FIRE == getGameAction(keyCode)) disparando=true;else TeclaPulsada=getGameAction(keyCode);

}

public void keyReleased(int keyCode) {if (Canvas.FIRE == getGameAction(keyCode)) disparando=false;//Le damos un valor que no se corresponda con ninguna teclaelse TeclaPulsada=1000;

}

public void moverJugador () {

switch(TeclaPulsada) {case Canvas.FIRE:

mensaje=”Estás pulsando DISPARO”;break;

case Canvas.UP: mensaje=”Estás pulsando ARRIBA”;break;

case Canvas.DOWN: mensaje=”Estás pulsando ABAJO”;break;

case Canvas.LEFT: mensaje=”Estás pulsando IZQUIERDA”;break;

case Canvas.RIGHT: mensaje=”Estás pulsando DERECHA”;break;

default:mensaje=”No detecto pulsación”;break;

}}

Figura 1. Mapeado de teclas de un 3650 con “FullCanvas”.

Page 19: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Vibración y control de luz de pantallaSeguramente el lector apasionado de los juegosen los móviles habrá observado cómo muchosjuegos vibran cuando, por ejemplo, nuestra navese golpea con un objeto, o cómo la pantalla par-padea cuando hay una explosión. Pues bien,estos efectos no son posibles con MIDP 1.0(aunque sí lo son con MIDP 2.0 y con la Nokia UIAPI). Vamos a ver un ejemplo en el que se usanalgunos métodos sencillos que nos permitencontrolar la vibración y la luz del teléfono.Los métodos relacionados con vibración yluz pertenecen a la clase “DeviceControl” yson todos estáticos. Son los siguientes:� static void flashLights(long dura-

tion): La luz del móvil parpadearádurante los milisegundos que se le indi-quen en el parámetro “duration”.

� static void setLights(int num, intlevel): En la mayoría de los casos sólopodremos encender y apagar la luz traserade la pantalla del móvil. En algunos termi-nales podremos elegir sobre qué luz actuar(con el parámetro “num”), y qué nivel deluminosidad tendrá.

� static void startVibra(int freq, longduration): Hace vibrar el móvil a la fre-

cuencia elegida durante el tiempo elegi-do. Cuando llamamos a esta función nose queda esperando a que acabe la vibra-ción sino que internamente crea un hiloque la controla, por lo que podremossimultáneamente realizar otra acciónmientras el teléfono sigue vibrando.

� static void stopVibra(): Para unavibración antes del tiempo para el que seprogramó.

En el listado 3 mostramos el código fuentede un MIDlet que usa estos métodos y quetiene el aspecto que muestra la figura 2.

SonidoPara reproducir sonido con MIDP 1.0 en un telé-fono de la serie 60 tenemos dos opciones: usarla Nokia UI API o la Mobile Media API (JSR-135)

(salvo en el Nokia 7650 que no soporta esta API).Las clases relacionadas con el sonido en MIDP2.0 son un subconjunto de la Mobile Media API,que será tratada en el siguiente apartado, sinembargo, para la mayoría de los terminalesNokia que no soporten MIDP 2.0 sólo tendre-mos como opción usar la Nokia UI API.

Cuando utilizamos la Nokia UI API, nos tene-mos que limitar a 3 formatos:� WAV: Formato binario (array de bytes).� Smart Messaging Ringtones: Formato

binario (array de bytes).� Tonos simples: Vienen dados por su fre-

cuencia y duración.

22

DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 2 Detección de teclas con la Nokia UI API

public void keyPressed(int keyCode) {if (FullCanvas.KEY_NUM2 == keyCode || FullCanvas.KEY_SOFTKEY3 == keyCode)

disparando=true;else TeclaPulsada=keyCode;

}

public void keyReleased(int keyCode) {if (FullCanvas.KEY_NUM2 == keyCode || FullCanvas.KEY_SOFTKEY3 == keyCode)

disparando=false;//Le damos un valor que no se corresponda con ninguna teclaelse TeclaPulsada=1000;

}

public void moverJugador () {

switch(TeclaPulsada) {case FullCanvas.KEY_UP_ARROW:

mensaje=”Estás pulsando ARRIBA”;break;

case FullCanvas.KEY_DOWN_ARROW: mensaje=”Estás pulsando ABAJO”;break;

case FullCanvas.KEY_LEFT_ARROW: mensaje=”Estás pulsando IZQUIERDA”;break;

case FullCanvas.KEY_RIGHT_ARROW: mensaje=”Estás pulsando DERECHA”;break;

default:mensaje=”No detecto pulsación”;break;

}}

¡Advertencia!Si tienes un teléfono de la serie 60 de Nokiaseguramente te habrás dado cuenta de que losjuegos Java nunca tienen la opción de vibración.La razón no es otra que la falta de soporte paraesta funcionalidad de la serie 60. Si pruebas elejemplo en el emulador de la serie 60 verás queno da ningún fallo pero simplemente no ocurrenada. Lo mismo pasa con la luz trasera.

¡Advertencia!En cualquier teléfono Nokia compatible conMIDP 2.0 no deberemos usar las clases de laNokia UI API que se usen para el mismo fin quelas que existan en MIDP 2.0. Este es el caso, porejemplo, de las clases relacionadas con el sonido.En un 6600, por ejemplo, Nokia no asegura quela clase “Sound” de la Nokia UI API funcionecorrectamente. Lo mismo ocurre con otras clasesde esta API que han sido declaradas “Deprecated”.

Figura 2. MIDlet de vibración y backlight.

Figura 3. Aplicación de capacidadessonoras en ejecución.

Page 20: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Sin embargo, cada terminal Nokia puede sercompatible o no con estos tres formatos.Cada terminal es un “mundo” y encontrare-mos teléfonos como el Nokia 6230 quepuede reproducir el formato MP3 de formanativa y, sin embargo, no soporta este for-mato desde aplicaciones Java. Para saberqué formatos son compatibles y el númerode sonidos concurrentes que se pueden uti-lizar, la clase “Sound” de Nokia tiene variosmétodos a tal efecto:� static int getConcurrentSoundCount(int

type): Devuelve el número de sonidos

concurrentes que se pueden reproducirdel tipo dado. Normalmente, sólo sepodrá reproducir un sonido a la vez.

� static int[] getSupportedFormats():Devuelve una matriz con todos los for-matos compatibles.

En el listado 4 se puede apreciar cómo seutilizan estos métodos. En este programa semuestran por pantalla todos los formatos deaudio que podremos usar en J2ME para elterminal. Hay que llamar la atención sobreuna línea del programa:int[] formatos= miSnd.getSupportedFormats();

Este método, que en la documentación apare-ce declarado como “static”, en la práctica no loes y debemos instanciar un objeto de la clase“Sound” para poder utilizarlo. Además, ymucho más importante, es necesario saberque este programa dará un error irrecuperablecuando se ejecute dicho método en cualquierteléfono de la serie 40 developer platform 1.x.El programa del listado 4 tiene el aspecto quese ilustra en la figura 3 al ejecutarse.

Todas las posibilidades sonoras de la Nokia UIAPI giran en torno a la clase “Sound” y a lainterfaz “SoundListener”. Para comprender eluso de estas dos clases se ha codificado unnuevo programa, cuyas fuentes por motivosde espacio no se mostrará en su totalidad,aunque se puede encontrar en el CD-ROMque acompaña a la revista. No obstante, mos-traremos las porciones de código más intere-santes y las explicaremos a continuación.El programa que hemos desarrollado enesta ocasión nos permite reproducir los trestipos de formatos sonoros posibles, asícomo recoger su estado de reproducción,que se mostrará en la parte superior del“Form” tal y como muestra la figura 4.

23

Juegos de calidad comercial en J2ME (III)DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 3 MIDlet con vibración y control de luz trasera

import javax.microedition.lcdui.*;import javax.microedition.midlet.MIDlet;import javax.microedition.midlet.MIDletStateChangeException;import com.nokia.mid.ui.DeviceControl;

public class Principal extends MIDlet implements CommandListener {

List myScreen;Command vibrar,flash,luzTrasera;boolean luzOn=true;

public Principal() {super();

}

protected void startApp() throws MIDletStateChangeException {myScreen = new List(“Efectos de la NOKIA UI API”, List.IMPLICIT);myScreen.append(“Vibrar”,null);myScreen.append(“Flash”,null);myScreen.append(“Luz ON/OFF”,null);myScreen.append(“Salir”,null);myScreen.setCommandListener(this);Display.getDisplay(this).setCurrent(myScreen);

}

protected void pauseApp() {}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {}

public void commandAction(Command c, Displayable d) {if (d == myScreen) {

if (c == List.SELECT_COMMAND) {switch (myScreen.getSelectedIndex()) {

case 0: DeviceControl.startVibra(100,2000);break;

case 1:DeviceControl.flashLights(8000);break;

case 2:if (luzOn) DeviceControl.setLights(0,0);else DeviceControl.setLights(0,100);luzOn=!luzOn;break;

case 3:try { destroyApp(false); }catch (Exception e) { }notifyDestroyed();break;

}}

}}

}

¡Advertencia!Hay que saber que las implementaciones deMIDP de Nokia suelen tener pequeñas variacio-nes entre sí, ¡incluso entre distintas versiones desoftware de un mismo modelo de móvil!Comprobaremos en numerosas ocasiones cómoalgunos métodos de APIs soportadas no funcio-nan como se espera o simplemente no estánsoportados. Además, muchos de estos problemasno están documentados, y Nokia sólo da estainformación a las empresas que forman parte delForo Nokia Pro que es de pago. Sin embargo,Nokia pone de forma gratuita a disposición delos desarrolladores numerosas herramientas,documentación y foros en la direcciónhttp://www.forum.nokia.com/main.html.

Figura 4. Aplicación de reproducción deaudio en ejecución.

Page 21: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

El programa consta de dos clases,“Principal.java” y “Sonido.java”. La primera claseusa la clase “Sonido”, que es un envoltorio de laclase “Sound”, para reproducir los distintos tiposde sonido según la opción elegida. Además,implementa la interfaz “SoundListener” (ademásdel “CommandListener”), con el que podremosdetectar cuándo el estado de un sonido cambia,y mostrarlo en el título del “Form”. En el listado 5se muestra el método “soundStateChanged()”de la clase “Principal.java” que gestiona los esta-dos del sonido.Para que se levante el evento “soundStateChanged” le hemos añadido un método anuestra clase “Sonido” similar al de la clase“Sound”, al que invocamos desde la clase“Principal” (véanse los listados 6 y 7).En la clase “Principal” también es de destacarel array de bytes que se muestra en el lista-do 8, que no es más que un fragmento deuna canción en formato “SmartRingTone”.De la clase “Principal” no destacaremos nadamás. Nos fijaremos ahora en la clase “Sonido”.Esta clase como se ha señalado antes, es unwrapper o envoltorio de la clase “Sound” deNokia que facilita su uso, sobre todo a la horade crear el sonido. La clase tiene tres cons-tructores, uno para cada tipo de sonido.Vamos a fijarnos en el constructor que creaun sonido WAV (véase el listado 9) porque esquizá la única parte del código que no esauto explicativa, sobre todo el método“getTamanno()”. El constructor primero llamaa la función “getTamanno()” para conocer eltamaño del archivo WAV que se va a abrir yreservar memoria para una matriz de bytesdel mismo tamaño. Posteriormente, lee elarchivo a esa matriz y se la pasa al construc-tor de la clase “Sound” de Nokia.Quizá el método más interesante sea el“getTamanno()”. Para entenderlo hay que com-prender el formato interno de un fichero WAV,cuya cabecera mostramos en la figura 5.En la cabecera de un WAV tenemos el tama-ño del archivo en los bytes del 8 al 5, es decir,que el archivo al que pertenece el fragmen-to de la figura 5 tendría un tamaño de: 00 0039 24 bytes; que es un número hexadecimalque transformado en decimal nos daría untamaño de: 16.628 bytes (14,28KB).Este proceso es lo que hace el código delmétodo “getTamanno()”. Abrimos el archivo y

leemos el primer entero (32 bits) y lo alma-cenamos en la variable cabecera que novamos a utilizar para nada. Habríamos leído

ya 52 49 46 46, ahora empezamos a leerbyte a byte los cuatro bytes que codifican eltamaño: tam4=24, tam3=39, tam2=00 ytam1=00. Para terminar se invierte el ordende las variables y se transforma el númeroobtenido a decimal. El código del método serecoge en el listado 10.

24

DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 4 MIDlet que muestra formatos de sonido compatibles

import javax.microedition.midlet.MIDlet;import javax.microedition.midlet.MIDletStateChangeException;import com.nokia.mid.sound.Sound;import javax.microedition.lcdui.*;

public class Principal extends MIDlet {

Form miForm;

public Principal() {super();

}

protected void startApp() throws MIDletStateChangeException {miForm = new Form(“Propiedades de Sonido”);String msg=””;try {

msg=”Tonos Simultáneos=“+Sound.getConcurrentSoundCount(Sound.FORMAT_TONE);

} catch (Exception e) {msg=”No Soporta Tonos”;

}StringItem strItm=new StringItem(“Polifonía”, msg);miForm.append(strItm);try {

msg=”Wavs Simultáneos=“+Sound.getConcurrentSoundCount(Sound.FORMAT_WAV);

} catch (Exception e) {msg=”No Soporta Wavs”;

}strItm=new StringItem(“Polifonía”, msg);miForm.append(strItm);//Según la documentación de Nokia es un método estático//pero en la práctica no lo es, y hay que crear un objeto Sound//Además, este método inexplicablemente no funciona para la serie 40Sound miSnd=new Sound(10,1000);int[] formatos= miSnd.getSupportedFormats();if (formatos.length > 0) {

for (int i=0;i<formatos.length;i++) {switch (formatos[i]) {

case Sound.FORMAT_TONE:strItm=new StringItem(“Formatos Compatibles”, “Tonos”);miForm.append(strItm);break;

case Sound.FORMAT_WAV: strItm=new StringItem(“Formatos Compatibles”, “WAV”);miForm.append(strItm);break;

default: strItm=new StringItem(“Formatos Compatibles”, “Formato

Desconocido”);miForm.append(strItm);

}}

}else {strItm=new StringItem(“Formatos Compatibles”, “Ninguno”);miForm.append(strItm);

}Display.getDisplay(this).setCurrent(miForm);

}

protected void pauseApp() {}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {}

}

Figura 5. Cabecera de un fichero WAV.

Page 22: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Aunque habría otras maneras de cargar unarchivo WAV, ésta quizá sea la más óptima,aunque como hemos visto implica conocerel formato binario del archivo.Una vez más comprobaremos que Nokia nonos avisa de determinados fallos. Si proba-mos este MIDlet, nos encontraremos convarias sorpresas:� En el emulador del 7210 el Smart Ring

Tone se oye pero mucho más rápido queen el terminal real, en el que la canción síse oye como debiera.

� En el emulador de la serie 60, el Smart RingTone no se oye y ni siquiera se levanta elevento “SoundListener”. En el terminal realfunciona perfectamente.

� En la documentación de la Nokia UI API sehace referencia a que se usen los Smart RingTones en vez de los Simple Tones. Y es que,aunque no lo pone en ninguna parte, lostonos simples no funcionan en la serie 60developer platform 1.x (ni en el emulador nien el terminal real). Sin embargo, en la serie60 developer platform 2.0 sí que funcionan.

Mobile Media API (JSR-135)

Ya conocemos esta API estándar de SUN, quecomo vimos no está soportada en su totalidadpor la serie 60 de Nokia. En MIDP 2.0 usaremosesta API, entre otras cosas, para reproducir soni-dos en vez de usar APIs de los fabricantes tal ycomo vimos anteriormente. En este apartadovamos a mostrar un ejemplo de una de las múl-tiples posibilidades que tiene esta API, capturaruna instantánea con la cámara del móvil.

La aplicación que vamos a mostrar está basa-da en un documento de Nokia llamado“Camera MIDlet: A Mobile Media API example”y está disponible en el área de desarrolladoresde su web en http://www.forum.nokia.com. Lafigura 6 muestra el diagrama de clases delMIDlet.Por motivos de espacio comentaremos lasporciones de código más interesantes. El

25

Juegos de calidad comercial en J2ME (III)DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 5Fragmento de código que gestiona los estados del sonido

// Principal.javapublic void soundStateChanged(Sound s, int evento) {

switch (s.getState()) {case Sound.SOUND_PLAYING :

myScreen.setTitle(“Reproduciendo”);break;

case Sound.SOUND_STOPPED : myScreen.setTitle(“Parado”);break;

case Sound.SOUND_UNINITIALIZED : myScreen.setTitle(“No Inicializ.”);break;

}}

LISTADO 8 Fragmento de un array de bytes de unSmartRingTone

// Principal.javapublic byte[] data={

(byte)0x02, (byte)0x4a, (byte)0x3a, (byte)0x40, (byte)0x04, (byte)0x01, (byte)0x9d, (byte)0x1c, (byte)0x82, (byte)0xf4, (byte)0x21, (byte)0x02, (byte)0x14, (byte)0x2f, (byte)0x42, (byte)0xf5, (byte)0x21, (byte)0x02, (byte)0xf4, (byte)0x2f,

……………………………

LISTADO 9 Constructor de sonidos de tipo WAV

public Sonido(String s,int miTipoSonido) {tipoSonido=miTipoSonido;cadena=s; int tamanno=getTamanno();try {

DataInputStream datainputstream = new DataInputStream(getClass().getResourceAsStream(cadena) );

soundData = new byte[tamanno];datainputstream.read(soundData, 0, tamanno);datainputstream.close();

} catch(Exception exception) {exception.printStackTrace();

}soundDriver = new Sound(soundData, tipoSonido);volumen = 255;setVol(volumen);

}

LISTADO 6 Fragmento de código que asigna el Listenerde eventos de sonido con la clase Principal

// Sonido.javapublic void setEscuchador(SoundListener miEscuchador) {

soundDriver.setSoundListener(miEscuchador);}

LISTADO 7 Fragmento de código que pasa la referenciade sí misma a la clase Sonido

// Principal.javasonWav.setEscuchador(this);

LISTADO 10 Cómo obtener el tamaño de un fichero WAV

private int getTamanno() { InputStream is;int tamanno=-1;try {

DataInputStream datainputstream = newDataInputStream(getClass().getResourceAsStream(cadena));

int cabecera = datainputstream.readInt();int tam4 = datainputstream.read();int tam3 = datainputstream.read();int tam2 = datainputstream.read();int tam1 = datainputstream.read();tamanno = (tam1 << 24) + (tam2 << 16) + (tam3 << 8) + (tam4 << 0) + 8;datainputstream.close();

} catch (Exception e) {System.out.println(“Fallo al cargar el archivo”);

}return tamanno;

}

¡Advertencia!En el MIDlet no se ha incluido ningún tipo de con-trol para que no se pueda seleccionar el WAV enun terminal que no soporta WAVs. Esto se hahecho así para no mezclar conceptos con el MIDletanterior. Por ello, si en un 7210 seleccionamosWAV, la aplicación dará un error irrecuperable.

¡Advertencia!Aunque las especificaciones del estándar hablen de quecon la MMAPI (Mobile Media API) podemos reproduciry grabar audio y vídeo, sus posibilidades reales varíancon cada móvil. Por poner un ejemplo, con el Nokia3650 no se puede grabar ni audio ni vídeo, aunque síreproducir ambos y capturar fotos. Con el Nokia 6600ya se podía grabar audio aunque no vídeo. Se puededecir, por tanto, que en cada nuevo modelo de Nokia laimplementación de la MMAPI va siendo más completa.

Page 23: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

código completo del MIDlet se puede encon-trar en el CD que acompaña a la revista.En el código mostrado en el listado 11 esta-mos simplemente accediendo a la cámaradel móvil. Para ello estamos obteniendo unobjeto “Placer” de un objeto “Manager”, y delobjeto “Placer”, un objeto “VideoControl” quees con el que “jugaremos”.Lo más importante del listado 11 es el Stringque pasamos como parámetro al método“createPlayer()” que se llama “Capture Locutor”y hace referencia a dispositivos de captura. Enla documentación de la MMAPI podemos veruna ampliación sobre los “Capture Locators” enla introducción a la clase “Manager”. En la prác-tica, si estamos programando para la serie 60de Nokia, sólo podremos usar los “CaptureLocutor” compatibles con el terminal en parti-cular para el que estamos programando. Parasaber qué “Capture Locators” son o no soporta-dos por cada terminal, no nos queda más reme-dio que investigar en los foros de Nokia, asícomo en los documentos que ponen a nuestradisposición. Por ejemplo, si queremos sabercuáles son compatibles con un Nokia 6600,existe un documento en la web de Nokia llama-do “Known Issues in_the Nokia 6600 MIDP 2.0”.Otra línea importante es en la que tomamosla instantánea:byte[] pngImage = videoControl.

getSnapshot(null);

Sobre el parámetro que le pasamos al méto-do “getSnapShot()”, en nuestro caso lehemos pasado “null”, con lo que obtendre-mos en la serie 60 de Nokia una imagen enformato PNG (Portable Network Graphics,véase la referencia 2) con un tamaño de160x120 píxeles. Podremos “jugar” con esteparámetro de la forma siguiente:

videoControl.getSnapshot(“encoding=

bmp&width=80&height=60”);

En el ejemplo estamos obteniendo un array debytes correspondiente a una imagen en for-mato BMP y del tamaño indicado. Hay quetener cuidado pues manipulando el tamañode la imagen podríamos distorsionar la ima-gen. Además, no podremos especificar anchu-ra o tamaño por separado, debemos especifi-car siempre los dos o tendremos un error.En cuanto al parámetro “encoding”, tenemostres opciones de formato compatibles:� PNG (Formato por defecto).� BMP.� JPEG.

Finalmente, para convertir la captura obtenidaen una imagen normal, usamos el método“setImage()” de la clase “DisplayCanvas.java”,que se recoge en el listado 12. Simplementeestamos creando una imagen inmutable leyen-do el array de bytes que obtuvimos al capturar,desde el byte 0 (primer byte del array), hasta elúltimo byte del array. La figura 7 muestra laaplicación en funcionamiento en un 3650.

Wireless Messaging API (JSR-120)

La WMA (Wireless Messaging API) es otra APIopcional de SUN que nos permitirá enviar yrecibir mensajes SMS (Short Message System)de texto y binarios. Los SMS de texto ya losconocemos todos, pero quizá los SMS binariosno sean tan conocidos a pesar de estar tan demoda últimamente. Los SMS binarios sonmensajes que usan el protocolo Short Message

Service para enviar información que será inter-pretada sólo por algunos terminales. Por ejem-plo, los logotipos de Nokia y los RingTones sonejemplos de información binaria que se pue-den enviar en un SMS y que sólo será válidapara un terminal Nokia o compatibles. Esta APInos abstraerá de la red que haya por debajo ycomo es lógico no nos importará si el SMS seenviará bajo GSM (Group Special Mobile oGlobal System for Mobile), CDMA (Code-Division Multiple Access), etc. Es importante noconfundir esta API con la Nokia SMS API, quees anterior en el tiempo a la WMA, y sólo fuesoportada por el Nokia 3410. Sus característi-cas eran similares a las de la WMA salvo quetenía una funcionalidad muy parecida al PushWAP de MIDP 2.0 que no es objeto de estudioen la presente serie de artículos.La WMA es una API con pocas clases y senci-lla de aprender si se parte de un ejemplo que

26

DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

Figura 6. Diagrama UML del MIDlet deacceso a la cámara.

Figura 7. MIDlet de acceso a la cámara.

¡Advertencia!Nokia no recomienda capturar imágenes superio-res a 240x180 a no ser que nuestro terminal seaun Nokia 6630 o similar.

LISTADO 11 Cómo acceder a la cámara

//CameraCanvas.javaplayer = Manager.createPlayer(“capture://video”);player.realize();//Cogemos el VideoControl y lo mostramos por pantallavideoControl = (VideoControl)(player.getControl(“VideoControl”));if (videoControl == null) {

...} else {

videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,this);...

}

LISTADO 12 Convertir el array de bytes en imagen

//DisplayCanvas.javavoid setImage(byte[] pngImage) {

image = Image.createImage(pngImage, 0, pngImage.length);}

Page 24: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

muestre el funcionamiento, por eso vamos amostrar un ejemplo auto explicativo de cómoenviar un SMS desde nuestro MIDlet.Con el código del listado 13 se envía un SMSal teléfono (inexistente) 751862661 de España.Afortunadamente, para evitar la existencia deMIDlets malintencionados que se dedicaran aenviar mensajes SMS indiscriminadamente, enel momento de ejecutarse el “send” nos apare-cerá un mensaje de confirmación de la inter-faz del teléfono para avisarnos de que se va aenviar un SMS, y podremos abortar el envío.Es importante saber que podremos enviar gran-des extensiones de texto y no tener la limitaciónde los 160 caracteres de un SMS. La interfaz“MessageConnection” tiene un método para cal-cular el número de SMSs necesarios para enviarun texto dado (“numberOfSegments”), por si elusuario de nuestro MIDlet quiere calcular cuán-to le va a costar el envío que nuestro MIDlet, ycomo hemos dicho antes, siempre en último tér-mino el usuario será quien tenga la última pala-bra para realizar o no el envío de información.Para poder enviar MMS ya existe una nuevaespecificación de WMA, la JSR-205. Aunquetodavía deberemos esperar un tiempo a queesté implementada en los teléfonos Nokia.

Compilación y ejecución de los ejemplos

Para compilar y ejecutar los ejemplos propuestosno será suficiente con el J2ME Wireless Toolkit deSun, puesto que los fragmentos de código aquípropuestos usan la API específica para terminalesNokia. Las herramientas necesarias para probarlos ejemplos incluidos en el CD-ROM son, el pro-pio J2ME Wireless Toolkit de Sun (http://java.sun.com/products/j2mewtoolkit/downlo-ad-2_2.html) y, además, el Nokia Developer’s Suitefor J2ME (http://www.forum.nokia.com/main/0,6566,034-2,00.html). Ambos paquetes de soft-ware están a disposición del desarrollador y pue-den descargarse libremente. En el caso del NokiaDeveloper’s Suite será necesario completar unproceso de registro y obtener así un número delicencia, necesario para la instalación. Todo este

proceso queda explicado en la página de descar-ga del producto.Una vez descargados ambos productos, se pro-cederá a la instalación de J2ME Wireless Toolkitde Sun. Es posible que el lector ya tenga insta-lado este entorno, puesto que ha sido objeto deestudio en números anteriores de SóloProgramadores. Después se procederá a la ins-talación del Nokia Developer’s Suite, eligiendo lainstalación “standalone” (opción por defecto).Después de superar la instalación de ambosproductos, se procederá a la configuración dela herramienta KToolbar del J2MEWTK. Paraello, habrá que copiar el contenido de la car-peta “C:\Nokia\Devices” (de la instalación delNokia Developer’s Suite) dentro de la carpeta“C:\WTK22\wtklib\devices” (de la instalacióndel J2MEWTK). Con esto, habremos añadido anuestro entorno J2MEWTK los emuladorespara los terminales Nokia (de los emuladoresinstalados sólo se garantiza el correcto fun-cionamiento del “Series_60_MIDP_Concept_SDK_Beta_0_3_1_Nokia_edition”).Para ejecutar los ejemplos incluidos en el CD-ROM tendremos dos posibilidades, totalmenteequivalentes. La primera, es copiar las carpetasque hay dentro del directorio “Proyectos” delCD-ROM en el directorio “C:\WTK22\apps” denuestro J2MEWTK. Después, ejecutar la herra-mienta KToolbar y pulsar en “Open Project”. Enla lista de proyectos, podremos ver los proyec-tos añadidos, puesto que cada una de las car-petas incluidas en directorio “Proyectos” delCD-ROM corresponde a un proyecto. Despuésde abrir un proyecto, escogeremos en la pesta-ña “Device” uno de los emuladores que hemos“importado” al J2MEWTK, para luego pulsar en“Build” y luego en “Run”. Otra opción para eje-cutar los ejemplos consiste en crear nosotrosmismos el proyecto. Para ello, habrá que pulsar

en “New Project” de KToolbar y nombrar el pro-yecto, para luego escribir el nombre de la claseprincipal. Una vez hecho esto, el propioKToolbar nos indicará dónde copiar los fuentespara luego poder compilar y ejecutar el proyec-to. El lector encontrará los fuentes en el direc-torio “Codigo” del CD-ROM. Es necesario enten-der que ambos procedimientos son equivalen-tes, y que por lo tanto el código del directorio“Codigo” también se encuentra incluido en losproyectos del directorio “Proyectos” (dentro deldirectorio “src” correspondiente).

Conclusiones

Con este artículo ya hemos completado losconocimientos técnicos necesarios para estaren disposición de crear un juego que superelas limitaciones de los terminales MIDP 1.0. Eneste artículo hemos visto cómo los fabricantesde juegos Java, hasta la aparición de los pre-sentes terminales MIDP 2.0, todavía no dema-siado extendidos entre los potenciales usua-rios de nuestros juegos, tienen que recurrir aAPIs adicionales que son soportadas con dife-rentes matices según el terminal. Se apreciapor tanto la gran dificultad que entraña eldesarrollo de juegos realmente multiplatafor-ma, sin tener que recurrir a distintas compila-ciones de un mismo código fuente adaptado acada teléfono. En este sentido existen iniciati-vas muy interesantes como es el proyectoJ2ME Polish que se puede conocer en la direc-ción http://www.j2mepolish.org/.En el próximo artículo nos pondremos manos ala obra y configuraremos el IDE gratuito Eclipse(http://www.eclipse.org/) para facilitarnos lalabor de programar en J2ME no estándar, paralo cuál también instalaremos y configuraremosalgunas herramientas gratuitas de Nokia.

27

Juegos de calidad comercial en J2ME (III)DISPOSITIVOS MÓVILES

http://digital.revistasprofesionales.com

LISTADO 13 Envío de un SMS

try {String addr = “sms://+34751862661”;MessageConnection conn = (MessageConnection)Connector.open(addr);TextMessage msg = (TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE);msg.setPayloadText(“Hola!”);conn.send(msg);

} catch (Exception e) { }

AgradecimientosSe quiere agradecer a la empresa Flag Solutions (http://www.flagsolutions.net) y al grupo AWEG (Adaptive Web Engineering Group) de la Universidad de Salamancasus aportaciones y consejos para la elaboración de este artículo.

Referencias[1] SUN MICROSYSTEMS JSR-37 (15 Diciembre 2000). MIDP (Mobile Information Device Profile) http://java.sun.com/products/midp/index.jsp.[2] W3C. Portable Network Graphics (PNG) Specification (Second Edition). Information technology — Computer graphics and image processing — Portable

Network Graphics (PNG): Functional specification. ISO/IEC 15948:2003 (E). W3C Recommendation 10 November 2003. http://www.w3.org/TR/PNG/.

Page 25: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

ASP.NET es una herramienta adecuada para laconstrucción de clientes ligeros que sólo visualizanlenguaje de marcado a través de un navegador. Sinembargo, hay aplicaciones que:� Se benefician de un mayor acoplamiento entre

el cliente y el servidor.� Se comportan mejor en la comunicación a dos

bandas entre el cliente y el servidor.� Requieren utilizar la red de manera más óptima

y facilitar el mantenimiento de sesiones. En .NET, el espacio de nombres “System.Runtime.Remoting” provee la infraestructura para el desarro-llo de este tipo de aplicaciones. .NET Remoting susti-tuye a la tecnología DCOM para crear aplicacionesdistribuidas sobre plataformas Windows. Propor-ciona una arquitectura orientada a objetos quecomo todo buen middleware otorga transparenciade localización a los componentes distribuidos. EnRemoting, los componentes de una aplicación pue-den concentrarse en un único ordenador o en múl-tiples nodos alrededor de Internet, sin que el consu-midor de tales servicios sepa que dichos componen-tes están distribuidos. Remoting permite invocarmétodos y pasar objetos más allá de los dominios denuestra aplicación de una manera sencilla, flexible ymuy configurable. Combina estándares ya existentescomo: SOAP (Simple Object Access Protocol), paracodificación de mensajes, o HTTP y TCP, como proto-colos de comunicación, con formateadores binariospropietarios destinados a conseguir un alto rendi-miento en las comunicaciones. Básicamente, .NET

Remoting consiste en un conjunto de servicios ycanales de comunicación que transmiten mensajesentre aplicaciones remotas, con la ayuda de forma-teadores que codifican y decodifican esos mensajes.A continuación estudiamos en detalle esta poderosaherramienta de programación distribuida.

.NET Remoting básico

En .NET, una clase es remota cuando puede serusada por clientes en otro dominio de aplicación,es decir, en el mismo proceso, en otro proceso o enotras máquinas. Para construir una clase remotahay que seguir los siguientes pasos:1. Derivar la clase de “System.MarshalBy

RefObject”. Por ejemplo:public class ClaseRemota: MarshalBy

RefObject {

...

}

Cuando un cliente cree una instancia de“ClaseRemota”, realmente se creará un proxy dela misma. Un proxy es un objeto que “pretende”ser otro. Es decir, llamadas recibidas por el proxyson transmitidas al objeto remoto a través de uncanal que conecta los dos dominios de aplica-ción. Realmente el cliente sólo mantiene unareferencia al objeto, no una copia del mismo. Elcliente interactúa con un objeto local, el proxy,que encapsula las complejidades de la comuni-cación distribuida con un objeto remoto.

2. Registrar la clase para que pueda ser activadadesde otro dominio de aplicación. Una clase remo-ta se puede registrar a través de dos métodos está-ticos definidos en “System.Runtime.Remoting.RemotingConfiguration”: “RegisterActivatedServiceType” y “RegisterWellKnownServiceType”.Asimismo, en .NET Remoting se pueden definir dostipos de objetos remotos: (1) server-activated y (2)client-activated.

Objetos activados en la parte cliente o en la parte servidoraLos objetos activados en la parte servidora (server-activated) tienen las siguientes propiedades:� Se registran con “RegisterWellKnown

ServiceType” y “RegisterWellKnownClient Type”.

28

MIDDLEWARE

Programación distribuida en .NET (II)Programación distribuida en .NET (II)

Tras conocer en la primera entregalas piedras angulares de laprogramación distribuida a bajonivel: sockets, multithreading yXML, ahora analizamos .NETRemoting, la tecnología porexcelencia para el desarrollo deaplicaciones distribuidas en .NET.

DIEGO LZ. DE IPIÑA GZ. DE ARTAZA (Profesor del departamento de Ingeniería del Software de la facultadde Ingeniería de la Universidad de Deusto (ESIDE)).

http://digital.revistasprofesionales.com

Gracias a .NETRemoting los

objetos de nuestraaplicación

podrán residir en máquinas

remotas

Page 26: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

� Cuando el cliente invoca “new” sólo secrea un proxy en la parte cliente, el objetono se crea en la parte servidora hasta queuna invocación es recibida.

� Sólo se pueden usar constructores pordefecto sin parámetros.

Por su parte, los objetos activados en la partecliente (client-activated):� Se registran con “RegisterActivated

ServiceType” y “RegisterActivatedClientType”.� El objeto remoto se crea en la parte servi-

dora inmediatamente después de llamar a“new” en el cliente.

� Se pueden activar con constructores conparámetros.

Cuando registras un objeto activado en laparte servidora se pueden especificar dosmodos de comportamiento:� “WellKnownObjectMode.SingleCall”, se crea

una nueva instancia de la clase remota porcada invocación recibida de un cliente.

� “WellKnownObjectMode.Singleton”, secrea una instancia de la clase remota paraprocesar todas las llamadas de los clientes.

Los objetos activados en la parte del cliente ofre-cen sólo un modo de activación. Cada llamada a“new” por un cliente creará una instancia en elservidor que preserva estado de una llamada aotra. Si se desea mantener estado por cada clien-te, este modo de activación es idóneo para ello.A modo de ejemplo, el siguiente fragmentode código activa un objeto de tipo“ClaseRemota” en la parte servidora, bajo laURI “ClaseRemota”, con un comportamiento“SingleCall”, es decir, se creará una instanciadel objeto por cada petición recibida:RemotingConfiguration.RegisterWell

KnownServiceType (

typeof(ClaseRemota), // Clase remota

“ClaseRemota”, // URI de la clase

remota

WellKnownObjectMode.SingleCall

// Modo de comportamiento

);

Canales en .NET RemotingPara hacer que una clase remota sea accesiblepor clientes, el proceso servidor tiene que creary registrar un canal (channel). Un canal es unconducto para transportar los mensajes desdey hacia los objetos remotos. La misión de uncanal es tomar datos, crear un paquete segúnlas especificaciones de un protocolo y enviar elpaquete a otro ordenador. Cuando un clienteinvoca remotamente un método, los paráme-tros y otros detalles referidos a la invocación

son transportados a los objetos por medio delcanal. De la misma forma son transportadaslas respuestas a esa invocación. Hay dos tiposde canales predefinidos en .NET: � Canales TCP (“TcpServerChannel” y “TcpClient

Channel”) usan TCP para comunicarse ytransmiten datos, por defecto, en formatobinario. Son adecuados cuando el rendimien-to es lo importante, ya que los datos se trans-miten por medio del formato de serializaciónbinario diseñado para .NET Remoting.

� Canales HTTP (“HttpServerChannel” y“HttpClientChannel”) usan HTTP paracomunicarse. Lo más normal es que trans-porten mensajes de tipo SOAP. Son adecua-dos cuando lo que prima es la interoperabi-lidad. El canal HTTP es comúnmente utiliza-do para las comunicaciones en Internet.Una interesante propiedad de los objetosque usan estos canales es que permiten eluso de IIS como su agente de activación.

El siguiente fragmento ilustra cómo crear uncanal TCP en la parte servidora escuchandoen el puerto 1234:TcpServerChannel channel = new Tcp

ServerChannel(1234);

ChannelServices.RegisterChannel(channel);

Por su parte, una aplicación cliente que quieracrear una instancia de una clase remota tam-bién tiene que registrarse. Para que un clientepueda hablar con la parte servidora de unaclase remota, escuchando en un “TcpServerChannel”, debería crear un “TcpClientChannel”.Si el cliente quiere usar “new” para instanciarun objeto remoto, debe registrar la clase remo-ta en el dominio de aplicación local.“RegisterWellKnownClientType” registra unaclase en el cliente correspondiente a una clase“RemotingConfiguration.RegisterWellKnownServiceType” en el servidor. El siguiente códigomuestra cómo hacerlo para el caso de“ClaseRemota”:TcpClientChannel channel = new Tcp

ClientChannel();

ChannelServices.RegisterChannel(channel);

RemotingConfiguration.RegisterWell

KnownClientType(

typeof(ClaseRemota), // Tipo de la

clase remota

“tcp://localhost:1234/ClaseRemota”

// URL de la clase remota

);

Una vez que el cliente y el servidor han efec-tuado sus registros correspondientes se creala instancia de “ClaseRemota”:

ClaseRemota cr = new ClaseRemota();

La infraestructura .NET Remoting es altamenteconfigurable y extensible. Es perfectamenteposible definir nuevos canales y formateadoresa través de .NET Remoting que permitan comu-nicarse con servicios/objetos distribuidos des-arrollados con otras populares herramientas deprogramación distribuida, como CORBA, RMI oTibco RV. Un buen ejemplo de ello ha sido laintegración del protocolo IIOP de CORBA en .NETcon la extensión Remoting.CORBA, incluida enel CD-ROM y disponible en http://remoting-corba.sourceforge.net.Gran parte de la capacidad de interoperabilidadde .NET Remoting es debida a que integra SOAP.Aunque no es el protocolo más eficiente, per-mite gran flexibilidad. SOAP es un protocolobasado en XML que especifica un mecanismomediante el cual aplicaciones distribuidas pue-den intercambiar información independiente-mente de la plataforma. Aunque, normalmente,SOAP es usado junto con HTTP para su trans-porte, SOAP puede utilizar cualquier protocolode transporte (por ejemplo SMTP). Para másdetalles visitar http://www.w3.org/TR/SOAP/.

Interoperabilidad vs. rendimientoen .NET Remoting

La figura 1 muestra las posibilidades de explo-tación ofrecidas por .NET Remoting. En la parteservidora podemos tener servidores configura-dos con un canal TCP que son utilizados porclientes locales dentro de una LAN. En ese caso,para la transmisión de datos se usa el mecanis-mo más eficiente, transmisión en binario. Porotro lado, en la parte servidora podemos tenerun servidor con un canal HTTP que ha sido acti-vado por IIS. La información transmitida entreeste servidor y sus potenciales clientes se reali-za por medio del estándar SOAP. Obsérvese queesta configuración IIS + canal HTTP/SOAP esideal para situaciones donde deseamos alojarun servicio detrás de un cortafuegos que sólotolera conexiones remotas vía HTTP en el puer-to 80. Al utilizar SOAP los clientes no tienenporque necesariamente haberse programadoen .NET Remoting. Clientes web estándar des-arrollados bien con .NET u otros lenguajes comoJava o Python podrían utilizarse. Consecuentemente, si queremos interoperabi-lidad adoptaremos una solución basada encanales HTTP y SOAP. Si queremos máximorendimiento utilizaremos TCP y formateobinario. La primera opción será ideal cuandoqueremos que nuestro servicio sea consumidopor clientes externos y se encuentre protegido

29

MIDDLEWAREProgramación distribuida en .NET (II)

http://digital.revistasprofesionales.com

Page 27: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

tras un cortafuegos. La segunda será adecua-da para el desarrollo de aplicaciones distribui-das eficientes a utilizar dentro de una LAN.

Nuestra primera aplicacióncon .NET Remoting

Apliquemos los conceptos aprendidos hasta elmomento desarrollando un sencillo serviciodistribuido que devuelve la hora actual en .NETRemoting. En primer lugar, creamos una claseque hereda de “System.MarshalByRefObject”(véase el listado 1). A continuación, creamos la clase “ServidorReloj” que usa un canal TCP para recibir peti-ciones dirigidas al objeto remoto “Reloj” activa-do en el servidor con modo de comportamien-to “SingleCall” (véase el listado 2). Finalmente, creamos la clase “ClienteReloj”que simplemente se conecta a través de uncanal TCP con el objeto remoto “Reloj” einvoca su método “ObtenerHoraActual”(véase el listado 3). La figura 2 muestra estaaplicación en ejecución.

Configuración declarativaLas clases “ServidorReloj” y “ClienteReloj” usaninformación de configuración embebida en el

código para registrar canales y clases remotas.En consecuencia, si deseamos cambiar la direc-ción IP o el puerto en el que escucha un servi-cio debemos recompilar el código. La solución

a este problema es el registro declarativo en.NET. Este mecanismo toma información de unfichero que es procesado al invocar al métodoestático “RemoteConfiguration.Configure”.Modificar el cliente para consumir el objeto“Reloj” alojado ahora en otra máquina sería tansencillo como editar su fichero de configura-ción asociado “ClienteReloj.exe.config”.

Transfiriendo objetos como argumentosen .NET RemotingA veces es necesario pasar a un método comoparámetro de entrada o salida un objeto.Cuando el objeto es pasado por valor, el marcode Remoting se encarga de hacer una copiacompleta del objeto para que pueda ser enviadoa través de un canal. En el framework .NET exis-ten dos formateadores de serialización que seencargan de codificar y decodificar los mensa-jes: .NET binario (“System.Runtime.Serialization.Formatters.Binary”) y SOAP (“System.Runtime.Serialization.Formatters.SOAP”). Si un objeto tiene una gran cantidad de infor-mación (el contenido de una tabla de unaBBDD), será adecuado pasarlo por referencia, yluego utilizar la referencia recibida en el clien-te para ir progresivamente, según demanda,recuperando el contenido del mismo.

Creación de proxiesPara generar un proxy de un objeto remoto noes siempre necesario ni conveniente utilizar

30

MIDDLEWARE

http://digital.revistasprofesionales.com

Figura 1. Arquitectura de .NET Remoting.

LISTADO 2 ServidorReloj.cs

// compilar: csc /r:Reloj.dll ServidorReloj.csusing System;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;class ServidorReloj{

static void Main() {

TcpServerChannel channel = new TcpServerChannel(1234);ChannelServices.RegisterChannel(channel);RemotingConfiguration.RegisterWellKnownServiceType(

typeof(Reloj), “Reloj”, WellKnownObjectMode.SingleCall);Console.WriteLine(“Pulsar INTRO para continuar ...”);Console.ReadLine();

}}

LISTADO 1 Reloj.cs

// compilar: csc /t:library Reloj.csusing System;public class Reloj: MarshalByRefObject{

public string ObtenerHoraActual() {

return DateTime.Now.ToLongTimeString();}

}

Page 28: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

“new”. El uso de “new” obliga al cliente a teneracceso a la implementación del objeto remoto(su dll o exe) para generar su proxy. La clase“System.Activator” ofrece un par de métodosestáticos que nos permiten instanciar proxiesde objetos remotos simplemente teniendoacceso a su interfaz:� “GetObject” se usa para activar objetos en

la parte servidora. � “CreateInstance” se usa para activar obje-

tos en la parte cliente.Si utilizamos cualquiera de los métodos en“System.Activator” ya no será necesario usar“RegisterActivatedClientType” o “RegisterWellKnownClientType”. Por ejemplo, hastaahora hemos visto que para crear una instan-cia de un proxy en la parte cliente haríamos:RemotingConfiguration.RegisterWell

KnownClientType(typeof(Reloj),

“tcp://localhost:1234/Reloj”);

Reloj r = new Reloj();

O bien: RemotingConfiguration.RegisterActiva

tedClientType(typeof(Reloj), “tcp://

localhost:1234”);

Reloj r = new Reloj();

Sin embargo, con “GetObject” y“CreateInstance” se puede activar un objeto

remoto sin poseer otro conocimiento que suURL y una interfaz que soporta el tipo:IReloj r = (IReloj)Activator.GetObject

(typeof(IReloj), “tcp://localhost:1234

/Reloj”);

O bien: object[] url = {new UrlAttribute(“tcp:

//localhost:1234”)};

IReloj r = (IReloj)Activator.Create

Instance(typeof(IReloj), null, url);

Transformando el ConversorRomanoArabea .NET Remoting

Vamos a utilizar ahora los conceptos mos-trados sobre .NET Remoting para transfor-mar la aplicación de conversión de núme-ros romanos a árabes (vista en la entregaanterior), y viceversa, a una aplicación en.NET Remoting. Los pasos que seguiremosserán:1. Transformación del conversor a un servi-

dor .NET Remoting con canal TCP, confi-gurado de manera programática.

2. Transformación del conversor a un servi-dor .NET Remoting con canales TCP yHTTP, configurado declarativamente.

3. Activación del servidor de conversiónmediante IIS.

ConversorRomanoArabe con canal TCP

En el fichero “IConversorRomanoArabe.cs” (adjun-to en el CD-ROM) hemos colocado las clases“ConversorRomanoArabeConstants” y “Usuario”, yla interfaz “IConversorRomanoArabe”. La clase“ConversorRomanoArabeConstants” declaratodas las constantes utilizadas para el desarrollode este servicio. Por ejemplo la enumeración“NumeroRomanoEnum” es un mapa de valoresen romano a decimales (árabes):public enum NumeroRomanoEnum {I=1,

V=5, X=10, L=50, C=100, D=500, M=1000}

La clase “Usuario” es un objeto serializable,está marcado por el atributo “[Serializable]”,que sirve para encapsular los detalles delogeo de un usuario que desea utilizar el ser-vicio “ConversorRomanoArabe”. El listado 4muestra su código.En el listado 5 se muestra la interfaz que defineel contrato ofrecido por el servicio de conversión.Todo cliente (“ConversorRomanoArabeClient”)deberá ajustarse a ese contrato para podercomunicarse con el objeto remoto que imple-menta tal interfaz (“ConversorRomanoArabe”). Adiferencia de nuestra anterior implementacióndel servicio mediante sockets (esta implementa-ción fue vista en la primera entrega del curso),hemos incluido un par de métodos “Login” y“Logoff”, que deberán invocarse antes y despuésde acabar de consumir el servicio, respectiva-mente. “Login” devuelve un token de autentica-ción que será enviado junto con cada petición deconversión. De esa manera, evitaremos queusuarios no autorizados tengan acceso a nuestro“valioso” servicio distribuido.La implementación del servicio “ConversorRomanoArabe” en .NET Remoting se muestraen el listado 6. Esta clase remota hereda comosiempre de “MarshalByRefObject” e implemen-ta la interfaz “IConversorRomanoArabe”. Elconstructor de esta clase simplemente inicializauna tabla que mapea nombres de usuario acontraseñas (usuarios) y una lista con lostokens asignados a clientes autorizados. Elmétodo “Login” simplemente verifica que elnombre de usuario y contraseña pasados exis-ten en la tabla usuarios, y en caso afirmativogenera un token de autorización para el cliente.Este token deberá ser utilizado por dicho clien-te cada vez que requiera una conversión, esdecir, use el servicio “ConversorRomanoArabe”.El listado 7 muestra cómo antes de efectuarsela conversión se verifica que el token pasadocomo argumento es válido.

31

MIDDLEWAREProgramación distribuida en .NET (II)

http://digital.revistasprofesionales.com

Figura 2. Ejecución de la aplicación distribuida Reloj.

LISTADO 3 ClienteReloj.cs

// csc /r:Reloj.dll ClienteReloj.csusing System;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;class ClienteReloj{

static void Main() {

TcpClientChannel channel = new TcpClientChannel();ChannelServices.RegisterChannel(channel);RemotingConfiguration.RegisterWellKnownClientType(

typeof(Reloj), “tcp://localhost:1234/Reloj”);Reloj reloj = new Reloj();Console.WriteLine(reloj.ObtenerHoraActual());

}}

Page 29: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

El listado 8 muestra cómo de manera progra-mática se configura el tipo de canal, puerto ymodo de comportamiento del servicio“ConversorRomanoArabe”. En este caso utiliza-mos un canal de tipo TCP y activamos el obje-to en el servidor tras recibir una invocación delcliente. Todos los clientes comparten la mismainstancia del servidor, ya que el modo de com-portamiento del objeto es Singleton.Finalmente, en el listado 9 mostramos elcódigo de un cliente que utiliza el servicio“ConversorRomanoArabe”. La figura 3 mues-tra un cliente de .NET Remoting utilizando elservicio “ConversorRomanoArabe”.

ConversorRomanoArabe con canalHTTP declarativo

Analicemos ahora cómo modificar el conversorpara que de manera declarativa, tan sólo modi-ficando un par de ficheros de configuración ysin recompilar, consigamos modificar el tipo decanal o puerto utilizado por “ConversorRomanoArabe”. En la clase “ConversorRomano

ArabeServer” tan sólo tendremos que colocarla siguiente sentencia para configurar el canaly modos de activación de este servicio:RemotingConfiguration.Configure

(“ConversorRomanoArabeServer.exe.

config”);

Esta sentencia simplemente indica que el fichero“ConversorRomanoArabeServer.exe.config”(véase el listado 10) contiene la configuración delservidor. Obsérvese que ahora este servidor esaccesible a través de tanto un canal TCP en elpuerto 1234 como un canal HTTP en el puerto8080.Por otra parte, las modificaciones necesariaspara permitir la programación declarativa delcliente serían:RemotingConfiguration.Configure

(“ConversorRomanoArabeClient.exe.

config”);

32

MIDDLEWARE

http://digital.revistasprofesionales.com

LISTADO 4 Clase Usuario

[Serializable]public class Usuario{

private string nombreUsuario;private string contraseña;public Usuario(string nombreUsuario, string contraseña){

this.nombreUsuario = nombreUsuario;this.contraseña = contraseña;

}

public string NombreUsuario{

get{

return this.nombreUsuario;}set{

this.nombreUsuario = value;}

}

public string Contraseña{

get{

return this.contraseña;}set{

this.contraseña = value;}

}}

LISTADO 5 Interfaz IConversorRomanoArabe

public interface IConversorRomanoArabe{

bool Login(Usuario usuario, out string token);bool Logoff(string token);string ArabeARomano(string token, int num);int RomanoAArabe(string token, string numRomano);

}

LISTADO 6 Constructor y método Login de ConversorRomanoArabe

namespace ConversorRomanoArabe{

public class ConversorRomanoArabe: MarshalByRefObject, IConversorRomanoArabe{

private Hashtable usuarios;private ArrayList tokens;public ConversorRomanoArabe(){

this.usuarios = new Hashtable();this.usuarios.Add(“solop”, “solop”);this.tokens = new ArrayList();

}

public bool Login(Usuario usuario, out string token){

if (this.usuarios.ContainsKey(usuario.NombreUsuario) &&(string)this.usuarios[usuario.NombreUsuario] == usuario.Contraseña)

{token = usuario.NombreUsuario + “:” + usuario.Contraseña +

System.DateTime.Now;this.tokens.Add(token);return true;

} else{

token = “”;return false;

}}// ...

}}

Figura 3. Cliente del servicioConversorRomanoArabe programado con.NET Remoting.

Page 30: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

WellKnownClientTypeEntry[]

serviceMetadata = RemotingConfiguration.

GetRegisteredWellKnownClientTypes();

IConversorRomanoArabe conversor =

(IConversorRomanoArabe)Activator.Get

Object(typeof(IConversorRomanoArabe),

serviceMetadata[0].ObjectUrl);

// ... código que usa el conversor

De nuevo, se hace uso de un fichero de confi-guración (véase el listado 11) para determinarlos parámetros de conexión al componente ser-vidor. En este caso se elige utilizar el canal HTTP.Recordar que a través de la programación decla-rativa podremos cambiar la ubicación (direcciónIP) y número de puerto del servidor sin necesi-dad de recompilar el código del servidor o losclientes.

ConversorRomanoArabe activado por IIS

Como última mejora de nuestro conversorvamos a hacer que el servidor web IIS lo activeen demanda al recibir conexiones de clientes.De esta manera nos evitamos la tediosa tareade tener que manualmente arrancar el servidor,y de tenerlo que mantener en ejecución inclusocuando nadie lo está utilizando. Una alternati-va a la activación vía IIS podría haber sido lacreación de un servicio Windows con este ser-vidor .NET Remoting. No obstante, la activación

con IIS es aún mejor, dado que podemos hacerque nuestro servidor transparentemente escu-

che a través del puerto 80 normalmente abier-to en todos los cortafuegos.En primer lugar, usaremos el gestor de IIS(inetmgr) para crear un directorio virtual.Haremos clic con el botón derecho del ratónsobre “Sitios Web por Defecto” y seleccionare-mos “Nuevo” -> “Directorio Virtual”.Introduciremos el nombre “ConversorRomanoArabe” y lo asociaremos a un directoriode nuestro disco duro en el que hemos coloca-do el código fuente de la aplicación (comosiempre, disponible en el CD-ROM). A continua-ción crearemos un fichero “web.config” en esedirectorio con el contenido mostrado en el lis-tado 12. La figura 4 ilustra la configuración deldirectorio virtual con inetmgr.El código para el servicio “ConversorRomanoArabe” será el mismo que hastaahora. La única salvedad es que ahora nonecesitaremos definir la clase “ConversorRomanoArabeServer”, ya que la activación delservicio la realizará IIS.Por otro lado, el código del cliente tampococambiará, tan sólo el fichero de configuración“ConversorRomanoArabeClient.exe.config”requerirá una mínima modificación para utili-zar la nueva URI del objeto remoto ahora acti-

33

MIDDLEWAREProgramación distribuida en .NET (II)

http://digital.revistasprofesionales.com

LISTADO 7 Modificación del método ArabeARomano de ConversorRomanoArabe

public class ConversorRomanoArabe: MarshalByRefObject, IConversorRomanoArabe{

// ...public string ArabeARomano(string token, int num){

if (this.tokens.Contains(token)){

// ... Implementación del método} else{

throw new ApplicationException(“El token pasado no es válido”);}

}}

LISTADO 8 Bloque Main del ConversorRomanoArabeServer

public class ConversorRomanoArabeServer{

static void Main() {

TcpServerChannel channel = new TcpServerChannel(1234);ChannelServices.RegisterChannel(channel);RemotingConfiguration.RegisterWellKnownServiceType(

typeof(ConversorRomanoArabe), “ConversorRomanoArabe”, WellKnownObjectMode.Singleton);

Console.WriteLine(“Pulsar Enter para continuar ...”);Console.ReadLine();

}}

LISTADO 9 Clase ConversorRomanoArabeClient

class ConversorRomanoArabeClient{

static void Main() {

TcpClientChannel channel = new TcpClientChannel();ChannelServices.RegisterChannel(channel);IConversorRomanoArabe conversor =

(IConversorRomanoArabe)Activator.GetObject(typeof(IConversorRomanoArabe), “tcp://localhost:1234/ConversorRomanoArabe”);

string token;if (conversor.Login(new Usuario(“solop”, “solop”), out token)){

string numRomano = conversor.ArabeARomano(token, 1295);Console.WriteLine(“El número árabe 1295 convertido a romano es: “ +

numRomano);conversor.Logoff(token);

}}

}

LISTADO 10Fichero de configuraciónConversorRomanoArabeServer.exe.config

<configuration><system.runtime.remoting>

<application><service>

<wellknown mode=”Singleton” type=”ConversorRomanoArabe.ConversorRomanoArabe, ConversorRomanoArabeServer” objectUri=”ConversorRomanoArabe” />

</service><channels>

<channel ref=”http server” port=”8080” /><channel ref=”tcp server” port=”1234” />

</channels></application>

</system.runtime.remoting></configuration>

Page 31: Revista Solo Programadores #124

vado por IIS en el puerto 80 y bajo el contex-to “ConversorRomanoArabeServer”. A conti-nuación mostramos la única modificación conrespecto a la anterior versión del fichero:<client>

<wellknown type=”ConversorRomano

Arabe.IConversorRomanoArabe,

IConversorRomanoArabe” url=”http:

//localhost/ConversorRomanoArabe/

ConversorRomanoArabe.rem” />

</client>

Algo importante a reseñar es que deberemoscolocar la dll con el código del objeto remo-to en el subdirectorio “bin” del directoriodonde está colocado el “web.config”, ya quees donde lo busca IIS. Es decir, asumiendoque los ficheros .cs están en el mismo direc-torio que el “web.config”, compilaremos losficheros “IConversorRomanoArabe.cs” y“ConversorRomanoArabeServer.cs” del si-guiente modo:csc /t:library /out:bin\IConversor

RomanoArabe.dll IConversorRomanoArabe.cs

csc /t:library /out:bin\Conversor

RomanoArabeServer.dll /r:bin\IConversor

RomanoArabe.dll ConversorRomanoArabe

Server.cs

Para más detalles sobre cómo compilar y eje-cutar todos los ejemplos de esta entrega con-súltense los ficheros “LEEME.txt” que acompa-ñan al código de este artículo en el CD-ROM.

Conclusiones

En este artículo hemos ilustrado las caracterís-ticas principales del framework para programa-ción distribuida orientada a objetos .NET

Remoting: modos de activación, modos decomportamiento, canales de comunicación, ytransferencia de objetos como parámetros. Parademostrar estos conceptos hemos transforma-do el ConversorRomanoArabe de la anteriorentrega a un servicio distribuido programadoen .NET Remoting. En la siguiente entrega, describiremos otras carac-terísticas más avanzadas de .NET Remoting comoleasing o creación de servicios web con .NETRemoting. Además, revisaremos .NET EnterpriseServices, la solución en .NET para el desarrollo deaplicaciones distribuidas de alto rendimiento y ele-vada disponibilidad, análoga a J2EE en Java.

MIDDLEWARE

LISTADO 11 Fichero de configuraciónConversorRomanoArabeClient.exe.config

<configuration><system.runtime.remoting>

<application><client>

<wellknown type=”ConversorRomanoArabe.IConversorRomanoArabe, IConversorRomanoArabe” url=”http://localhost:8080/ConversorRomanoArabe” />

</client><channels>

<channel ref=”http client” /></channels>

</application></system.runtime.remoting>

</configuration>

LISTADO 12 Fichero web.config para el Directorio VirtualConversorRomanoArabe

<configuration><system.runtime.remoting>

<application><service>

<wellknown mode=”Singleton” type=”ConversorRomanoArabe.ConversorRomanoArabe, ConversorRomanoArabeServer” objectUri=”ConversorRomanoArabe.rem”/>

</service></application>

</system.runtime.remoting></configuration>

Figura 4. Directorio virtualConversorRomanoArabe en IIS.

Autor: Francisco Charte

2.0 en Visual Studio 2005

Patrocinado por:

Una de las novedades más interesantesde la nueva versión de es laincorporación de las páginas maestras.En la próxima entrega del coleccionabledescubriremos cómo las páginas maestras pueden abreviar el ciclo dedesarrollo de una aplicación web,todo ello desde el nuevo entorno Visual Studio 2005.

Page 32: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

En los artículos anteriores aprendimos aemplear los controles nativos de XAML paraconformar una interfaz gráfica y vimos cómomodificar su apariencia. Básicamente estatarea se lleva adelante mediante estilos visua-les, los que hacen posible personalizar la con-formación total o parcial de un control, tantosea para definir uno nuevo o para alterar algu-na faceta del mismo. Todo esto gracias al fabu-loso lenguaje de marcación XAML que seráincluido en la próxima versión del sistema ope-rativo de Microsoft, aunque el lector puede yahacer uso de esta tecnología descargando einstalando Avalon Community TechnologyPreview del sitio MSDN. Esto hará que puedaprescindir de complejas líneas de código deprogramación para finalmente remitirse a eti-quetas para crear una interfaz de usuario; yapuede crear su anhelado botón redondo o lalista con elementos de imágenes con hipervín-culos. Ahora bien, será necesario conocer cómoanidar cada uno de los miembros para asíobtener un resultado consistente. En estepenúltimo artículo del curso sobre programa-ción de interfaces con XAML iré más allá yexplicaré cómo enlazar XAML a datos parafinalmente desembocar en una de las caracte-rísticas que a mi parecer es de las más desta-cables y poderosas, llamada “Estilo de Datos”.También mostraremos cómo crear aplicacionesejecutables de Avalon para comenzar a cerrar

el círculo de tecnologías y herramientas. Sinembargo, antes vamos a hablar sobre las capa-cidades de este nuevo estándar para la cone-xión a datos, algo que hemos dejado hasta elmomento para ofrecer primero una buena baseen los temas básicos de XAML.

El enlace a datos

Cuando se piensa en el enlace a datos, todosimaginamos una aplicación que obtiene infor-mación de alguna parte y posteriormente laexhibe. Por supuesto que esto involucramucho más que este simple punto de vista, yaque por debajo existen traslados de paquetesde bytes desde el origen hasta la interfaz grá-fica, manejadores de base de datos, transfor-maciones, redes, etc. Afortunadamente, pocosde estos procesos nos interesan ya que enXAML esta tarea se resuelve de forma sencilla,aunque no por ello deje de ser poderosa y fle-xible. Además de la complejidad de actores quemencioné anteriormente los datos pueden serde tipos variados; cuando digo esto no merefiero a que el origen sea un motor SQLServer u Oracle, sino a formatos realmentedispares, como podría ser un documento XML,el valor de una propiedad de un objeto o unabase de datos. También se cuentan con variasalternativas de cómo manipular la informa-ción, se puede indicar que los datos vendrándel origen a la interfaz gráfica pero nunca vol-verán a éste o incluso ser bidireccional. Loseventos juegan necesariamente un papelimportante ya que hacen posible recibir notifi-caciones de cuándo la conexión está abierta,que ha llegado la información, así como tam-bién modificar la misma para que sea repre-sentada de una forma diferente a la original(transformaciones). Todo esto que he mencio-nado parece muy complejo en términos gene-rales, pero el lector comprobará en las próxi-mas páginas que no lo es tanto.

La clase BindLa nueva infraestructura provee una clase lla-mada “Bind” la cual es vista dentro del lengua-

36

MIDDLEWARE

XAML (IV)XAML (IV)

El acceso a orígenes de datos es unacaracterística deseable para cualquieraplicación. Esto nos conduce a unproblema, no siempre bien resuelto:¿Cómo mostrar estos datos alusuario? La solución que ofreceXAML es elegante y seguro quemuchos quedarán sorprendidosdespués de practicar con ella.

ERICH R. BÜHLER (MVP en .NET Framework)

http://digital.revistasprofesionales.com

Page 33: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

je declarativo XAML como una etiqueta deigual nombre. Esta es la responsable devincular un elemento con datos, por lo queinteractuar con sus propiedades haráposible un control total sobre el enlace.Todas las clases relacionadas con consumode información se encuentran dentro delespacio “System.Windows.Data”. El cuadro“Algunas de las clases del espacioSystem.Windows.Data” nos muestra unpequeño resumen de ellas, ya que su tota-lidad abarca más de 30 estructuras, aun-que en realidad solamente se emplean 2 o3 a no ser que desee realizar alguna imple-mentación con características realmenteavanzadas.Como podemos apreciar se tienen 3 posi-bles modelos de conexión y consumo dedatos, uno orientado al típico modelo rela-cional, otro a un documento XML, y el últi-mo que hace posible enlazarse con propie-dades de objetos, cosa que es de muchautilidad cuando se está trabajando en .NETFramework. El siguiente código contieneun pequeño ejemplo de cómo indicar uncampo a consumir:<Image.Source>

<Bind DataSource=”{DatosLibros}”

Path=”Imagen”/>

</Image.Source>

Más adelante nos centraremos en laforma de establecer el origen de datos.Como puede apreciarse en el código ante-rior, se declara una etiqueta de imagen yposteriormente se anida una segunda detipo “Bind”. Ésta utiliza la propiedad“DataSource” que indica el nombre delorigen de datos. Por su parte “Path” apun-ta al elemento deseado (del que nos inte-resa su valor) que es llamado “Imagen”.Básicamente esto obtendrá el contenidodel miembro y lo pondrá en el control,exhibiéndose finalmente dentro delmismo. Por supuesto que existen muchasalternativas a la hora de vincular un con-trol a datos, pero por una cuestión deespacio solamente me remitiré a veraquellas opciones que nos serán de utili-dad para explicar más adelante las carac-terísticas de “Estilo de Datos”. Como se mencionó anteriormente hayvarios tipos de origen, como por ejemploun documento XML. En este formato lainformación viene organizada de formajerárquica, lo que hace que en algunas

ocasiones sea necesario indicar una rutaque apunte al nodo específico dentro dela jerarquía. Esto no es un problema con“Bind” ya que ofrece el miembro “XPath”que permite definir el criterio de selec-ción. El siguiente fragmento de códigonos muestra cómo indicar un nodo inme-diato de la jerarquía utilizando esta pro-piedad, aunque esto podría ser una rutacomo por ejemplo la senda de un directo-rio de MSDOS (“/Imagen/VersionBlancoyNegro”):<Image.Source>

<Bind DataSource=”{DatosLibros}”

XPath=”Imagen”/>

</Image.Source>

Existe también una forma más económicadesde el punto de vista de la escritura, elatajo en cuestión hace lo mismo desde elpunto de vista funcional pero usando unasola línea. Sé que a algunos programadoresles gusta tener todo compacto en vez deemplear propiedades complejas (etiquetasanidadas). En general yo evito esta opciónya que mi criterio le quita legibilidad alcódigo, pero no obstante es bueno que ellector lo conozca. Para utilizar esta sintaxishabrá que asignar directamente en la pro-piedad donde se desea mostrar el resulta-do un asterisco seguido de la palabra“Bind” y luego entre paréntesis todos losvalores para el enlace separados por puntoy coma. La siguiente línea nos muestracómo hacerlo:

<Image Source=”*Bind(XPath=Imagen;

Datasource=’{DatosLibros}’)”/>

Hemos visto cómo vincular un enlace conun control simple aunque también es posi-ble hacer lo mismo con una lista de ele-mentos (“Listbox”). Ello brinda la posibilidadde exhibir varios miembros en vez de unosolo. Para esto es necesario bajar por lajerarquía de “Listbox” hasta toparnos con lacolección de elementos de la lista y allíestablecer el enlace. Veamos cómo se haceesto en el siguiente fragmento de código:<ListBox>

<ListBox.Items>

<CollectionContainer>

<CollectionContainer.Collection>

<Bind DataSource=”{DatosLibros}”

XPath=”Libro”/>

</CollectionContainer.Collection>

</CollectionContainer>

</ListBox.Items>

</ListBox>

Antes de pasar a detallar todo lo relacionadocon la conformación de la conexión, veamosen el cuadro “Propiedades de Bind” algunasde las propiedades que ofrece “Bind” parapersonalizar la forma en que los datos serántratados.

Estableciendo el origen de datosComo ya se ha dicho, todas las clasesrelacionadas con un enlace a datos se

37

MIDDLEWAREXAML (IV)

http://digital.revistasprofesionales.com

Algunas de las clases del espacio System.Windows.DataClase Descripción

Bind Define un objeto que contendrá la declaración de enlace entre un ele-mento de la interfaz gráfica y un origen de datos.

ObjectDataSource Representa un enlace con datos. Se puede enlazar con propiedades deotros objetos como origen/destino de datos.

SqlDataSource Proveedor específico para enlazar con Microsoft SQL Server.

XmlDataSource Si se desea consumir información en formato XML, es ésta la opciónque se deberá emplear (lo veremos aquí más adelante).

Propiedades de BindPropiedad Descripción

BindTypeTwoWays: Modifica la interfaz o el origen si alguno de ellos cambia.OneWay: Solamente actualiza la interfaz gráfica cuando el origen cambia.OneTime: Solamente actualiza la interfaz gráfica al inicio de la aplicación.

Converter Permite especificar una transformación para los datos al ser traídos a lainterfaz gráfica o al ser llevados al origen de datos.

IsAsync Indica cuándo los valores se deberán obtener/escribir en forma asíncrona.

ValidationRules Es de tipo colección y permite establecer reglas de validación a aplicar enel momento de enviar los datos.

Page 34: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

encuentran dentro del espacio “System.Windows.Data”. El cuadro “Algunas de lasclases del espacio System.Windows.Data”nos mostró un pequeño resumen de losmiembros allí contenidas ya que su tota-lidad abarca más de 30 estructuras.Básicamente se proveen 3 tipos diferen-tes de enlace, uno que es el tradicional(“SqlDataSource”), para vincular estruc-turas XML (“XmlDataSource”), y lo másinteresante… para consumir un objetocreado por nosotros mismos (“ObjectDataSource”).Comencemos por lo básico, el listado 1 nosmuestra un documento XML con informa-ción sobre libros.Por una cuestión de comodidad estainformación la incluiré dentro del mismodocumento XAML que define la interfazgráfica, sobre todo para no tener quehacer referencia a archivos externos. Aesto se le llama “isla de datos” ya que losmismos se encuentran dentro de un únicodocumento. Debido que el formato esXML se tendrá que emplear la estructura“XMLDataSource” (véase el listado 2).

“XPath” indica el nodo en el documentopor el que se desea filtrar así como elnombre que se empleará para la conexión.Con esto basta para que el enlace estécompleto. Por supuesto que el documentoque alimenta al origen puede estar en unarchivo independiente. Para ello solamen-te hay que indicar en el origen (“Source”)el nombre del archivo:<XmlDataSource def:Name=”DatosLibros”

Source=”MisLibros.xml” XPath= ”/Libros”/>

Como ve la diferencia en sintaxis es muypequeña, pero nos permite utilizar unarchivo independiente en vez de la “islaXML”.

Estilo de Datos

Cuando exhibimos datos por ejemplodentro de un control de lista, en realidadestamos acostumbrados a que sean mos-trados como elementos de texto unodebajo del otro. Esto no está mal, aunqueparece que esto ha resultado un pocoaburrido al grupo de arquitectos deXAML, por lo que han dado un paso másallá a esta aproximación. Ahora cuandose enlazan los datos a un elemento de la

38

MIDDLEWARE

http://digital.revistasprofesionales.com

LISTADO 1 Nuestra lista de libros

<Libros><Libro ISBN=”84-481-3271-8” EnAlmacen=”si”>

<Titulo>Guía de migración y actualización a Visual Basic .NET</Titulo><Imagen>Guia.jpg</Imagen>

</Libro>

<Libro ISBN=”84-451-3251-8” EnAlmacen=”si”><Titulo>Cocinando con .NET framework y XAML en 5 minutos</Titulo><Imagen>Cocinando.jpg</Imagen>

</Libro>

<Libro ISBN=”44-586-5231-4” EnAlmacen=”si”><Titulo>Cenando con .NET framework y con otras tecnologías</Titulo><Imagen>Cenando.jpg</Imagen>

</Libro>

<Libro ISBN=”74-341-3474-3” EnAlmacen=”in”><Titulo>Woman .NET una historia de amor en el ciberframework</Titulo><Imagen>Mujer.jpg</Imagen>

</Libro></Libros>

LISTADO 2 Accediendo a nuestra lista de libros

<DockPanel xmlns=”http://schemas.microsoft.com/2003/xaml” xmlns:def=”Definition”><DockPanel.Resources>

<XmlDataSource def:Name=”DatosLibros” XPath=”/Libros”><Libros xmlns=””>

<Libro ISBN=”84-481-3271-8” Stock=”in”><Titulo>Guía de migración y actualización a Visual Basic .NET</Titulo><Imagen>Guia.jpg</Imagen>

</Libro>...

</DockPanel>

Figura 1. La tecnología “Estilo de Datos” permite definir la forma en la que queremospresentar los datos obtenidos del origen.

Page 35: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

interfaz gráfica es posible indicar unaplantilla de visualización específica. Porejemplo, el primer campo a ser mostradoen la “ListBox” lo podríamos plasmarcomo un texto, pero el segundo al ser unaimagen emplearíamos un control“Picture”, mientras que el tercero lo mos-traríamos como hipervínculo. Para cubriresta necesidad se cuenta con una nuevatecnología que hace posible definir unaplantilla que transformará los datos deorigen a un tipo de visualización especí-fico. Como puede ver la tecnología de“Estilo de Datos” es una mezcla entrecaracterísticas avanzadas de presenta-ción e información. La figura 1 muestraun control de “ListBox” que he modifica-do para que su apariencia sea adecuada alos datos suministrados por el origen.Básicamente los pasos a seguir son siem-pre los siguientes tres:1. Crear un estilo para los datos (cómo éstos

serán mostrados).2. Asociar el control con el estilo creado pre-

viamente.3. Conectar el control al origen de datos.

Estableciendo el estiloEl primer paso entonces es definir un esti-lo para los datos. En la entrega anterior yase explicó que todo estilo debe ser defini-do como un elemento de la colección derecursos. El listado 3 nos muestra unaapariencia personalizada llamada“MiEstilo” donde se emplean varios con-troles para exhibir los diferentes elemen-tos del origen de datos; cada uno de elloscumple un rol meramente estético. Sin

embargo, hay que prestar atención a laslíneas que se encuentran resaltadas. La totalidad de la etiqueta “Bind” seráreemplazada por el valor del campo defi-nido en la propiedad XPath. El título seráinsertado dentro de un contenedor detexto, mientras que con el segundo ele-mento (“Image”) se hará algo más intere-sante ya que se utilizará este contenidopara alimentar la imagen. Por ejemplo, sise tiene un valor de campo “guia.gif”entonces se irá al directorio actual y secargará la imagen que tenga este nombre.En caso de no existir no se producirá unerror sino que se omitirá la misma.La propiedad “VisualTree” tiene un papelcrucial ya que como vimos en el capítuloanterior todo lo que se escriba dentro deella sobrescribirá la apariencia predetermi-nada del control. El resto de paneles y eti-quetas simplemente sirven para alinear losdatos.Hemos culminado el primer paso, ahoratenemos que asociar el control con elestilo creado previamente, con el fin deque se comience a utilizar la nueva formade plasmar la información. Evidentementeno deseamos que se aplique la aparienciaa toda la lista “Listbox” sino a sus elemen-tos miembros (“Items”). Para ello el con-trol cuenta con una propiedad llamada“ItemStyle” donde se debe poner el nom-bre del estilo previamente definido (eneste caso llamado “MiEstilo”). Veamoscómo:<ListBox ItemStyle=”{MiEstilo}”>

</ListBox>

Esto nos asegura que la nueva definiciónvisual será utilizada por los elementos con-tenidos así se carguen de un origen o utili-zando las primitivas del control de lista. Eltercer y último paso consiste en indicarcómo localizar el origen de datos, para ellosimplemente se deberá adicionar dentro dela colección de elementos la etiqueta “Bind”indicando el nombre de la conexiónmediante “DataSource”:<ListBox ItemStyle=”{MiEstilo}”>

<ListBox.Items>

<CollectionContainer>

<CollectionContainer.Collection>

<Bind DataSource=”{DatosLibros}”

XPath=”Libro”/>

</CollectionContainer.Collection>

</CollectionContainer>

</ListBox.Items>

</ListBox>

Una vez que hemos hecho esto debemosestablecer de dónde obtener los datos.Como mencioné anteriormente este ori-gen será un documento XML, por lo quese tendrá que emplear la estructura“XMLDataSource” y nombrar al nodo dedónde obtener la información.

Generando una aplicación Avalon

Cuando se tiene un documento XAMLcualquiera, éste puede abrirse y modifi-carse ya que en realidad se trata de unarchivo de texto que sigue ciertas reglas.Sin embargo existe la posibilidad de crearuna aplicación Avalon (exe) que cumplala misma función que el documento ymás. Básicamente esta tarea consiste enllevar las etiquetas y propiedades a códi-go .NET y posteriormente compilarlo.Cada etiqueta se transformará en unainstancia de una clase, mientras que laspropiedades serán convertidas a líneas decódigo que configuren cada uno de susvalores. No obstante la ventaja más noto-ria es que para tener código asociado aeventos del documento en alguno de loslenguajes de .NET Framework (lógicadetrás de escenas) se deberá utilizar for-zosamente esta aproximación. Aquí setendrán entonces 2 archivos, uno queserá el archivo XAML en sí con la defini-ción de la interfaz gráfica y otro con la

39

MIDDLEWAREXAML (IV)

http://digital.revistasprofesionales.com

LISTADO 3 Definición del estilo MiEstilo

<DockPanel.Resources><Style def:Name=”MiEstilo”>

<ContentPresenter/><Style.VisualTree>

<DockPanel xmlns=http://schemas.microsoft.com/2003/xaml Width=”100%” Height=”100%” DockPanel.Dock=”Left”>

<Text FontSize=”Small” Foreground=”Black”><Text.TextContent>

<Bind XPath=”Titulo”/></Text.TextContent>

</Text><DockPanel Margin=”5 5 5 5” DockPanel.Dock=”Left” Width=”200”>

<Image Width=”100” Height=”150”><Image.Source>

<Bind XPath=”Imagen”/></Image.Source>

</Image></DockPanel>

</DockPanel></Style.VisualTree>

</Style></DockPanel.Resources>

Page 36: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

lógica bajo la nomenclatura <Nombre dearchivo>.XAML.CS (o VB para el caso deser Visual Basic .NET).Desde este código será posible interac-tuar/modificar las características deldocumento, así como prescindir del pri-mero para crear la interfaz desde cero. Porejemplo, en vez de emplear la etiqueta“Bind” se podrían escribir las líneas decódigo necesarias para efectuar el enlaceen el momento en que se cargue el docu-mento.La herramienta que lleva adelante la com-pilación se denomina MSBUILD, la que esen realidad el nuevo sistema de compila-ción para las aplicaciones .NET y futurasversiones de Visual Studio. Simplementese deberá invocar a esta aplicación desdela línea de comandos, estando siempresobre la carpeta con el documento XAML acompilar. Se requieren siempre 2 archivos que le indi-quen al compilador cómo realizar su trabajo:� Archivo de aplicación (CualquierNombre

.xaml)� Archivo con información de proyecto

(nombredelProyecto.cs/vb)El archivo de aplicación puede contenermás datos, pero el mínimo requerido debeindicar el documento XAML de inicio quetendrá que mostrarse al abrirse la aplica-ción:<NavigationApplication xmlns=”http://

schemas.microsoft.com/2003/xaml”

xmlns:def=”Definition” StartupUri=”

[Aquí el nombre de la página XAML

de inicio].xaml”>

</NavigationApplication>

El archivo con información del proyectopuede resultar un poco más aterrador aprimera vista ya que contiene muchainformación casi incomprensible para elojo humano. Sin embargo, verá que lamayor parte de las etiquetas siempre per-manecen constantes (vea esto en el lista-do 4).

Se han destacado los valores que habráque modificar, el resto podrán dejarsecon los tipos propuestos. El valor delespacio de nombres (“DefaultClrNameSpace”), por ejemplo, lo utilizaremosmás adelante cuando queramos escribircódigo detrás de escenas, por lo quevolveremos sobre este atributo. El restode los miembros son auto-descriptivos,por lo que no requieren de explicaciónalguna. Sin embargo en el caso de“ProjectGuid” es obligatorio obtenerun número identificador único para elproyecto, lo que sería igual al DNI deuna persona. Para ello hay que utilizarla aplicación guidgen que se encuentraen la carpeta “\Common7\Tools” den-tro de Visual Studio. Ésta creará unnuevo identificador el que será únicoen el tiempo y en el espacio (véase lafigura 2). Una vez completada la tarea tendrá los 2documentos con información de aplica-ción mas la/las páginas XAML. Bastará eje-cutar MSBUILD dentro de la carpeta paraque se genere el ejecutable correspon-diente a la interfaz definida en XAML.

40

MIDDLEWARE

http://digital.revistasprofesionales.com

LISTADO 4 El archivo de información

<?xml version=”1.0” encoding=”utf-8”?><Project DefaultTargets=”Build”xmlns=”http://schemas.microsoft.com/developer/msbuild/2003”>

<!— MSBUILD Project File —><PropertyGroup>

<DefaultClrNameSpace>Nombre_del_espacio_de_nombres</DefaultClrNameSpace><AssemblyName>Nombre_de_mi_Ensamblado</AssemblyName><TargetType>winexe</TargetType><Configuration>Release</Configuration><BuildSystem>MSBuild</BuildSystem><HostInBrowser>False</HostInBrowser><ProductVersion>8.0.40209</ProductVersion><SchemaVersion>2.0</SchemaVersion><ProjectGuid>{55DF4C82-60B1-401E-9A8D-AF62DCA542AF}</ProjectGuid>

</PropertyGroup><Import Project=”$(MSBuildBinPath)\Microsoft.CSharp.targets” /><Import Project=”$(MSBuildBinPath)\Microsoft.WinFX.targets” /><ItemGroup>

<ApplicationDefinition Include=”<Nombre del archivo de aplicación>.xaml” /><!—Archivos a compilar —><Page Include=”<Nombre de la página a compilar>.xaml” />

</ItemGroup></Project>

Figura 2. Generando un identificador para el proyecto.

Page 37: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Asociando código detrás de escenas a un evento

Como se mencionó anteriormente es rela-tivamente sencillo escribir código que estéasociado a los diferentes eventos de unapágina XAML; esto es similar a la aproxi-mación que utiliza ASP.NET. Se tendránentonces 2 archivos, uno con la definiciónde la interfaz gráfica mientras que otroserá el encargado de contener la lógica.Para llevar esto adelante es necesariomodificar el primer elemento de la jerar-quía del documento XAML para indicarle aMSBUILD dónde localizar la lógica (veaesto en el listado 5).Mientras que el atributo “def:Class” indica elespacio de nombres del ensamblado (véase“DefaultClrNameSpace” en el archivo de

proyecto) y de la clase a la que deberá per-tenecer el archivo de código, “def:CodeBehind” especifica el nombre y dóndelocalizar al mismo. Por su parte es recomen-dable adicionar a todos los controles unnombre mediante el atributo “ID”, con el finde que luego se pueda hacer referencia aellos desde código. También debe asignarse alos nombres de los eventos a capturar cuálserá el procedimiento que contendrá suimplementación. El código del listado 6muestra un esqueleto clásico de lógica.Como se puede apreciar se indica el nombredel ensamblado así como también de laclase, la cual en este caso hereda las carac-terísticas del panel “DockPanel”. Este procedimiento se “enganchará” auto-máticamente con la ejecución del clic delbotón.

¿Qué hay que tener para ejecutarXAML?

En el futuro nuestras interfaces XAML estaránautomáticamente soportadas por el nuevo sub-sistema gráfico Avalon de Longhorn, la próximaversión del sistema operativo de Microsoft(véanse los artículos dedicados a Longhorn enlos números 122 y 123 de Sólo Programadores).Sin embargo, mientras tanto es posible compi-lar y ejecutar nuestras interfaces XAML consoluciones alternativas, como las que siguen:� Visor XAML de XAMLON y también con-

versor de Flash a este formato. Es posibledescargar la aplicación desde http://www.xamlon.com.

� Visor de XAML de Mobiform, que por elmomento es la única aplicación consoporte a la librería gráfica Avalon yademás con un editor gráfico incorpora-do. Puede descargarse desde http://www.mobiform.com.

� Visor XAML de Microsoft, contenidodentro del paquete Public November2004 “Avalon” Community TechnologyPreview, disponible para descarga desdeel site de Microsoft para desarrolladores.

Conclusiones

Y hasta aquí hemos llegado en esta cuartaentrega, en el próximo y último capítulo dela serie hablaremos de cómo animar unainterfaz gráfica, cosa muy sencilla pero a lavez muy impactante, así como alguna delas características 3D de XAML.

41

MIDDLEWAREXAML (IV)

http://digital.revistasprofesionales.com

LISTADO 5 Modificaciones en el documento XAML

<Canvas xmlns=http://schemas.microsoft.com/2003/xaml xmlns:def=”Definition”def:Class=”Espacio_de_nombres_del_Ensamblado.MiClase” def:CodeBehind=”MiArchivo.xaml.cs” ID=”MiControl”>

<Button ID=”MiBotón” Click=”MiProcedimientoParaMiBotón”>¡Hola Mundo!</Button>Aquí otros controles...

</Canvas>

LISTADO 6 Archivo con lógica de negocio

// Estos son los espacios de nombres comúnmente utilizados por un panel.using System;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Navigation;using System.Windows.Shapes;

namespace Espacio_de_nombres_del_Ensamblado{

public partial class MiClase : DockPanel{

private void MiProcedimientoParaMiBotón(object sender, RoutedEventArgs e) {}}

}

Figura 3. Ejecutando MSBUILD dentro de la carpeta transformaremos el documentoXAML en un ensamblado EXE de .NET Framework.

Page 38: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

Comunicaciones asíncronasComo es sabido, la comunicación asíncrona, tam-bién llamada “no bloqueante”, es aquella en la queel emisor envía un mensaje y continúa con sufuncionamiento normal sin esperar a que elreceptor lo procese. El caso contrario es la comu-nicación síncrona, en la que el emisor envía elmensaje y espera (se bloquea) hasta que recibe larespuesta o transcurre el tiempo de espera.Los sistemas de mensajería (MOM, MessageOriented Middleware) se encargan de proporcionareste tipo de comunicación entre aplicaciones corpo-rativas de una forma sencilla, robusta y fiable. Sonmucho más ampliamente escalables que aquellosbasados en conexiones directas o a través de llama-das a procedimientos remotos (RPC), y uno de loscampos en los que son más utilizados es en el con-trol de flujo (workflow) de información de sistemas.En sistemas MOM los participantes de la comuni-cación no tienen que preocuparse de esperar unarespuesta del recipiente, ni siquiera de dónde seencuentra éste, ya que pueden confiar en lainfraestructura de mensajería que se encarga deasegurar su entrega.JMS o Java Message Service es la única API demensajería soportada por J2EE.Los sistemas de mensajería han ido evolucionan-do desde simples colas asíncronas hasta sistemaselaborados con publicadores, suscriptores, distri-

buidores, formateo de mensajes, capacidades deproporcionar calidad de servicio, etc.Dentro de estos sistemas se conoce a los clientesde mensajería en JMS como clientes JMS, al pro-pio sistema como proveedor JMS, y a la aplicaciónJMS como al conjunto de clientes y proveedores(normalmente uno) que forman el sistema.El cliente JMS que produce el mensaje es conoci-do como productor y el que lo recibe se conocecomo consumidor, aunque un mismo cliente JMSpuede actuar a la vez de los dos modos.

Modelos estándar de mensajeríaJMS nos proporciona dos modelos distintos demensajería, publicación/suscripción y comunica-ción punto a punto mediante colas. Se suelenabreviar con “pub/sub” para el primer modelo y“p2p” para el segundo.A grandes rasgos, el modelo publicación/suscrip-ción está pensado para una comunicación “uno amuchos” mientras que el modelo punto a punto loestá para comunicaciones “uno a uno”.Podemos sugerir para el modelo pub/sub el serviciode suscripciones de esta revista. Pensemos en quelos lectores se apuntan a una lista mediante unasuscripción y los responsables les envían su ejem-plar cada mes. Todos y cada uno de ellos recibenuna “copia” de la revista, y no es necesario que loslectores se conozcan entre sí. Para el segundomodelo, podemos pensar en un sistema de colastípico, como puede ser las colas en las cajas de unsupermercado. En este caso, los clientes buscan unasola de las cajas disponibles, hacen cola hasta quellega su turno y son atendidos por el/la cajero/a.En la figura 1 podemos apreciar el esquema delmodelo pub/sub. En este modelo un productorenvía un mensaje a un canal virtual llamado tópi-co. Los consumidores pueden suscribirse a dichotópico, con lo que recibirían una copia del mensa-je; todos los mensajes enviados a un tópico sonentregados a todos los receptores. En este modelose conoce al productor como publicador y al con-sumidor como suscriptor. Un aspecto importanteen este modelo es que el publicador no conocenada acerca de los suscriptores, no sabe dónde seencuentran, ni cuantos hay ni lo que hacen con losmensajes. Asimismo, los receptores no pueden

42

REDES

Sistemas de mensajería conJava Message Service (I)Sistemas de mensajería conJava Message Service (I)

La especificación de mensajería JMSnos permite construir sistemas demensajería asíncronos con un altogrado de robustez y sencillez.Además, hoy en día existen en elmercado soluciones JMS de códigoabierto que proporcionan un gradode madurez suficiente como para serutilizados en aplicacionescorporativas.

EDUARDO MILLÁN MARTÍNEZ

http://digital.revistasprofesionales.com

Artículo publicado en colaboración con

javaHispano

Page 39: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

examinar los mensajes pendientes, y tienenque consumirlos tal cual les llegan.Los aspectos importantes de este modeloson los siguientes:� No existe acoplamiento entre producto-

res y consumidores, pueden ser añadidosdinámicamente.

� Cada suscriptor recibe su propia copia delmensaje.

� Los suscriptores reciben el mensaje sintener que solicitarlo. Los mensajes publi-cados en un tópico son automáticamen-te entregados a los suscriptores.

Veamos ahora el modelo punto a punto en lafigura 2. Este modelo se basa en otro esque-ma. Los clientes JMS envían mensajes a tra-vés de canales virtuales llamados colas. Aquíse conoce a los productores como emisores ya los consumidores como receptores. Se tratade un modelo en el cual los receptores che-quean la cola para ver si han recibido algúnmensaje, contrariamente a lo que sucedía enel anterior modelo (aunque es el comporta-miento por defecto, se puede aproximar almodelo anterior mediante configuración).En una cola puede haber más de un receptoresperando mensajes, aunque solamente unode ellos va a consumir cada mensaje. Comoobservamos en la figura 2, el productor seencarga de generar el mensaje y el sistemaJMS entrega el mensaje a uno y sólo uno delos potenciales receptores.La especificación no define las reglas quedeben seguirse para la distribución de los

mensajes entre los receptores, así que cadafabricante realiza su propia implementación.Este modelo ofrece otras herramientas,como el explorador de colas mediante el cualel receptor es capaz de examinar los mensa-jes pendientes antes de consumirlos, deforma que puede descartar alguno de ellos.Esta es una característica diferenciadora delanterior modelo, además de las que explica-mos a continuación:� Los mensajes se intercambian a través de

colas.� Cada mensaje se entrega a un sólo receptor.� Los mensajes llegan ordenados, a medi-

da que se consumen se van eliminandode la cola.

� No existe acoplamiento entre emisores yreceptores, se pueden añadir dinámica-mente, ya que esta es una característicageneral de los sistemas de mensajería.

El porqué de la existencia de ambos modelostiene su explicación en los orígenes de la espe-cificación JMS. Inicialmente se pensó comouna solución para sustituir las APIs de los sis-temas de mensajería existentes. En el momen-to del análisis, unos fabricantes de sistemasutilizaban un modelo y el resto el otro mode-lo. Así pues, JMS tuvo que dar opción a ambosmodelos para que la industria lo aceptase. Enrealidad la especificación no exige que lasimplementaciones proporcionen los dos, aun-que los proveedores de JMS lo ofrecen.Fundamentalmente, todo lo que se puedehacer con un modelo también se puede

hacer con el otro. Podemos establecer unaanalogía en relación a qué lenguaje de pro-gramación preferimos, sea el que sea, segu-ro que podremos conseguir el mismo resul-tado. De la misma forma, la elección delmodelo pub/sub o p2p se convierte en unacuestión de preferencias.Ante la existencia de los dos modelos, surge laduda de cuándo elegir uno u otro. La decisiónva a depender de los distintos méritos queaporta cada uno. Si se trata de una aplicaciónen la que nos interesa repartir mensajes a dis-tintos destinatarios sin importarnos si estánconectados o no, el modelo pub/sub puedeservirnos. Si por el contrario es importantesaber que los mensajes llegan, como puede serel caso de una conversación uno a uno, quizássea más interesante utilizar el modelo p2p.La variedad de los datos a transmitir tambiénpuede ser un punto a tener en cuenta.Podemos aprovecharnos de la facilidad detópicos que nos ofrece el modelo pub/subpara segregar los diferentes mensajes entrelos potenciales destinatarios.El modelo p2p es más adecuado cuando sequiere que el receptor procese el mensajeuna sola vez. Otra ventaja, mencionada ante-riormente, es que disponemos de un explora-dor de colas que nos permite echar una oje-ada a la cola para ver los mensajes que espe-ran ser consumidos.

OpenJMS. Instalación y configuración

OpenJMS es una implementación libre de laespecificación Java Message Service API 1.0.2.La página del proyecto es http://openjms.sourceforge.net.

InstalaciónLa instalación de OpenJMS es muy sencilla,únicamente necesitaremos tener instaladopreviamente el JRE (en su caso el J2SDK sideseamos modificar el código fuente delproyecto) y seguir unos sencillos pasos.El archivo de instalación es únicamente unaestructura de directorios que contiene todo lonecesario para ejecutar OpenJMS en nuestramaquina.El primer paso consiste en descomprimir elarchivo de instalación que está disponible enformato .zip y .tar.gz. La estructura de direc-torios generada al descomprimir el archivodebe ser la mostrada en la figura 3.La carpeta “bin” contiene archivos .sh y .batpara iniciar, detener, y administrar en servidor

43

REDESSistemas de mensajería con Java Message Service (I)

http://digital.revistasprofesionales.com

Figura 1. Modelo pub/sub de mensajería JMS.

Figura 2. Modelo point-to-point de mensajería JMS.

Page 40: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

OpenJMS. La carpeta “config” contiene el archi-vo “openjms.xml” el cual indica la configuraciónpor omisión del servidor OpenJMS. La carpeta“config/db” contiene scripts SQL para bases dedatos OpenJMS. La carpeta “config/examples”contiene varios ejemplos de archivos de confi-guración para otras necesidades de funciona-miento del servidor. La carpeta “docs” contienetoda la documentación del proyecto, incluyen-do información más detallada de esta instala-ción. La carpeta “lib” contiene los archivos .jarrequeridos para ejecutar el servidor OpenJMS yaquellos requeridos por programas cliente queusan OpenJMS. La carpeta “src/examples” con-tiene el código fuente de varios archivos deejemplo. Además de esto, hay que crear lassiguientes variables de entorno:� JAVA_HOME: El directorio raíz de insta-

lación del JRE.� OPENJMS_HOME: El directorio raíz de

instalación de OpenJMS.Para probar si la instalación se realizó satis-factoriamente iniciamos el servidor desde lalínea de comandos.Para Windows:cd %OPENJMS_HOME%\bin

startup

Para UNIX:cd $OPENJMS_HOME/bin

startup.sh

Debe aparecer un mensaje indicándonos queel servidor se encuentra ya disponible (véasela figura 4).Para detener el servidor ejecutamos, en elcaso de plataformas Windows:cd %OPENJMS_HOME%\bin

shutdown

Para UNIX:cd $OPENJMS_HOME/bin

shutdown.sh

ConfiguraciónLa configuración de OpenJMS se realiza através de la modificación del archivo

“openjms.xml”. Simplemente se van agre-gando los elementos de configuración quenecesitemos para el entorno sobre el cualejecutaremos el servidor; dichos elementospueden ser para configurar las bases dedatos que vamos a utilizar, la seguridad,configuración de tópicos para publicación/

44

REDES

http://digital.revistasprofesionales.com

Figura 3. Estructura de directorios deOpenJMS.

Figura 4. Consola del sistema con el servidor OpenJMS en funcionamiento.

LISTADO 1 Fichero de configuración de OpenJMS

<?xml version=”1.0”?><!—

NOTA: Esta configuración muestra los elementos másrelevantes cuando se utiliza un conector RMI.

—><Configuration>

<!— Opcional. Representa la configuracion por omisión—><ServerConfiguration host=”localhost” embeddedJNDI=”true” />

<!— Requerido cuando se usa un conector RMI —><Connectors>

<Connector scheme=”rmi”><ConnectionFactories>

<QueueConnectionFactory name=”JmsQueueConnectionFactory” /><TopicConnectionFactory name=”JmsTopicConnectionFactory” />

</ConnectionFactories></Connector>

</Connectors>

<!— Requerido —><DatabaseConfiguration>

<JdbmDatabaseConfiguration name=”openjms.db” /></DatabaseConfiguration>

<!— Requerido —> <AdminConfiguration script=”${openjms.home}\bin\startup.bat” />

<!— Opcional. Si no se especifica, no se crearan destinos —><AdministeredDestinations>

<AdministeredTopic name=”charla”><Subscriber name=”sub1” /><Subscriber name=”sub2” />

</AdministeredTopic>

<AdministeredQueue name=”queue1” /><AdministeredQueue name=”queue2” /><AdministeredQueue name=”queue3” />

</AdministeredDestinations>

<!— Opcional. Si no se especifica, no se crearan usuarios—><Users>

<User name=”admin” password=”openjms” /> </Users>

</Configuration>

Page 41: Revista Solo Programadores #124

Sólo Programadoresen FormatoDigitalCon el respaldo de más de diez añosde publicación mensual y sin interrupcionesEntra en http://digital.revistasprofesionales.comSuscripción anual a Sólo Programadores por sólo 27 euros y a Sólo Programadores y Mundo Linux por sólo 40 euros

Regalo de un CD-ROM con el archivo de los 12 ejemplaresde la temporada 2003-04

Page 42: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

suscripción y más opciones. Como ejemplovemos en el listado 1 el archivo de configu-ración utilizado para ejecutar el ejemplo queacompaña a este artículo. Podemos observar las instrucciones másrelevantes para una configuración con unconector RMI, que es la que viene conOpenJMS por omisión al momento de insta-larlo. Los posibles elementos de configura-ción de este archivo se pueden ver en latabla “Opciones de configuración del servi-dor OpenJMS”. A continuación vamos arepasar algunos ejemplos de estos elemen-tos de configuración.Configuración JDBC.En el listado 2 se muestra un ejemplo deconfiguración JDBC. Actualmente OpenJMS

esta configurado para ser compatible conJDBC 2.0 y varios sistemas de bases de datos.Además de agregar este fragmento de códi-go a nuestro archivo de configuración, esnecesario agregar al CLASSPATH la ruta denuestro driver JDBC.Configuración de Conectores OpenJMS.OpenJMS proporciona conectividad a travésde varios protocolos utilizando conectores.El listado 3 muestra un ejemplo de configu-ración para habilitar un conector RMI.Los conectores soportados actualmente porOpenJMS son: RMI, TCP, TCPS, HTTP, HTTPS,Embedded.Una ventaja importante de OpenJMS es quenos permite definir múltiples conectores anuestro servidor.

Configuración de seguridad.OpenJMS proporciona configuraciones pararealizar autenticación de conexiones. Paraello se utilizan 2 elementos de configura-ción, “<SecurityConfiguration>” y “<Users>”.El listado 4 muestra cómo utilizar dichos ele-mentos para habilitar la autenticación deconexiones.Como podemos observar, OpenJMS propor-ciona una amplia gama de características deconfiguración, lo que lo convierten en unservidor JMS muy versátil. La finalidad deeste apartado es mostrar un panoramageneral de las opciones de configuración deOpenJMS. Para conocer con mayor detalle lainformación para la configuración, puedesrecurrir a la página del proyecto en Internet.

Ejemplo con el modelo pub/sub y OpenJMS

Como ejemplo de aplicación JMS ofrecemosel típico chat. Se trata de una sola clase java“ClienteJMSChat.java”, que actúa tantocomo suscriptor como publicador de untópico de mensajes JMS. Por tanto, se tratade un ejemplo del modelo de publicación/suscripción. Hay que decir que el ejemplo aquí propues-to es realmente exagerado, el hecho de utili-zar un sistema robusto como JMS para unaaplicación de chat es quizá excesivo, perosirva como ilustración.Los métodos de nuestra clase son lossiguientes:� main(). Conocido método principal para

hacer que la clase sea ejecutable.� initialize(String, String, String). Método

de instancia para la inicialización de laclase como su propio nombre indica.Veremos su contenido a continuación.

� show(). Muestra el mensaje recibidodesde el sistema JMS.

� debug(). Método para ver mensajes dedepuración. Separado de “show()” porconveniencia, aunque realmente hacen lomismo.

� chatIt(String). Envía un mensaje al tópi-co JMS.

� onMessage(Message). Método que debeimplementar la clase para recibir mensa-jes JMS.

� close(). Cierra la conexión JMS abierta.En la ejecución del ejemplo, el programa nosva a ir sacando trazas por pantalla, que ayu-darán a comprenderlo mejor.

46

REDES

http://digital.revistasprofesionales.com

Opciones de configuración del servidor OpenJMSConfiguración Descripción

JDBC OpenJMS se puede configurar para usar bases de datos JDBC paraimplementar persistencia de mensajes.

Conectores OpenJMS OpenJMS proporciona opciones de conectividad sobre varios proto-colos, utilizando conectores.

JNDI OpenJMS utiliza JNDI para hacer disponibles al cliente: fábricas deconexiones, tópicos, y colas.

Fábricas de conexión OpenJMS permite configurar la fábrica de conexiones con distintasopciones.

Seguridad OpenJMS proporciona mecanismos para implementar autenticaciónde conexiones.

Destinos Los destinos son registrados con JNDI por el servidor OpenJMS paraque estén disponibles a los clientes.

Garbage collection OpenJMS permite configurar al detalle la manera en que se ejecuta-rá el recolector de basura.

LISTADO 2 Ejemplo de configuración JDBC

<DatabaseConfiguration><RdbmsDatabaseConfiguration

driver=”oracle.jdbc.driver.OracleDriver”url=”jdbc:oracle:oci8:@myhost” user=”openjms” password=”openjms” />

</DatabaseConfigura>

LISTADO 3 Ejemplo de configuración de un conector RMI

<Connectors><Connector scheme=”rmi”>

<ConnectionFactories><QueueConnectionFactory name=”QueueConnectionFactory”/><TopicConnectionFactory name=”TopicConnectionFactory”/>

</ConnectionFactories></Connector>

</Connectors>

LISTADO 4 Ejemplo de configuración para habilitar autenticación de conexiones

<SecurityConfiguration securityEnabled=”true”/><Users>

<User name=”admin” password=”openjms”/><User name=”user1” password=”password1”/><User name=”user2” password=”password2”/>

</Users>

Page 43: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

La función main()Pasemos a examinar la función principal“main()”. En primer lugar observamos quesalta una excepción si el número de argu-mentos pasados es inferior a tres. Los argu-mentos que hay que pasar son: el primero eltópico al cual queremos conectar, el segundoel nombre de usuario que vamos a utilizar y eltercero la contraseña del usuario (obviamen-te no se permiten en este caso contraseñas enblanco). Más adelante veremos cómo hay queconfigurar el servidor JMS para que esté dis-ponible el tópico para el cliente.A continuación instanciamos un objeto de laclase “ClienteJMSChat” y la inicializamos conlos argumentos anteriores. Una vez hecho estoobtenemos el stream de la entrada estándarpara poder leer los mensajes que el usuario

escribe. Todo texto que escriba el usuario espasado al objeto instanciado llamando almétodo “chatIt()” excepto en el caso de que secorresponda con el comando de salida“EXIT_COMMAND” (también configurablemediante una variable estática) que hará que elprograma termine. Si durante la comunicaciónocurre un problema en la capa JMS la captura-remos con la excepción correspondiente.En el listado 5 podemos observar la parteprincipal de este método.

Inicialización JMSLos pasos para inicializar nuestro programaJMS son los siguientes:1. Inicializar JNDI.2. Obtener el objeto Factory JMS.3. Crear una conexión al servidor JMS

mediante el objeto Factory.4. Obtener dos sesiones JMS, una para

publicar y otra para suscribirse al tópico(recordar que nuestro programa actúacon ambos roles).

5. Obtener el objeto tópico a través de JNDI.6. Por cada sesión, obtener un objeto publi-

cador y suscriptor respectivamente, queactúan como agentes de comunicación.

7. Registrar en el suscriptor la clase actualpara que reciba los mensajes que sepublican en el tópico.

8. Por último, realizar la conexión con el ser-vidor.

En el listado 6 podemos ver estos pasos. Lasvariables que no aparecen declaradas sonvariables de clase, se puede consultar elcódigo completo para ver su declaración. Enconcreto y para conectar con JMS, los datosque hay que proporcionar son:

47

REDESSistemas de mensajería con Java Message Service (I)

http://digital.revistasprofesionales.com

LISTADO 5 Parte principal del método main()

ClienteJMSChat chat = new ClienteJMSChat();//Argumentos: topic - nombre de usuario - contraseñachat.initialize(args[0], args[1], args[2]);

//Leer los mensajes desde la consolaBufferedReader consola = new java.io.BufferedReader(new InputStreamReader(System.in));

//Bucle hasta que se introduzca el comando de finalizaciónwhile (true) {

String s = consola.readLine();try {

if (s.equalsIgnoreCase(EXIT_COMMAND)) {chat.close(); //Cerrar la conexiónbreak;

} else {chat.chatIt(s);

}} catch (JMSException jmse) {

chat.debug(“Excepcion JMS: “ + jmse.getMessage());break;

}}

LISTADO 6 Inicializando el servicio de mensajería

//Obtener una conexión JNDI para acceder a los objetos JMSProperties properties = new Properties();

//Propiedades específicas para conectar con OpenJMSproperties.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY);properties.put(Context.PROVIDER_URL, PROVIDER_URL);

try {//Obtener contexto inicial JNDIInitialContext context = new InitialContext(properties);

//Obtener la factoría JMSTopicConnectionFactory conFactory = (TopicConnectionFactory) context

.lookup(TOPIC_CONNECTION_FACTORY);

//Crear la conexiónTopicConnection conexion = conFactory.createTopicConnection(

usuario, password);

//Creamos dos sesiones, una para publicación, donde se envían los // mensajes que escribimos, y otra para suscribirnos al tópico, de// forma que recibamos los mensajes que allí son enviados.TopicSession sesionP = conexion.createTopicSession(false,

Session.AUTO_ACKNOWLEDGE);TopicSession sesionS = conexion.createTopicSession(false,

Session.AUTO_ACKNOWLEDGE);

//Obtener el tópico JMSTopic topicObj = (Topic) context.lookup(topico);

//Crear un publicador y un suscriptor JMSTopicSubscriber suscriptor = sesionS.createSubscriber(topicObj);TopicPublisher publicador = sesionP.createPublisher(topicObj);

//Esta misma clase es la que recibe los mensajessuscriptor.setMessageListener(this);

...

//Iniciar la conexion, a partir de aquí los mensajes pueden ser// enviados al tópicoconexion.start();

} catch (NamingException ne) {throw new RuntimeException(“Error JNDI”, ne);

} catch (JMSException jmse) {throw new RuntimeException(“Error JMS”, jmse);

}

Page 44: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

CONTEXT_FACTORY = “org.exolab.jms.

jndi.InitialContextFactory”

PROVIDER_URL = “rmi://localhost:1099/”

(suponiendo que se conecta al host local)

TOPIC_CONNECTION_FACTORY = “JmsTopic

ConnectionFactory”;

Envío y recepción de mensajesComo nuestra clase implementa el interface“javax.jms.MessageListener”, debemos crearel método “onMessage()” que recibe losmensajes que provienen del sistema JMScuando algún cliente envía un mensaje altópico. Según vemos en la implementación,el método recibe un mensaje tipo “Message”,se convierte a un mensaje de tipo texto yobtenemos el texto como cadena para mos-trarlo en la consola (véase el listado 7).Por último examinamos cómo se envían losmensajes al tópico. Simplemente creamosun mensaje tipo texto desde el objeto sesiónque corresponde al publicador y establece-mos la cadena del mensaje que queremosenviar. A continuación utilizamos el objetopublicador para enviar el mensaje al tópico,como vemos en el listado 8.En el código que acompaña a este artículopodemos observar que en los “imports” no sehace referencia a ninguna clase específica deJMS, únicamente al obtener el contexto ini-

cial JNDI es donde especificamos datos pro-pios de OpenJMS, pero incluso esto lo hemosaislado en una variable estática, el códigofácilmente puede ser adaptado para que leadichos datos de un archivo .properties exter-no, por ejemplo.Para compilar y ejecutar el ejemplo, ademásdel fuente necesitaremos incluir la API JMS yla implementación OpenJMS para el cliente.Los archivos .jar que vamos a necesitar son lossiguientes:� jms-1.0.2a.jar: API JMS.� openjms-client-0.7.6.1.jar: Implementación

para clientes OpenJMS.

Ejecutar el ejemploPara ejecutar el ejemplo, ofrecemos tresopciones:

� Importar el proyecto en el IDE Eclipse.� Utilizar Ant para compilar, crear el java-

doc y ejecutarlo.� Utilizar un script .bat (.sh para linux) para

ejecutarlo.Para importar el proyecto a Eclipse, utilizare-mos la opción “Import” del menú “File”, yespecificaremos que se trata de un proyectoexterno. También podemos copiar el directo-rio dentro del workspace de Eclipse, y crear unnuevo proyecto Java con el mismo nombre,para que sea reconocido dentro del editor.Para aquellos lectores familiarizados con Ant(http://ant.apache.org) el ejemplo viene conel script correspondiente con el que podre-mos compilar, ejecutar el ejemplo e inclusocrear el javadoc.Por último, para hacerlo más sencillo, pro-porcionamos los scripts para la ejecución delejemplo desde consola: “run.bat”(Windows)y “run.sh” (Linux). Deberemos proporcionarlos parámetros necesarios a estos scripts,según se ha explicado.

Conclusiones

Hasta la llegada de JMS, cada proveedor demensajería definía su propia API. Mientrasque cada solución tenía sus propios proto-colos, la similitud lógica entre las distintasversiones eran las mismas. Esto hizo posiblela existencia de JMS para estandarizar dealguna forma el desarrollo de sistemas demensajería.JMS se convierte en una API simple y a la vezrobusta, para la implementación en nuestrasaplicaciones de este tipo de sistemas, con laventaja de que existen soluciones OpenSource ya maduras como OpenJMS que pode-mos utilizar de una forma productiva.

48

REDES

http://digital.revistasprofesionales.com

LISTADO 7 Recepción de un mensaje

try {TextMessage textMessage = (TextMessage) message;String text = textMessage.getText();show(text);

} catch (JMSException jmse) {jmse.printStackTrace(System.out);

}

LISTADO 8 Envío de un mensajeTextMessage message = sesionP.createTextMessage();message.setText(“[“ +usuario + “] “ + text);publicador.publish(message);

Sobre el autorEduardo Millán Martínez ([email protected]) es Ingeniero Técnico en Telecomunicaciones por la Universidad Politécnica de Valencia. Desde diciembre del 2004trabaja en la empresa Saytel, Premier Business Partner de IBM como consultor de desarrollo. Eduardo lleva trabajando en proyectos Java desde el año 1998 y es socioactivo de javaHispano desde 2002. Actualmente es responsable de Calidad y Administrador del sitio de proyectos de Software Libre: http://www.javahispano.net.

Figura 5. Ejecución del ejemplo en Eclipse.

Page 45: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

En el número anterior analizamos las necesida-des, actividades y características de trabajo delos Analistas de Negocio, Analistas Funcionales, yJefes de Proyecto, así como las soluciones pro-porcionadas por Borland para automatizar y agi-lizar su trabajo diario. En este número avanzaremos un poco más en elciclo de vida de desarrollo, e identificaremos lasnecesidades de perfiles como Arquitectos,Consultores Técnicos, Analistas Programadores,o Responsables Técnicos de Desarrollo. La carac-terística común a todos ellos es la necesidad detrabajar paralelamente con código y modelo, asícomo la necesidad de poder acceder a los requi-sitos y a los modelos de negocio. Por supuesto,también es necesario para todos ellos poder tra-bajar en grupo sobre un repositorio centralizado,en el que residan tanto los modelos como elcódigo. Por último, la mayoría de estos perfilestambién necesitan poder ejecutar pruebas unita-rias funcionales y pruebas de rendimiento sobrelos componentes desarrollados.Borland, en su plataforma SDP (Software DeliveryPlatform), identifica a todos estos perfiles con elnombre genérico de “Architect”. En realidad, esteperfil es cada día más común en los equipo dedesarrollo, en los que los programadores clásicos,

centrados exclusivamente en el código, han idoevolucionando a perfiles más multidisciplinaresque participan en varias de las fases del ciclo devida de desarrollo, o que, como mínimo, necesi-tan obtener información de ellas. En este artículonos referiremos a todos los roles anteriormenteseñalados con el nombre genérico de “arquitecto”.

El arquitecto y sus necesidades

La principal información de partida para losarquitectos es, sin duda, los requisitos de un sis-tema. El objetivo del arquitecto es modelar diná-micamente infraestructuras complejas y distri-buidas a partir de las últimas versiones de losrequisitos funcionales, de negocio, operacionalesy de arquitectura. Adicionalmente, el objetivo delarquitecto es que todos los miembros del equipode desarrollo conozcan cuál es su visión del sis-tema y que conozcan las decisiones y restriccio-nes técnicas que ha definido.Así pues, para un arquitecto, lo más importanteserá poder integrar el proceso de diseño con elsistema de Gestión de Requisitos, aumentando elcontrol de los cambios en los mismos, y pudien-do garantizar la visibilidad de sus modelos alresto del equipo.Hay que tener en cuenta, además, que paradeterminados tipos de proyectos y equipos dedesarrollo, es necesaria la figura del Analista deNegocio o Funcional, responsable de transformarlos requisitos expresados en lenguaje natural endiagramas de negocio (casos de uso, diagramasde estado, etc.). Estos diagramas son los que enterminología MDA (Model Driven Architecture)se han englobado bajo el nombre genérico deComputation-Independet Models (CIM). El arqui-tecto, en cambio, deberá convertir esos diagra-mas en modelos computacionales, que podránser independientes de la plataforma (PIM) oespecíficos de una plataforma (PSM).En general, el arquitecto es el responsable detransformar un conjunto de especificaciones(PROBLEMA) en un sistema (SOLUCIÓN). Estatransformación se realiza a través de diferentespasos, y en cada uno de ellos se usa un conjun-to de modelos (típicamente UML en el mundoOrientado a Objetos) que van desde una repre-

50

Together Architect es la soluciónde Borland para dar respuesta a lasnecesidades de todo arquitecto de software. En este artículoestudiaremos cuáles son estasnecesidades y cómo TogetherArchitect puede ayudar a lascompañías de software a crear,mantener y comunicar los modelosconceptuales de un sistema a partirde los requisitos.

JORDI BORJA (Director de Tecnología de Borland)

DISEÑO

Together Architect, el enlace entre el problemay la solución

Together Architect, el enlace entre el problemay la solución

http://digital.revistasprofesionales.com

Page 46: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

sentación más abstracta del sistema a unarepresentación más específica sobre la pla-taforma elegida para la implementación dela solución.Los tres niveles de modelado definidos porMDA deben de poder ser relacionados entresí. Por ejemplo, debería ser posible poderconocer qué diagramas de clases estánrelacionados con un requisito concreto, oqué diagramas de secuencia implementanun caso de uso determinado. Además,deberá ser posible que diferentes perfilesdentro de un equipo de desarrollo hayancreado cada uno de estos diagramas.Un arquitecto, como hemos comentado pre-viamente, necesita poder trabajar de formaparalela con código y modelos, disponiendode herramientas que permitan la sincroniza-ción automática entre ambas vistas. Uncambio en el modelo debe poder transmitir-se automáticamente al código, y viceversa.Además, como un arquitecto puede partici-par en proyectos en los que se utilicen demanera combinada múltiples tecnologías ylenguajes de programación, los modelosdeben poderse reutilizar para generar códigosobre diferentes plataformas.Adicionalmente, un arquitecto necesitaaumentar la productividad, eficiencia, ypredictibilidad en sus tareas de diseño. Espor ello que la reutilización de conocimien-to a través de blueprints, plantillas o patro-nes de diseño resulta imprescindible.Por último, un arquitecto necesita podergenerar documentación personalizada apartir de los modelos definidos, que incluyalas relaciones entre ellos, y las relacionescon los requisitos.

Borland Together Architect

Borland Together Architect es la respuestade Borland a todas estas necesidades y amuchas más. Together Architect es unasolución ágil de modelado diseñada porBorland para ayudar a las compañías dedesarrollo a crear, mantener y comunicarlos modelos conceptuales de un sistema apartir de los requisitos.

MDA ya es una realidadCon una clara orientación al desarrolloorientado por el modelo (MDD), esta herra-mienta permite hacer realidad la filosofíaMDA, permitiendo a los equipos de des-arrollo transformar requisitos en códigomediante un entorno visual fácil de usar, ycon soporte a todos los diagramas del len-guaje UML, incluyendo los definidos en laversión 2.0 de la especificación y OCL(Object Constraint Language).

Together Architect incorpora integracionescon Borland Caliber RM, Telelogic DOORS eIBM RequisitePro, con el objetivo de que losmodelos de negocio sean construidos apartir de las últimas versiones de los requi-sitos. Integrando con estos productos esposible gestionar la trazabilidad entrerequisitos y modelos. Adicionalmente, si seha elegido Borland Caliber RM para laGestión de Requisitos, Together Architectincorpora un cliente embebido con toda lafuncionalidad del cliente nativo, con elobjetivo de que el arquitecto pueda partici-par en el proceso de Gestión de Requisitos.

La independencia de la tecnologíaEl coste de acoplar una arquitectura a unainfraestructura concreta, en un entorno tec-nológico cambiante como el actual, puedeser muy elevado. Es por ello que TogetherArchitect posibilita crear modelos indepen-dientes de la plataforma, permitiendo unarápida adaptación a cambios tecnológicos oa cambios en los requisitos. Por ejemplo, enlugar de definir un sistema en base a undeterminado lenguaje de programación,Together permite crear modelos en un len-guaje formal independiente de la platafor-ma, para posteriormente ser convertidos a laplataforma .NET o a J2EE. El código fuente esgenerado en un proceso de transformación,de forma que los programadores puedentrabajar posteriormente en ese lenguaje consu entorno de desarrollo preferido.

Visión única del sistemaLos modelos de un sistema pueden sercompartidos por Analistas de Negocio(véase Together Designer en el númeroanterior de Sólo Programadores) o por losprogramadores, a través de los diversosplug-ins de Together para entornos de des-

arrollo como JBuilder, Eclipse, C++Builder oMS VS.NET. De este modo, es posible quetodo el equipo de desarrollo comparta unaúnica visión del sistema, y que cualquiercambio en los modelos sea automática-mente notificado al resto de miembros delequipo de desarrollo.Además, los modelos relacionados con laplataforma están completamente sincroni-zados con el código. Esto significa quecualquier cambio que realice un programa-dor en el código Java, C#, C++, Visual Basic,etc. a través de una refactorización porejemplo, será de igual forma visible por losperfiles que trabajen sobre el modelo.

Cohesión totalComo se ha visto, la sincronización y la tra-zabilidad son las principales característicasde un desarrollo en el que el modelo con-ceptual se ha realizado con Together. Poruna parte, como hemos comentado, losrequisitos están trazados con los elementosdel modelo. En segundo lugar, los diferentesmodelos pueden enlazarse entre sí, permi-tiendo, por ejemplo, asociar modelos inde-pendientes de la plataforma o de negociocon modelos dependientes de la plataforma.Por último, los modelos dependientes de laplataforma están siempre sincronizados conel código. De esta forma, se consigue cohe-sionar al equipo de desarrollo, aumentandoel control y gestión del cambio, y la visibili-dad compartida del sistema.Gracias a su capacidad de mantener código ymodelos sincronizados, Together es la solu-ción ideal para realizar ingeniería inversa desistemas, generando de ese modo modelos apartir de código existente. La ingenieríainversa facilita la comprensión de un sistemay su mantenimiento. En efecto, a través delas capacidades de refactoring, aplicación de

51

DISEÑOTogether Architect, el enlace entre el problema y la solución

http://digital.revistasprofesionales.com

Integración de Caliber en Together Architect.

Page 47: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

patrones de diseño, auditoría de código ymétricas de diseño, Together permite valorarla calidad de un sistema, y facilitar su mante-nimiento correctivo y evolutivo.

Patrones de diseñoLa aplicación de patrones de diseño permitereutilizar soluciones previamente probadaspor otros para resolver problemas que serepiten entre proyectos, así como ajustarnuestras aplicaciones a las buenas prácticasde la industria. Together incorpora los patro-nes de diseño creacionales, estructurales y decomportamiento conocidos como GoF(Gang-of-Four), además de proporcionar losprincipales patrones de diseño aplicables a laplataforma específica de desarrollo. Pero…¿qué ocurre si queremos definir nuestrospropios patrones de diseño, o buenas prácti-

cas? Ningún problema: Together es unaherramienta totalmente flexible y extensible.Podemos definir nuestros propios patronesde diseño para poder ser reutilizados en otrosproyectos, y de esa forma crearnos nuestropropio catálogo de patrones personalizado,que podrán también ser utilizados tambiéndesde las herramientas de desarrollo preferi-das de los programadores.

Garantías de calidadOtra de las necesidades actualmente másimportante para un arquitecto, o Responsablede Desarrollo, es el poder valorar la calidad delcódigo fuente en base a un conjunto de nor-mativas, nomenclaturas, buenas prácticas yguías de estilo, bien universalmente aceptadas(por ejemplo, los blueprints de la plataformaJ2EE) o definidos para un cliente o de formacorporativa. Together permite auditar el códi-

go fuente antes de ser entregado, y garantizarla homogeneidad de calidad entre los diferen-tes miembros del equipo de desarrollo. Pordefecto, Together verifica el cumplimiento delas buenas prácticas y nomenclaturas estánda-res para el lenguaje de programación seleccio-nado, pero es posible construir un conjuntopropio de reglas sintácticas y de programación,que podrá de nuevo ser utilizado y validado enlas herramientas de codificación. Algo similar ocurre con la calidad del propiodiseño. Cuantificar la calidad del diseñoOrientado a Objetos en términos de acopla-miento, tamaño, cohesión, complejidad, uso deherencia y polimorfismo, etc. permite conocerla calidad y eficiencia del equipo y de los pro-cesos de desarrollo, y detectar futuros proble-mas de extensibilidad, flexibilidad, robustez ofacilidad de mantenimiento de una solución.Together permite aplicar múltiples métricascuantificativas de la calidad de un desarrollo en

52

DISEÑO

http://digital.revistasprofesionales.com

Patrones de diseño en Together.

Auditorías en Together.

Métricas en Together.

Page 48: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

términos del uso de la Programación Orientadaa Objetos, y, cómo no, definir nuestro propioconjunto de métricas.

MetodologíasTogether es mucho más que una herra-mienta de modelado. Es una herramientacompleta de ingeniería que permite asegu-rar la calidad de un desarrollo y el cumpli-miento de los requisitos de un sistema.Además, es una herramienta que nos ofre-ce la flexibilidad necesaria para poder con-tinuar utilizando cualquier proceso y meto-dología de desarrollo. Desde RUP a eXtremeProgramming. Tener libertad de elección delproceso de desarrollo, en función del equi-po de desarrollo y del proyecto concreto esotra de las grandes ventajas de Together.

DocumentaciónSin embargo, para tener total flexibilidad a lahora de elegir nuestra metodología de des-arrollo, es también necesario que podamosdecidir cómo queremos entregar y documen-tar nuestro sistema. Con Together, es posiblegenerar documentación de todo el modelo apartir de plantillas de documentación perso-nalizables, en formato HTML, RTF o PDF.Podemos seleccionar el formato, la informa-ción a incluir y el nivel de detalle. Por supues-to, podremos incluir en nuestro documento deproyecto las relaciones del modelo con elcódigo (y su documentación estándar) y lasrelaciones con los requisitos de la aplicación.Un único documento para todo el proyecto,generado automáticamente con un simple clicde ratón con la última información disponible.

UML… y mucho másPara terminar el conjunto de capacidades dela herramienta, hay que señalar que Together

soporta diagramas no UML de gran impor-tancia y utilidad en los desarrollos actuales,como diagramas Entidad Relación lógicos yfísicos (estos últimos con generación de scriptSQL y sincronización con tablas relacionales),diagramas de XML Schemas, diagramas demodelado de procesos de negocio, modeladoen color, y un largo etcétera. Además, permi-te la exportación/importación de los proyec-tos conforme al estándar XMI, además deimportaciones específicas de diagramas reali-zados mediante Rose.

¿Y el trabajo en grupo?Together permite integrar con múltiples solu-ciones de control de versiones y configuracio-nes. En el caso de que utilicéis BorlandStarTeam como herramienta de trabajo engrupo, Together incluye un cliente embebidoque permite no únicamente realizar las activi-dades típicas de control de versiones, sino tra-bajar con peticiones de cambio, tareas, foros de

discusión, vistas evolutivas y correctivas, etc.Imaginaros que se produce una petición decambio en el sistema: automáticamente, losarquitectos responsables de atender a lapetición de cambio serán notificados en suherramienta de trabajo, y podrán enlazarlos cambios que realicen en el modelo delsistema a la incidencia, permitiendo de esemodo poder conocer qué cambios se hanrealizado para atenderla. Del mismo modo,la planificación del proyecto que se ha defi-nido, por ejemplo, con MS Project, genera-rá de forma automática tareas para cadauno de los perfiles del proyecto, de formaque cuando abran su herramienta demodelado podrán conocer cuáles son lastareas que debe realizar sin necesidad deconsultar el Gantt del proyecto. Adicionalmente, Together permite compa-rar modelos, para conocer los cambios quese han producido a lo largo del proyecto,compartir diagramas y fragmentos de losmismos entre proyectos, etc.

Conclusiones

La edición de Together para el Arquitecto,como hemos visto, no es una solución ais-lada dentro del ciclo de vida de desarrollo.Está totalmente integrada en la fase deGestión de Requisitos, así como en la deProgramación, y proporciona cohesión yvisibilidad a todo el equipo de desarrollo,gracias a la integración de la herramientacon las soluciones de trabajo en grupo líde-res en el mercado.En el próximo número analizaremos las solu-ciones de Borland para los programadores, ymostraremos cómo es posible que éstos acce-dan desde su herramienta de codificación a losmodelos definidos por el arquitecto y cómomantenerlos en sincronía con el código.

53

DISEÑOTogether Architect, el enlace entre el problema y la solución

http://digital.revistasprofesionales.com

Documentación en Together.

StarTeam en Together.

Page 49: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Introducción

Las dos entregas anteriores nos sirvieron paraentender hasta qué punto la librería ACE puedeayudarnos a diseñar y escribir aplicaciones C++multiplataforma. En la entrega que ahora nosocupa veremos cómo trabajar con la fecha y lahora, cómo gestionar el sistema de ficheros yalgunos patrones de diseño que la librería ACE nosayudará a implementar.

Operar con fechas y horas

La función “time()” de C devuelve la cantidad desegundos que han pasado desde el primero deenero de 1970 como un entero largo de tipo“time_t”. La plataforma Unix provee la estructura

“timeval” para encapsular una fecha/hora. Loimportante es que también en este aspecto, dife-rentes sistemas operativos proveen primitivasdiferentes para la gestión de estos datos.La clase “ACE_Time_Value” de la librería ACE pro-vee una interfaz portable que encapsula un valorde tipo tiempo. Puede encapsular un intervalo detiempo (por ejemplo una determinada cantidad desegundos o microsegundos) o una fecha absoluta. Esta clase permite convertir entre formatos detiempo de diferentes plataformas. Sus funcionespúblicas son:� set(): Permite establecer el valor de fecha. Hay

versiones sobrecargadas para cualquiera de lostipos de fecha disponibles en las distintas pla-taformas.

� sec(): Devuelve sólo el componente de segun-dos del valor encapsulado.

� usec(): Devuelve sólo el componente demicrosegundos del valor encapsulado.

� msec(): Convierte el valor encapsulado(“sec()”+”usec()”) en un valor de milisegundos ydevuelve este valor.

También posee operadores de comparaciónsobrecargados para poder comparar un objeto“ACE_Time_Value” con otros. Para poder usaresta clase es necesario incluir el fichero “ace/Time_Value.h”. Podemos obtener la hora actual del sistema de lasiguiente manera:#include <ace/Time_Value.h>

#include <ace/System_Time.h>

Ace_Time_Value hora_actual;

ACE_System_Time::get_local_system

_time(hora_actual);

Este código deja en la variable “hora_actual” lahora del sistema.

Acceso al sistema de ficheros

La librería estándar de C++ provee clases de tipotemplate que nos permiten trabajar fácilmente conel contenido de un fichero e incluso crear ficherosnuevos. Utilizando estas funciones podremos abrir,cerrar, leer y escribir desde y hacia ficheros tanto enmodo texto como en modo binario. El punto en el

54

En esta última entrega noscentraremos en conocer algunasclases adicionales de ACE que nospermiten escribir código portable yalgunas que implementan patronesde diseño de uso bastante habitual.

GABRIEL DOS SANTOS DÁVILA

DISEÑO

Diseño multiplataformapara aplicaciones C++ (y III)Diseño multiplataformapara aplicaciones C++ (y III)

http://digital.revistasprofesionales.com

Documentación de la clase “ACE_System_Time”.

Page 50: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

que la librería estándar carece de funcionali-dad es en el referente al trabajo con los fiche-ros en si en lugar de su contenido. Si necesi-tamos borrar ficheros o listar los ficherosdentro de un directorio no podremos hacerlosutilizando la librería estándar. La navegaciónde un sistema de ficheros no es igual enWindows que en Unix y por lo tanto necesita-remos utilizar las abstracciones de ACE pararealizar estas tareas de forma portable.

Borrar ficherosEl borrado de un fichero es una tarea suma-mente simple utilizando ACE. Para compro-barlo haremos una copia del proyecto“Esqueleto” que creamos en la primeraentrega y modificaremos el código delmismo para que reciba un nombre de fiche-ro como parámetro de la línea de comandosy, luego de pedir una confirmación, lo borredel disco.

En el listado 1 vemos el contenido del fiche-ro “main.cpp”. En la función “main()” se veri-fica que el ejecutable haya sido invocadocon un parámetro y se utiliza la función“ACE_OS::unlink()” para eliminar el ficherosolicitado, no sin antes confirmar la elimina-ción. Hemos de tener mucho cuidado con eluso de este programa porque en Windowsno mueve los ficheros a la papelera de reci-claje sino que los borra directamente y siborramos un fichero por error sólo podre-mos recuperarlo con una herramienta derecuperación de ficheros borrados y un pocode suerte.La función “ACE_OS::unlink” utiliza las fun-ciones específicas de cada sistema operati-vo para eliminar el fichero indicado ydevuelve un número entero. Si devuelve unvalor menor que cero significa que la lla-mada a la función falló. Esto podría ocurrirporque el fichero está siendo usado y porello no puede eliminarse, porque no secuenta con los permisos suficientes paraborrarlo o simplemente porque el ficherono existe.

Listar los contenidos de un directorioPara crear una lista de todos los archivoscontenidos dentro de un directorio utili-zaremos la clase “ACE_Dirent_Selector”.Esta clase implementa un iterador deentradas de directorio basado en la fun-ción “scandir” del API POSIX al que se lepueden pasar filtros para limitar los resul-tados devueltos. Nuevamente partiremos de nuestro esquele-to vacío de la primera entrega y en el fiche-ro “main.cpp” escribiremos el código del lis-tado 2. El programa recibe como parámetrouna ruta del sistema de ficheros (el nombrede un directorio) y muestra todos los archi-vos y subdirectorios contenidos en éste,incluidos los denominados “.” y “..” que repre-sentan al directorio actual y al directoriopadre del mismo. Si en lugar de un directo-rio se indica como parámetro un nombre dearchivo, la función “length()” devolverá 0 y elprograma no dará ningún error.El operador [] de la clase “ACE_Dirent_Selector” devuelve un puntero a una estruc-tura “dirent” que posee información sobrecada una de las entradas del directorio de lacual sólo nos interesa el nombre, el cual obte-nemos por medio de atributo “d_name”, quecontiene un char* con el nombre de la entrada.Si en lugar de mostrar sólo el contenido deun directorio quisiéramos mostrar el de unárbol de directorios completo bastaría concambiar la función “listar_directorio()” paraque funcione recursivamente de la siguien-te manera:

55

DISEÑODiseño multiplataforma para aplicaciones C++ (y III)

http://digital.revistasprofesionales.com

LISTADO 1 Borrar un fichero del disco

#include <ace/OS.h>#include <string>#include <iostream>

int main(int argc, char* argv[]){try{

if (argc<2) return -1;std::string fichero(argv[1]);std::cout << “¿Realmente desea borrar el fichero “<< fichero << “?”<< std::endl;std::string borrar;std::cin >> borrar;if (borrar==”s”){

int result= ACE_OS::unlink(fichero.c_str());if (result<0){

std::cout << “No se pudo eliminar el fichero. “<< “Es posible que no exista.” << std::endl;

}return result;}return 0;

}catch(...){std::cout << “Excepción durante la ejecución” << std::endl;return -1;

}}

LISTADO 2 Mostrar todos los archivos de un directorio

#include <ace/OS.h>#include <ace/Dirent_Selector.h>#include <string>#include <iostream>

void listar_directorio(char* directorio){ACE_Dirent_Selector dir;dir.open(directorio);for(int i=0;i<dir.length();i++){

std::cout << std::string(dir[i]->d_name) << std::endl;

}dir.close(); //No es necesario pues está en el stack

//y se ejecuta en el destructor}

int main(int argc, char* argv[]){

try{if (argc<2) return -1;listar_directorio(argv[1]);

}catch(...){std::cout << “Excepción durante la ejecución” << std::endl;return -1;

}return 0;

}

Page 51: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

void listar_directorio(char* directorio){

ACE_Dirent_Selector dir;

std::cout << std::string(dir[i]->d_name)

<< std::endl;

dir.open(directorio);

for(int i=0;i<dir.length();i++){

if (nombre!=”.” && nombre!=”..”)

listar_directorio(dir[i]->d_name);

}

dir.close();

}

Para probar el código debemos compilarlo yejecutarlo pasando como parámetro unnombre de directorio. Si todo funcionacorrectamente, veremos por la salida están-dar la lista de los archivos contenidos en eldirectorio y en todo el árbol de subdirecto-rios. El listado de archivos de este ejemploincluye todas las entradas de los directoriospero es posible que en algún caso deseemosfiltrar el listado mostrando sólo algunas delas que aparezcan. Una posibilidad parahacer esto es agregar un sentencia if antesde mostrar el nombre por salida estándar enla función “listar_directorio”, tal como hace-mos en este ejemplo para filtrar las entradas“.” y “..” pero ACE provee una solución similarque ya viene incorporada dentro del frame-work. Para lograr este objetivo debemoscrear una función que actúe como filtro ypasársela como parámetro al método “open”de “ACE_Dirent_Selector”.El primer paso será crear una función con lafirma:int nombre_funcion(cons dirent* d)

Esta función será invocada automáticamen-te por cada entrada de directorio detectadapor “ACE_Dirent_Selector” y debe devolver 1para aceptar esa entrada o 0 para filtrarla. En

nuestro caso, crearemos una función quemuestre sólo los ficheros que contengan“.txt” en su nombre y que filtre el resto, peropodría extenderse para filtrar cualquier cosaque deseemos.En “main.cpp”, antes de la función “main()”,agregaremos la siguiente función:int dirselector(const dirent * d){

int i=1;

std::string filename(d->d_name);

if (filename.find(“.txt”)== std::

string::npos)

return 0;

else

return 1;

}

La función “dirselector” extrae el nombre dela entrada de la estructura “dirent”, si estenombre corresponde a alguno de los ele-mentos que no deseamos mostrar devuelve1 y si no devuelve 0.Por último, remplazaremos la invocación almétodo “open” de la clase “ACE_Dirent_Selector” en la función “listar_directorio” porlo siguiente:dir.open(directorio,dirselector);

En el listado 3 podemos ver la versión finaldel programa con el filtro activado. Si locompilamos y ejecutamos, sólo mostraráaquellos ficheros que nos interesan.

Patrones de diseño

Dentro de las facilidades de ACE podemosencontrar no sólo clases que nos permitenescribir código portable sino también otrosconjuntos de clases que implementan algu-

56

DISEÑO

http://digital.revistasprofesionales.com

LISTADO 3 Filtrar la lista de archivos

#include <ace/OS.h>#include <ace/Dirent_Selector.h>#include <string>#include <iostream>

int dirselector(const dirent * d){int i=1;std::string filename(d->d_name);if (filename.find(“.txt”)==std::string::npos)

return 0;else

return 1;}

void listar_directorio(char* directorio){ACE_Dirent_Selector dir;dir.open(directorio,dirselector);for(int i=0;i<dir.length();i++){

std::cout << std::string(dir[i]->d_name) << std::endl;

}dir.close(); //No es necesario pues está en el stack

//y se ejecuta en el destructor}

int main(int argc, char* argv[]){

try{if (argc<2) return -1;listar_directorio(argv[1]);

}catch(...){std::cout << “Excepción durante la ejecución” << std::endl;return -1;

}return 0;

}

Listado de directorios generado por la aplicación de ejemplo.

Page 52: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

nos frameworks y patrones de diseño de usohabitual también de manera independientede la plataforma, basándose para ello en lasclases Wrapper Façade que hemos vistohasta ahora.

SingletonEl patrón Singleton define una técnica paraasegurar que sólo existe una instancia deuna clase determinada durante todo el tiem-po de vida de un programa. Podría enten-derse como el equivalente orientado a obje-tos de una variable global. Se utiliza en oca-siones en que un mismo objeto debe utili-zarse en muchas partes del código de unprograma, en funciones distintas. Para ello,en lugar de pasar referencias entre funcio-nes a la única instancia, se emplea unSingleton que permita accederla de maneraglobal. ACE provee clases template que permiten demanera muy sencilla transformar cualquierclase en un Singleton. Para ello crearemos enprimer lugar la clase en cuestión.Supongamos que tenemos una aplicacióncuyos parámetros de configuración se hande mantener en memoria en un lugar cen-tralizado y queremos crear una clase paraencapsular el acceso a estos parámetros de

configuración. El objeto que provea estafuncionalidad deberá estar accesible desdetoda la aplicación y deberá existir una únicainstancia para tener centralizado el controlde los parámetros. Tenemos aquí un exce-lente candidato a ser implementado comoun Singleton. En primer lugar crearemos la cabecera de laclase que encapsula los parámetros (“para-metros.hpp”, véase el listado 4)A continuación crearemos la implementa-ción (“parametros.cpp”). No nos detendre-mos a describir la implementación completade las funciones para leer y guardar losparámetros pues no es ese el objetivo delartículo. En cambio, nos limitaremos a defi-nir los métodos necesarios y ver cómo con-vertir la clase en un Singleton (vea esto en ellistado 5). Una vez escrita la clase, haremos las modifi-caciones necesarias para la implementacióndel patrón Singleton en el fichero “parame-tros.hpp” (véase el listado 6).Como podemos ver en el código hemos rea-lizado tres modificaciones. Para implemen-tar el patrón Singleton alcanza con la decla-ración del tipo “parametros_singleton”.Adicionalmente hemos hecho privado elconstructor de la clase parámetros y decla-ramos a la clase Singleton como friend paraevitar que algún programador pueda crear

57

DISEÑODiseño multiplataforma para aplicaciones C++ (y III)

http://digital.revistasprofesionales.com

LISTADO 4 parametros.hpp, primera versión

#ifndef PARAMETROS_HPP#define PARAMETROS_HPPclass parametros{public:

parametros(void);~parametros(void);std::string leer_parametro(std::string nombre);void modificar_parametro(

std::string nombre, std::string valor

);private:

//crear una variable para guardar los parametros};#endif //PARAMETROS_HPP

LISTADO 5 parametros.cpp

#include “parametros.hpp”parametros::parametros(void){

//lee fichero de paramtros}parametros::~parametros(void){

//escribe fichero de parametros}std::string parametros::leer_parametro(std::string nombre){

//devuelve el valor de un parametroreturn “”;

}void parametros::modificar_parametro(

std::string nombre, std::string valor){//modifica el valor de un parametro

}

Site del libro en el que se basa el diseño de ACE.

LISTADO 6 parametros.hpp, segunda versión

#include <string>#include <ace/Singleton.h>#include <ace/Null_Mutex.h>class parametros{

friend class ACE_Singleton<parametros,ACE_Null_Mutex>;public:

~parametros(void);std::string leer_parametro(std::string nombre);void modificar_parametro(

std::string nombre, std::string valor

);private:

parametros(void);//crear una variable para guardar los parametros

};typedef ACE_Singleton<parametros,ACE_Null_Mutex>

parametros_singleton;

Page 53: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

instancias de la clase parámetro por sucuenta, salteándose la restricción delSingleton. La clase template “ACE_Singleton” recibedos parámetros. El primero es la clase a laque queremos convertir en Singleton y elsegundo es el tipo de mecanismo de exclu-sión mutua a utilizar para sincronizar elacceso de los distintos threads a la únicainstancia del Singleton. En aplicaciones deun único thread se puede usar “ACE_Null_Mutex”, en cuyo caso no se aplicará nin-gún mecanismo de exclusión. Si estamoscreando una aplicación multithreaded, esnecesario que la declaración del Singletonutilice “ACE_Recursive_Thread_Mutex”:typedef ACE_Singleton<parametros,

ACE_Recursive_Thread_Mutex>

parametros_singleton;

En este caso el Singleton se encargará auto-máticamente de sincronizar los accesosdesde múltiples threads. Como nuestra apli-cación tendrá un sólo thread no utilizaremosmecanismo de exclusión mutua.Una vez que hemos creado la claseSingleton veremos como podemos utilizar-la en un programa de prueba. El acceso a laúnica instancia del Singleton se efectúa através de un método llamado “instance()”que devuelve un puntero a una instancia dela clase que el Singleton está encapsulando.El programa de ejemplo invoca dos veces ala función “instance()” y compara los resul-tados devueltos para verificar que se tratade la misma instancia (véase el listado 7).La penúltima línea de la función “main”está comentada. Esta línea intenta crearuna instancia de la clase parametros demanera directa por medio de “new”. Si qui-tamos las barras de comentario de estalínea e intentamos compilar ese código, elcompilador nos devolverá un error porquela clase “parametros” no tiene ningún cons-tructor público. Por eso para que la clase“ACE_Singleton” pueda crear instancias hasido declarada como friend.

Acceptor-ConnectorEste patrón se aplica en servicios que debencooperar y se encuentran distribuidos en dis-tintas máquinas. Para poder trabajar en con-junto deberán establecer una conexión de redentre si y el objetivo de este patrón es permi-tir separar la lógica requerida para establecerlas conexiones de la lógica que realiza las tare-as reales del servicio o lógica de aplicación. Los roles de una aplicación que utiliza unaconexión de red pueden dividirse en dos:� Rol de conexión: Determina el papel que

juega en el establecimiento de una cone-

xión. Puede ser un papel activo (el quesolicita la conexión) llamado Connector oun papel pasivo (el que está escuchandoa la espera de peticiones) llamadoAcceptor.

� Rol de comunicación: Determina si elcomponente cumple el papel de servidoro de cliente (o ambos) durante la utiliza-ción de la conexión.

La aplicación de este patrón separa clara-mente los dos tipos de roles. Además, unavez escrito el código para establecer unaconexión (ya sea de manera activa o pasi-va) es muy poco probable que éste cam-bie. Por el contrario, el código relacionadocon el rol de comunicación seguramentedeberá evolucionar con el tiempo y éstaevolución se verá simplificada por elpatrón Acceptor-Connector. La lógica detrabajo del componente se implementa enun Service Handler o Gestor de Servicios.También es importante destacar que sibien este artículo se refiere a la aplicaciónde este patrón en conexiones de red porser el ejemplo más claro y fácil de com-prender, el mismo puede aplicarse a cual-quier tipo de comunicación entre proce-sos y ACE provee la flexibilidad parahacerlo.La clase “ACE_Svc_Service_Handler” proveela base para implementar el código delcomportamiento de la aplicación. Esta esuna clase template cuyos parámetros son eltipo de Stream (o corriente de datos) que seutilizará para conectarse con el componen-

te remoto y el mecanismo de sincroniza-ción de threads a utilizar. Si quisiéramosimplementar el servidor echo de la primeraentrega de esta serie usando este patrón,comenzaríamos por declarar la clase han-dler del servicio:class echo_svc_handler : public

ACE_Svc_Handler<ACE_SOCK_Stream,

ACE_INET_Addr, ACE_NULL_SYNCH>{

public:

int svc ();

};

Esta clase hereda de la clase “ACE_Svc_Handler”. El parámetro “ACE_SOCK_Stream” de la clase template indica que losdatos hacia el otro extremo de la conexión seenviarán a través de un objeto de esa clase,“ACE_INET_Adrr” describe el tipo de direc-ción que identificará el otro extremo de laconexión y el parámetro “ACE_NULL_SYNCH” sirve para indicar que no se ha dehacer ningún control de sincronización dethreads. Para la implementación del com-portamiento de la clase, sólo necesitamossobrescribir el método virtual “svc()” de“ACE_Svc_Handler” de la manera en que semuestra en el listado 8.Hay varios métodos de “ACE_Svc_Handler”que podemos sobrescribir:� open(): Inicialización del servicio.� svc(): Ejecuta el trabajo del servicio.� close(): Finalización de las tareas del

servicio.

58

DISEÑO

http://digital.revistasprofesionales.com

LISTADO 7 main.cpp

#include “parametros.hpp”#include <string>#include <iostream>

int main(int argc, char* argv[]){parametros * ptr1=parametros_singleton::instance();parametros * ptr2=parametros_singleton::instance();if (ptr1==ptr2){

std::cout << “Ambos punteros apuntan al mismo objeto”<< std::endl;

}//ptr1=new parametros();return 0;

}

LISTADO 8 Sobrescribiendo el método svc()

int echo_svc_handler::svc () { char buffer[4096];ssize_t bytes_received;while ((bytes_received = peer().recv(buffer, sizeof(buffer))) > 0) {

std::string recibido(buffer,bytes_received);std::cout << recibido.c_str() << std::endl;peer().send_n (buffer, bytes_received);

}peer().close ();return 0;

}

Page 54: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

En la documentación de ACE podemosencontrar un detalle de todos los métodosdisponibles. Para acceder al stream que noscomunica con el otro extremo de la conexiónusamos la función “peer()” de la clase“ACE_Svc_Handler”, que nos devuelve unareferencia a un objeto de tipo “ACE_SOCK_Stream” o más precisamente del tipo espe-cificado como primer parámetro de la clasetemplate. A diferencia del ejemplo de la pri-mera entrega, en este servidor echo no apa-rece el código relacionado con aceptar yestablecer la conexión mezclado con el códi-go necesario para que el servidor haga sutrabajo lo cual mejora la separación de res-ponsabilidades.Por último debemos escribir el código paraque nuestro servidor echo comience a escu-char y acepte conexiones. Este código seríasimilar al siguiente:typedef

ACE_Acceptor<echo_svc_handler,

ACE_SOCK_ACCEPTOR> echo_acceptor;

ACE_INET_Addr port_to_listen(7);

echo_acceptor acceptor(port_to_listen);

Al recibir una dirección en su constructorel acceptor comienza inmediatamente aescuchar en ella. Por cada petición que elacceptor reciba, crea una instancia de laclase “echo_svc_handler” e invoca almétodo “svc()”. De esta manera, habrá unainstancia independiente para gestionarcada petición, eso sí, todas en el mismothread. El código explicado en este ejemploes mucho más limpio y elegante aún que elde la primera entrega, que ya representabauna mejora significativa sobre el métodode programación estándar. He aquí la utili-dad de los patrones de diseño.

ReactorEl patrón de diseño Reactor simplifica eldesarrollo de aplicaciones orientadas aeventos. Estos eventos pueden ser dispara-dos por señales del sistema operativo,algún mecanismo de comunicación entreprocesos (también conocidos como IPC porsus siglas en inglés) o simplemente por elpaso del tiempo.Así como el objetivo del patrón Acceptor-Connector es separar la responsabilidad deestablecer la conexión de red del código detrabajo de la aplicación, el patrón Reactortiene como principal objetivo separar códigoque detecta la ocurrencia del evento deseadodel código de trabajo de la aplicación. Estosaspectos están encapsulados por las clases“ACE_Reactor” y “ACE_Event_Handler” res-pectivamente.

La clase abstracta “ACE_Reactor” proveeuna interfaz portable para un conjunto desubclases que encapsulan llamadas a fun-ciones como “WaitForMultipleObjects()” deWindows o “select()” de Unix, logrando deesta manera una implementación comple-tamente multiplataforma de este patrónde diseño. Un “ACE_Reactor” monitoreaalgún evento determinado y mantiene unalista de objetos interesados en ser notifi-cados cuando el mismo ocurra. La clasereactor se encarga de notificar a todos losobjetos interesados cuando ocurre elevento. Los objetos de esta lista deben serde una clase derivada de “ACE_Event_Handler”. Disponemos de varias funcio-nes para gestionar la lista de “event han-dlers” registrados:� register_handler(): Permite agregar un

handler a la lista.� remove_handler(): Permite eliminar un

handler de la lista.� suspend_handler(): Permite detener

temporalmente el envío de notificacionesa un handler determinado.

� resume_hander(): Reinicia el envío denotificaciones a un handler suspendido.

Hay 3 subclases concretas de la clase“ACE_Reactor”:� ACE_Select_Reactor encapsula el uso

de la función “select()” de Unix.� ACE_WFMO_Reactor encapsula la fun-

ción “WaitForMultipleObjects()”.� ACE_TP_Reactor() permite extender el

patrón a un pool de threads.La función “handle_events()” hace que elreactor comience a monitorear el eventoseleccionado. Como ya hemos mencionado el códigoespecífico de la aplicación es encapsulado

por una subclase de “ACE_Event_Handler”.Esta clase base define métodos virtualescuyo nombre comienza con “handle_” yque deben ser anulados en la subclasepara implementar el comportamientorequerido:� handle_input(): Se utiliza cuando el

reactor moniterea una conexión de red ala espera de datos.

� handle_signal(): Se utiliza cuando el reac-tor monitorea una señal del sistema opera-tivo como con “WaitForMultipleObjects()”por ejemplo.

� handle_close(): Sirve para colocar aquíel código necesario para liberar cualquierrecurso que el event handler tuviera enuso.

� handle_timeout(): Es llamado cuando elreactor está monitoreando un temporiza-dor y ocurre cuando el temporizadoralcanza el tiempo indicado.

Conclusiones

A lo largo de estas tres entregas hemoscubierto una parte de la funcionalidad deACE. Esta librería no sólo posee un excelentediseño de arquitectura sino que nos facilitala creación de un diseño igual de bueno ennuestro propio código. Un buen diseño, fle-xible y claro, debería ser siempre uno denuestros objetivos a la hora de diseñar unaaplicación. ACE es además muy eficiente ycompatible con una amplia variedad decompiladores y sistemas operativos. Estoagregado a la enorme cantidad de funciona-lidad que provee la convierte en una opciónideal para la implementación de aplicacionesen las cuales la independencia de la plata-forma es una necesidad.

59

DISEÑODiseño multiplataforma para aplicaciones C++ (y III)

http://digital.revistasprofesionales.com

Documentación de la clase “ACE_Reactor”.

Page 55: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

En una aplicación en C/C++ para Windows,¿existe alguna forma de hacer que se llamea una función con un retardo determinado,sin necesidad de utilizar threads o procesos?

En el API de Windows existe la función “SetTimer”,la cual permite establecer un temporizador. Estemecanismo puede emplearse precisamente parahacer que la llamada a una función se ejecute conun cierto retardo. Por ejemplo:SetTimer(hwnd, IDT_TIMER1, 5000, NULL);

La llamada anterior recibe cuatro parámetros.El primero es el manejador de la ventana prin-cipal de la aplicación. El segundo es una cons-tante “define” que permite identificar al tem-porizador. El tercer parámetro indica el núme-ro de milisegundos que transcurrirán antes deque salte el temporizador. Finalmente, el últi-mo parámetro es un puntero a la función res-ponsable de procesar los mensajes del tempo-rizador. Cuando este parámetro es “NULL” losmensajes llegan al procedimiento de ventanaprincipal de la aplicación.Cada vez que el temporizador salta el siste-ma hace llegar a la función de procesamien-to un mensaje del tipo “WM_TIMER”. El pará-metro “wParam” del mensaje representa elidentificador del temporizador y el paráme-tro “lParam” es un puntero a la función deprocesamiento que se pasó como paráme-tro. Así por ejemplo si el procedimiento de

ventana principal de la aplicación se definede la siguiente manera:LRESULT CALLBACK WindowProcedure

(

HWND hwnd,

UINT uMsg,

WPARAM wParam,

LPARAM lParam

)

{

...

}

Los mensajes procedentes de los temporiza-dores pueden procesarse tal y como semuestra a continuación:switch (uMsg) {

...

case WM_TIMER:

{

if (wParam==IDT_TIMER1) {

KillTimer(hwnd, IDT_TIMER1);

...

}

}

}

Estoy desarrollando un Applet firmado queemplea un componente “JFileChooser” paraque el usuario pueda salvar unos ficheros yme gustaría poder personalizar el compo-nente para que algunos botones no salieran,o salieran con los iconos que yo quiero, etc.He estado revisando el API y no encuentroningún método que me permita hacer estascosas, ¿es posible?

En principio la capacidad de personalizacióndel componente “JFileChooser” es bastantelimitada en lo que al API se refiere. No obstan-te sí que existe un buen número de propieda-des que puedes establecer empleando la clase“UIManager”. Esta clase sirve, entre otrasmuchas cosas, para fijar las características rela-tivas al aspecto, y en algunos casos incluso alcomportamiento de los componentes que seemplean en una aplicación o Applet Java. La

60

DUDAS

Preguntas y respuestasPreguntas y respuestasADOLFO ALADRO GARCÍA

http://digital.revistasprofesionales.com

Características de los componentes de una interfazPropiedad Objeto

FileChooser.ancestorInputMap InputMapFileChooser.cancelButtonMnemonic Integer

FileChooser.detailsViewIcon IconFileChooser.directoryOpenButtonMnemonic Integer

FileChooser.helpButtonMnemonic IntegerFileChooser.homeFolderIcon Integer

FileChooser.listViewIcon IconFileChooser.newFolderIcon Icon

FileChooser.openButtonMnemonic IconFileChooser.saveButtonMnemonic Integer

FileChooser.upFolderIcon IntegerFileChooser.updateButtonMnemonic Icon

FileView.computerIcon IntegerFileView.directoryIcon Icon

FileView.fileIcon IconFileView.floppyDriveIcon Icon

FileView.hardDrive Icon

Documentación de la función “SetTimer”(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/timers/timerreference/timerfunctions/settimer.asp).

Page 56: Revista Solo Programadores #124

¿Luchas contra el caos?…ahora puedes solucionarlo !!

Consigue por sólo 6 euros un archivador de revistas valorado en 5,41 eurosy un archivador de cd’s valorado en 4,20 euros.Haz tu pedido llamando al teléfono 91 304 87 64, por fax al 91 327 13 03o por correo electrónico a [email protected],indicando tus datos personales y la forma de pago (giro postal, domiciliación bancaria,tarjeta de crédito o contrareembolso*).

REVISTAS PROFESIONALES - C/ Valentín Beato, 42 - 3ª plta. - 28037 Madrid*en opción contrareembolso se cobrará un suplemento de 5 euros por gastos de envío

En opción domiciliación bancaria, se ruega aporten los datos completos de la entidad bancaria (nombre, dirección y número de cuenta completo)

Page 57: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

tabla “Características de los componentes deuna interfaz” muestra un resumen de esto.La primera columna contiene el nombre de lapropiedad y la segunda el tipo de objeto queespera recibir. Obsérvese también que el primergrupo de propiedades se refieren al componente“JFileChooser” propiamente dicho, mientras queel segundo grupo se refieren no a un componen-te sino a la clase “FileSystemView”, que es la quese emplea para mostrar los directorios y ficherosdentro de un componente “JFileChooser”.El método “put” de la clase “UIManager” sedefine como sigue:public static Object put(Object key,

Object value)

El primer parámetro es un objeto que sirvepara identificar la propiedad que se deseaestablecer, y el segundo es otro objeto conel valor de dicha propiedad. Así por ejem-plo, si antes de crear una instancia delcomponente “JFileChooser” se ejecuta unalínea como la que sigue:UIManager.put

(

“FileChooser.detailsViewIcon”,

new ImageIcon(“my_detailsviewicon.gif”);

);

El icono que aparecerá en el botón de deta-lles del componente será el correspondientea la imagen “my_detailsviewicon.gif”.

Con el mecanismo descrito anteriormente sepueden personalizar algunos aspectos de laapariencia de un componente “JFileChooser”pero realmente no se pueden hacer cosastales como eliminar uno de los botones. Paraeste tipo de tareas tampoco existen métodosen el API. La única solución pasa por“deconstruir” el componente paso a paso,hasta dar con todos los componentes que asu vez forman parte de él, y entonces llevara cabo la personalización que sea necesaria.El método del listado 1 permite explorar todoslos componentes que forman parte de uncomponente dado. El primer parámetro repre-senta el componente a explorar y el segundoparámetro es un objeto de tipo “ArrayList”donde se irán almacenando las referencias detodos los componentes encontrados.En primer lugar se añade a la lista el compo-nente que se pasa como parámetro. Si esecomponente es una instancia de la clase“Container” entonces significa que puedecontener otros componentes. La colecciónde componentes que contiene se obtieneempleando el método “getComponents”.Esta colección se recorre y se llama recursi-vamente de nuevo a la misma función paracada uno de los elementos.Si se emplea esta función haciendo:JFileChooser jFileChooser = new JFileChooser();

ArrayList alComponents = new ArrayList();

getComponents(jFileChooser, alComponents);

Y posteriormente se muestra la lista de lasiguiente forma:int iSize = alComponents.size();

for (int i=0; i<iSize; i++) {

Component component = (Component)

alComponents.get(i);

System.err.println(component);

}

Se obtiene una lista de todos los componen-tes que forman parte de un objeto de tipo“JFileChooser”. Esta lista tiene el siguienteaspecto:javax.swing.JFileChooser[...]

javax.swing.JPanel[...]

javax.swing.JPanel[...]

javax.swing.JButton[...]

javax.swing.Box$Filler[...]

...

Evidentemente, una vez que se tiene accesoa cada uno de los componentes individuales,se pueden hacer cualquier tipo de cambios,como por ejemplo el que se muestra en ellistado 2.En este ejemplo se parte del supuesto que seestá empleando el look&feel llamado“metal”. Si la clase del icono que emplean unbotón contiene la cadena de texto “MetalIconFactory$FileChooserDetailViewIcon”significa que se trata del botón de detalles yentonces se elimina del componente sim-plemente utilizando el método “remove” desu padre.Finalmente, este mecanismo es tan potentecomo peligroso ya que en realidad se estánaccediendo a las propiedades internas de uncomponente “JFileChooser”, lo que significaque no sólo podemos cambiarlo sino queademás podemos hacer que deje de funcio-nar correctamente.

62

DUDAS

http://digital.revistasprofesionales.com

LISTADO 1 Explorando componentes

public static void getComponents(Component component, ArrayList alComponents){

alComponents.add(component);

if (component instanceof Container) {Container container = (Container)component;Component[] components = container.getComponents();if (components!=null) {

int iComponentsLength = components.length;if (iComponentsLength>0) {

for(int i=0; i<iComponentsLength; i++) {getComponents(components[i], alComponents);

}}

}}

}

LISTADO 2 Cambios en los componentes

if (component instanceof AbstractButton) {Icon icon = ((AbstractButton)component).getIcon();if (icon!=null) {

String sIconClassName = icon.getClass().getName();if (sIconClassName.indexOf(“MetalIconFactory$FileChooserDetailViewIcon”)!=-1) {

component.getParent().remove(component);}

}}

Aspecto de un componente “JFileChooser”al que se le ha eliminado el botón dedetalles.

Page 58: Revista Solo Programadores #124

LIBROS

http://digital.revistasprofesionales.comSOLO PROGRAMADORES nº 124 64

PHP y MySQL son conocidas tecnologías de códi-go abierto que resultan muy útiles para diseñar deforma rápida y eficaz aplicaciones web dirigidas abases de datos. Como el lector sabrá, PHP es unpotente lenguaje de secuencia de comandos dise-ñado específicamente para crear aplicaciones web

con distintas prestaciones de forma rápida y segu-ra. MySQL es una base de datos rápida y fiable quese integra a la perfección con PHP y que resultamuy adecuada para aplicaciones dinámicas basa-das en Internet.Este libro enseña a utilizar estas herramientas deforma conjunta para obtener aplicaciones web efi-caces e interactivas, desde los formularios de pedi-dos más sencillos hasta los sitios de comercioelectrónico más complejos y seguros.Los temas tratados en esta obra podrían resumir-se en el diseño de bases de datos, creación desitios de comercio electrónico, construcción de uncarrito de la compra, creación de gestores de listasde correo, creación de foros web, generación diná-mica de documentos PDF etc.

Desarrollo web con PHP y MySQLAUTORES: Luke Welling, Laura ThomsonEDITORIAL: ANAYAISBN: 84-415-1569-7PÁGINAS: 911LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2003IDIOMA: CastellanoOBSERVACIONES: Incluye CD-ROM con el código fuentede los ejemplos y herramientas para el desarrollo

El principal objetivo de este libro es ofrecer unapequeña muestra de lo que un diseñador webpuede realizar con la ayuda de PHP, Apache yMySQL. Esta obra pretende guiar en la creación desitios web utilizando el modelo AMP (Apache,MySQL y PHP) de código abierto. El lector apren-

derá a instalar PHP, Apache y MySQL, aprenderá acrear páginas web con PHP, aprenderá a adminis-trar y a proteger bases de datos y, por último,aprenderá a integrar sus creaciones en platafor-mas de comercio electrónico con otras tecnologí-as. Cuando el lector haya terminado, podrá crearsitios web dinámicos y bien diseñados con laayuda de herramientas de código abierto.A modo de resumen, diremos que los temas queaborda esta libro son el lenguaje PHP, cómo acce-der a una base de datos, creación de formularios,formas de permitir a los usuarios el acceso a lainformación de la base de datos, creación de apli-caciones de comercio electrónico, etc.

Desarrollo con PHP, Apache y MySQLAUTORES: Michael K. Glass, Yann Le Scouarnec, ElizabethNaramore, Gary Mailer, Jeremy Stolz, Jason GernerEDITORIAL: ANAYAISBN: 84-415-1755-XPÁGINAS: 704LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2004IDIOMA: Castellano

PHP se ha convertido en el estándar para la crea-ción de páginas de servidor y aplicaciones web,constituyendo la nueva versión la renovación másimportante de los últimos años. Este libro describe

todas las novedades que incorpora PHP y demues-tra su uso en la práctica, con proyectos reales denivel profesional.Los primeros capítulos del libro ayudarán al lectora instalar PHP 5 sobre windows, GNU/Linux y MacOS X, ya sea con Apache 1.3, Apache 2.0 o InternetInformation Server. Después, capítulo a capítulo, ellector irá configurando las extensiones necesariaspara cada tipo de proyecto.Los temas que aborda este libro se centran en elestudio de la sintaxis de PHP 5, acceso a bases dedatos, uso de cookies, XML y SOAP para la crea-ción de servicios web con PHP, creación de unservicio de chat, generación de informes, etc.

PHP 5AUTOR: Francisco Charte OjedaEDITORIAL: ANAYAISBN: 84-415-1770-3PÁGINAS: 655LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2004IDIOMA: CastellanoOBSERVACIONES: Incluye CD-ROM con el software nece-sario para llevar a cabo proyectos en PHP 5 sobre diferentessistemas operativos

Desarrollo web con PHPDesarrollo web con PHP

Page 59: Revista Solo Programadores #124

SOLO PROGRAMADORES nº 124

Fuentes

Juegos de calidad comercial en J2ME (III)El lector estará notando, después de leer estatercera entrega del curso sobre programaciónavanzada sobre móviles Nokia, que realmentese puede hacer todo o casi todo desde unaaplicación J2ME si se conoce el API del termi-nal destino. El CD-ROM incluye, en este apar-tado, códigos de ejemplo para manejar la luzde la pantalla, la vibración del teléfono, lacámara de fotos, el sonido, etc.

Programación distribuida en .NET (II)En esta segunda entrega sobre programacióndistribuida en .NET nos hemos centrado en lasolución .NET Remoting. El lector encontraráen el CD-ROM, en la sección dedicada a esteartículo, los ejemplos que se han ido comen-tando así como las instrucciones para sucompilación y ejecución.

XAML (IV)A estas alturas, y después de 4 entregas sobreXAML, podríamos decir que ya casi somosunos expertos. Los ejemplos propuestos eneste punto ilustran cómo conformar interfa-ces gráficas XAML obteniendo la informaciónde distintos orígenes de datos.

Sistemas de mensajería con Java Message Service (I)Esta primera entrega ha servido para introduciral lector en el mundo de la mensajería y, concre-tamente, a la API JMS. El ejemplo que se incluyeen esta sección del CD-ROM es de lo más ilus-trativo, además se ofrecen distintas formas deejecución del mismo: Importando el proyectodesde Eclipse, con Ant o por línea de comandos.

Diseño multiplataforma para aplicaciones C++ (y III)Seguramente el lector, antes de leer este artículo,desconocía cómo hacer un programa C++ quetrabajara con el sistema de ficheros (listandodirectorios, borrando ficheros, etc.) y que dichoprograma fuera compilable en distintas platafor-mas (Windows, Linux, etc.). Los ejemplos ofreci-dos en este punto demuestran cómo hacer esto,y además nos enseñan a implementar el patrónde diseño Singleton con la librería ACE.

Programación

OpenJMS 0.7.6.1Este es el servidor de mensajería utilizado en laserie de artículos “Sistemas de mensajería conJava Message Service”. OpenJMS proporcionauna implementación del API JMS robusta yprofesional, es de fácil instalación y es libre.

Aspect# 2.1.0.0La Programación Orientada a Aspectos, pese aser desconocida por muchos, en realidad yaestá al orden del día, y en este sentido hemosquerido acercar este mundo al lector. Aspect#es un framework que permite programar bajoeste paradigma a los programadores C#.

Yet Another Forum.net 0.9.9Para quienes estén desarrollando un portal conASP.NET, puede ser de gran ayuda un recursocomo YAF. Este paquete de software contieneuna implementación completa de un foro dediscusión escrito en ASP.NET, C# y con SQLServer. La idea es que cualquiera debería poderincluir en su portal web ASP.NET este foro demanera directa.

NHibernate 0.7.0.0NHibernate es la alternativa a Hibernate en elmundo .NET. Como el lector sabrá, puesto queen el número 120 de Sólo Programadores fueobjeto de estudio, Hibernate es la soluciónpara la persistencia de objetos en BBDD rela-cionales del mundo Java. Por su parte,NHibernate es su homólogo del mundo .NET.

JSP Standard Tag Library 1.1El desarrollo con la tecnología JSP ha sidomuchas veces criticado por producir códigomuy poco legible, mantenible y elegante, almezclar código Java con lenguaje de marcasHTML. JSTL pretende ofrecer una solución aeste problema, ya que permite tener por unlado el código de la presentación y por otrolado el código de la lógica de negocio.

OpenSTA 1.4.2Conocer los niveles de carga de trabajo yestrés que nuestra aplicación web puedesoportar es útil para detectar, en última ins-tancia, los puntos débiles o los cuellos debotella. OpenSTA es un avanzado sistema quenos permite definir un script con la navega-ción deseada, y luego aplicar fuertes cargas detrabajo contra nuestro site.

NUnit 2.2.0NUnit debería ser una herramienta de interéspara aquellos programadores .NET que quie-ran hacer pruebas extremas sobre el códigoque escriben.

Log4J 1.2.9Log4J es una aplica-ción que permite ges-tionar de forma ele-gante, mediante ficherosde configuración externos, los tan famosos“printf” (o la instrucción de turno para escribirpor la salida estándar) que nos ayudan, en tiem-po de desarrollo y pruebas, a controlar la ejecu-ción de nuestro programa.

Remoting.Corba 1.3.1Tal como se ha descrito en el artículo“Programación distribuida en .NET (II)”,Remoting.Corba permite agregar a nuestroentorno .NET la capacidad de comunicarsecon objetos mediante CORBA.

Joda-Time 1.0Este producto ha sido presentado en la sec-ción de la comunidad javaHispano. Su objeti-vo es ofrecer a la comunidad Java una libreríaque haga más sencilla y eficiente la gestión dela fecha y la hora desde aplicaciones Java.

66

CD-ROM

http://digital.revistasprofesionales.com

Contenido del CD-ROMContenido del CD-ROM